Show TimeSpan on Value Axis in Kendo Chart - asp.net-mvc

I want to show TimeSpan values on my Value axis. Chart is working fine for numeric but if I change to TimeSpan nothing is showing. I checked the data and it's ok. If TimeSpan is not supported is there a way to format minutes in int values to be shown as Time (ie ,,6h 34 min")
Here is my chart:
#(Html.Kendo().Chart<MachineWorkTimeChartViewModel>()
.Name("chartMachineWorkTime")
.DataSource(ds => ds.Read(read => read.Action("MachineWorkTimeChart_Read", "Charts")
.ChartArea(chartArea => chartArea
.Background("transparent")
)
.Series(series =>
{
series.Bar(e => e.WorkTimeSpan).Name("Time of work");
})
.CategoryAxis(axis => axis
.Name("label-axis")
.Categories(e => e.MachineName)
.Line(line => line.Visible(false))
)
)
and here is my ViewModel:
public class MachineWorkTimeChartViewModel
{
public int WorkMinutes { get; set; }
public string MachineName { get; set; }
public TimeSpan WorkTimeSpan => TimeSpan.FromMinutes(WorkMinutes);
}

Based on your answer ezanker and modified js function from jgritty link
I got it to work (I didn't want to use an external js library).
Here is full example:
#(Html.Kendo().Chart<MachineWorkTimeChartViewModel>()
.Name("chartMachineWorkTime")
.DataSource(ds => ds.Read(read => read.Action("MachineWorkTimeChart_Read", "Charts")
.ChartArea(chartArea => chartArea
.Background("transparent")
)
.Series(series =>
{
series.Bar(e => e.WorkMinutes).Name("Time of work");
})
.CategoryAxis(axis => axis
.Name("series-axis")
.Line(line => line.Visible(false))
)
.CategoryAxis(axis => axis
.Name("label-axis")
.Categories(e => e.MachineName)
)
.ValueAxis(axis => axis
.Numeric()
.Labels(labels => labels.Format("{0} min.")
.Template("#= getTimeSpanFromMinutes(value) #"))
// Move the label-axis all the way down the value axis
.AxisCrossingValue(0, int.MinValue)
)
.Tooltip(tooltip => tooltip
.Visible(true)
.Format("{0}%")
.Template("#= getTimeSpanFromMinutes(value) #")
))
<script>
function getTimeSpanFromMinutes(newMinutes) {
var minsPerYear = 24 * 365 * 60;
var minsPerMonth = 24 * 30 * 60;
var minsPerWeek = 24 * 7 * 60;
var minsPerDay = 24 * 60;
var minsPerHour = 60;
var minutes = newMinutes;
var years = Math.floor(minutes / minsPerYear);
minutes = minutes - years * minsPerYear;
var months = Math.floor(minutes / minsPerMonth);
minutes = minutes - months * minsPerMonth;
var weeks = Math.floor(minutes / minsPerWeek);
minutes = minutes - weeks * minsPerWeek;
var days = Math.floor(minutes / minsPerDay);
minutes = minutes - days * minsPerDay;
var hours = Math.floor(minutes / minsPerHour);
minutes = minutes - hours * minsPerHour;
var timeSpan = "";
if (years > 0)
timeSpan += years + " years ";
if (months > 0)
timeSpan += months + " months ";
if (weeks > 0)
timeSpan += weeks + " weeks ";
if (days > 0)
timeSpan += weeks + " days ";
if (hours > 0)
timeSpan += hours + " hours ";
if (minutes > 0)
timeSpan += minutes + " min. ";
return timeSpan;
}</script>

Related

Angular date pipe shows NaN on iphone/ios after formatting date

I'm making a PWA on angular 8 / ionic 5. Users can create events and have them listed on a feed page. Problem is, that the date and the time of each event does not get displayed and gives the error "NaN" on iphones/iOS devices. Both date and time get their information from start_at which is the time in the format of "hh:mm:ss".
Following code shows how we receive the response data from our MySQL php laravel server for listing the events:
getTodos() {
console.log("arrived to gettodos");
var id = this.userInfo.id
this.todoService.getTodos('', '', '', id, false).subscribe(res => {
console.log("res", res);
console.log("frimes", res['frimes']);
// debugger;
// console.log(res);
if (res['code'] === 200) {
// console.log(res['data']);
const userFrimes: any[] = res['frimes'];
this.todos = [] as any[];
console.log(userFrimes);
if (userFrimes && userFrimes.length > 0) {
userFrimes.forEach(uf => {
var timeofFrime = this.formatAMPM(uf.start_at);
if (!this.todoService.isFrimeExpired(uf.start_at)) {
this.todos.push({
owner: this.userInfo.username,
title: uf.title,
message: uf.description,
date: uf.start_at,
time: timeofFrime,
max: uf.max,
guests: uf.member.length, //uf.guests == null ? 0 : uf.guests,
frime_id: uf.id,
status: uf.status,
user_id: uf.user_id
});
}
});
}
} else if (res['code'] === 205) {
} else if (res['code'] === 401) {
}
}, err => {
//this.errorMessage = err.message;
console.log(err);
});
}
here you can see that the properties date and time are being fetched for the formatAMPM() function and changed to the AM/PM date format.
formatAMPM(d) {
let dd = d + " UTC";
let date = new Date(dd);
var hours = date.getHours();
var minutes = date.getMinutes();
var ampm = hours >= 12 ? 'PM' : 'AM';
hours = hours % 12;
hours = hours ? hours : 12; // the hour '0' should be '12'
var min = minutes < 10 ? '0' + minutes : minutes;
var strTime = hours + ':' + min + ' ' + ampm;
return strTime;
}
here the final date string gets displayed in the pipe fields where it shows the "NaN" error on ios.
the error itself says:
ERROR Error: InvalidPipeArgument: 'Unable to convert "2021-05-19 17:15:38" into a date' for pipe 'Re'.
what does 'Re' mean btw?
<ion-col size="3" class="date-wrapper">
<h3 class="notification-date">
{{ item.date | date: "shortDate" }}
</h3>
<h3 class="notification-date">
{{ item.time | date: "HH:mm" }}
</h3>
<h3 class="notification-date">{{ item.guests + '/' + item.max }}</h3>
</ion-col>
hope you can help me fixing this, because this is giving me soooo many headachse lately...
thanks in advance!
ok i have fixed it by adding this line of code:
d = d.replace(" ", "T");
the date came in a format like dd-MM-yyyy HH:mm:ss and i needed to add the "T" so it is like dd-MM-yyyyTHH:mm:ss
formatAMPM(d) {
d = d.replace(" ", "T");
let dd = d + " UTC";
let date = new Date(dd);
var hours = date.getHours();
var minutes = date.getMinutes();
var ampm = hours >= 12 ? 'PM' : 'AM';
hours = hours % 12;
hours = hours ? hours : 12; // the hour '0' should be '12'
var min = minutes < 10 ? '0' + minutes : minutes;
var strTime = hours + ':' + min + ' ' + ampm;
return strTime;
}

Dart : Show the time until the next time

How to show a countdown time duration until the next alarm
Code:
TimeOfDay _nextSalah(List<SalahModel> salahs) {
DateTime now = DateTime.now();
List<TimeOfDay> times = [];
int currentSalah;
salahs.forEach((s) => times.add(s.time));
times.add(TimeOfDay(hour: now.hour, minute: now.minute));
times.sort((a, b) => a.hour.compareTo(b.hour));
currentSalah = times.indexWhere((time) => time.hour == now.hour);
return TimeOfDay(hour: times[currentSalah].hour, minute: times[currentSalah].minute);
}
But the time difference is wrong and it doesn't animate. Also how to make sure the time difference works when it's the same day and time of the next day i.e. now is Dec 1 2:30 PM and I want to get the difference on Dec 2 6:15 AM.
It does not work because TimeOfDay represents a time during the day, independent of the date that day might fall on or the time zone. The time is represented only by hour and minute.
If you want a countdown that spans multiple days a DateTime must be used and the time difference evaluation needs some math before formatting the result string, something like:
String nextTime(DateTime nextAlarmTime) {
List<int> ctime = [0, 0, 0, 0];
DateTime now = DateTime.now();
int diff = nextAlarmTime.difference(now).inSeconds;
ctime[0] = diff ~/ (24 * 60 * 60); // days
diff -= ctime[0] * 24 * 60 * 60;
ctime[1] = diff ~/ (60 * 60); // hours
diff -= ctime[1] * 60 * 60;
ctime[2] = diff ~/ 60; // minutes
ctime[3] = diff - ctime[2] * 60; // seconds
return ctime.map((val) => val.toString().padLeft(2, '0')).join(':');
}

Angular Directive to replace html not working on iOS

I have this piece of code:
(function() {
"use strict";
angular
.module("Default")
.directive(
"numberToTime",
["$rootScope", "$compile", "$log",
function($rootScope, $compile, $log) {
return {
"restrict": "A",
"transclude": true,
"replace": true,
"scope": {
"time": "="
},
"link": function(scope, ele, attrs) {
/**
* Function to add one serie of string to another untill complete
* certain length
*
*/
var _lpad = function(str, padString, length) {
while (str.length < length) {
str = padString + str;
}
return str;
};
/**
* Function to turn a number into time format
*/
var _2time = function(s, hideDays, hideSeconds) {
var d = Math.floor(s / (24 * 60 * 60));
s -= d * (24 * 60 * 60);
var h = Math.floor(s / (60 * 60));
s -= h * (60 * 60);
var m = Math.floor(s / 60);
s -= m * 60;
s = Math.floor(s);
var time = "";
if (!hideDays) {
time += d > 0 ? d + " day" + (d > 1 ? "s" : "") + ", " : "";
}
time += _lpad(h.toString(), '0', 2) + ":" + _lpad(m.toString(), '0', 2) + (hideSeconds ? "" : (":" + _lpad(s.toString(), '0', 2)));
return time;
};
var _setTime = function(time) {
var _time = _2time(time, attrs.hidedays != "false", attrs.hideseconds != "false");
ele.html(_time);
};
scope.$watch("time", function() {
_setTime(scope.time);
}, true);
}
};
}
]
)
;
})();
It works ok, if I have something like:
<span number-to-time time="time"></span>
where
$scope.time = 1234;
It turns that number into readable time format. However, in iOS it does not updates the html.
I have it in a player, and if I log the html() content of ele, it says it has the correct time, but in the page I still see 00:00:00, and the time does not updates correctly. What am I doing wrong?
FIXING
Instead of using .html use .text:
ele.text(_time);
Looks like your page is not being rendered. Instead of using html, use text.
var _setTime = function(time) {
var _time = _2time(time, attrs.hidedays != "false", attrs.hideseconds != "false");
ele.text(_time);
};
You can find more information here: http://bit.ly/1E4cMxG

How to create series and setup X and Y axis?

I have to make a series as shown in the image.
The Dates and the values are dynamically generating based on the user selection. The Time is in 24 hrs format. Please tell me how can i create the series for this. Also how to put the duration 1 hour for the time value.
Image for Reference:
In your series data you are using data: [Date.UTC(2012, 10, 01, 12,11,10)] you can simply change that to: data: [90 *60 * 1000] //For 90 Minute
Here is the LIVE DEMO
If you want to plot other series for other days then you should add categories in xAxies. for example for showing 3 days:
xAxis: {
categories: ['01/10/2012', '01/11/2012', '01/2/2012']
},
And in series-data use equal number of parameters as you have in your categories for 3 categories:
data: [ 50 *60 * 1000, 100 *60 * 1000, 50 *60 * 1000 ]
See the LIVE DEMO
Use formatter in tooltip to see a correct hour:minutes when you hover the series.
tooltip: {
formatter: function() {
var ms = this.y;
var x = ms / 1000;
var seconds = x % 60;
x = x / 60;
var minutes = x % 60;
x = x / 60;
var hours = parseInt(x % 24);
x = (x / 24);
var days = parseInt(x);
if(days == 0)
{
return '<b>' + this.series.name +'</b> ->' + this.x + '<br/>' + hours +':' + minutes;
} else {
return '<b>' + this.series.name +'</b><br/>' + days + ' Day ' + hours +':' + minutes;
}
}
},
See the LIVE DEMO

Convert string format to another date format

My string format is: M/d/yyyy h:m:s aa
Now, I want to change it in yyyy-MM-ddTHH:mm:ss format.
How can I change it in this format. Please tell me appropriate solution
The method getConvertedDate(String), will do a plain text parsing for conversion.
private String getConvertedDate(String inputDate) {
// extract and adjust Month
int index = inputDate.indexOf('/');
String month = inputDate.substring(0, index);
if (month.length() < 2) {
month = "0" + month;
}
// extract and adjust Day
inputDate = inputDate.substring(index + 1);
index = inputDate.indexOf('/');
String day = inputDate.substring(0, index);
if (day.length() < 2) {
day = "0" + day;
}
// extract Year
inputDate = inputDate.substring(index + 1);
index = inputDate.indexOf(' ');
String year = inputDate.substring(0, index);
// extract Hour
inputDate = inputDate.substring(index + 1);
index = inputDate.indexOf(':');
String hour = inputDate.substring(0, index);
// extract and adjust Minute
inputDate = inputDate.substring(index + 1);
index = inputDate.indexOf(':');
String minute = inputDate.substring(0, index);
if (minute.length() < 2) {
minute = "0" + minute;
}
// extract and adjust Second
inputDate = inputDate.substring(index + 1);
index = inputDate.indexOf(' ');
String second = inputDate.substring(0, index);
if (second.length() < 2) {
second = "0" + second;
}
// extract AM/PM marker
// adjust hour, +12 for PM
inputDate = inputDate.substring(index + 1);
String am_pm_marker = inputDate.substring(0);
if (am_pm_marker.equalsIgnoreCase("pm")) {
int hourValue = 0;
try {
hourValue = Integer.parseInt(hour);
} catch (Exception e) {
}
hourValue += 12;
hour = "" + hourValue;
if (hour.length() < 2) {
hour = "0" + hour;
}
} else {
if (hour.length() < 2) {
hour = "0" + hour;
}
}
String outputDate = year + "-" + month + "-" + day;
outputDate += "T" + hour + ":" + minute + ":" + second;
return outputDate;
}
Sample input and output:
String input = "04/01/2012 9:55:47 pm";
System.out.println("Output: " + getConvertedDate(input));
// Output: 2012-04-01T21:55:47
Date date = (Date)new SimpleDateFormat("M/d/yyyy h:m:s aa").parse(your_string_date);
String finalFormat = new SimpleDateFormat("yyyy-MM-ddTHH:mm:ss").format(date)
Basically the first SimpleDateFormat recognizes your original format and parses it into a Date. Then the second one formats the date object to what you need.
I don't have jdk around to test here, but it should work.
Check this links for format syntax in case something doesn't work:
http://docs.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html

Resources