Javascript time difference via timepicker - javascript

I'm working on a web timesheet where users use timepicker to determine start & end times and I'd like to have the form automatically find the difference between the two times and place it in a 3rd input box. I understand that I need to get the values, convert them to milliseconds, then subtract the first number from the second, convert the difference back to human time and display that in the third box. But I can't seem to wrap my head around time conversion in javascript. Here's what I have so far:
function date1math(){
var date1in = document.getElementById("date-1-in").value;
var date1out = document.getElementById("date-1-out").value;
date1in = date1in.split(":");
date1out = date1out.split(":");
var date1inDate = new Date(0, 0, 0, date1in[0], date1in[1], 0);
var date1outDate = new Date(0, 0, 0, date1out[0], date1out[1], 0);
var date1math = date1outDate.getTime() - date1inDate.getTime();
var hours = Math.floor(date1math / 1000 / 60 / 60);
date1math -= hours * 1000 * 60 * 60;
var minutes = Math.floor(date1math / 1000 / 60);
return (hours < 9 ? "0" : "") + hours + ":" + (minutes < 9 ? "0" : "") + minutes;
document.getElementById("date-1-subtotal").value = date1math(date1in, date1out);
}
I want to take the timepicker result (say 9:00am) from the input date-1-in, the timepicker result (say 5:00pm) from the input date-1-out, and then place the difference as a number in date-1-subtotal.

Presumably the input is a string in the format hh:mm (e.g. 09:54) and that the two strings represent a time on the same day. You don't mention whether an am/pm suffix is included, but it's there in the text so I'll assume it might be.
If daylight saving changes can be ignored, the simplest method is to convert the string to minutes, find the difference, then convert back to hours and minutes, e.g.:
// Convert hh:mm[am/pm] to minutes
function timeStringToMins(s) {
s = s.split(':');
s[0] = /m$/i.test(s[1]) && s[0] == 12? 0 : s[0];
return s[0]*60 + parseInt(s[1]) + (/pm$/i.test(s[1])? 720 : 0);
}
// Return difference between two times in hh:mm[am/pm] format as hh:mm
function getTimeDifference(t0, t1) {
// Small helper function to padd single digits
function z(n){return (n<10?'0':'') + n;}
// Get difference in minutes
var diff = timeStringToMins(t1) - timeStringToMins(t0);
// Format difference as hh:mm and return
return z(diff/60 | 0) + ':' + z(diff % 60);
}
var t0 = '09:15am';
var t1 = '05:00pm';
console.log(getTimeDifference('09:15am', '05:00pm')); // 07:45
console.log(getTimeDifference('09:15', '17:00')); // 07:45
If daylight saving is to be incorporated, you'll need to include the date so that date objects can be created and used for the time difference. The above can use either 12 or 24 hr time format.

Related

How to get timezone offset in javascript?

In javascript, I want to get my local timezone offset such as -04:00 as a string. How can I do this?
Thanks
You can use Date object for this task.
let offset = new Date().getTimezoneOffset()
Now you got a string like -120 you can format as you like. You can divide by 60 to get hours and then use + or push:
offset = (offset / 60) + ":00";
one line:
new Date().getTimezoneOffset() / 60 + ":00";
Edit: Since you seem having problems, i made you a code example you can test.
<html>
<body>
<script>
let offset = new Date().getTimezoneOffset() / 60;
if (offset >= 0 && offset < 10) {
offset = "0" + offset;
} else if (offset > -10) {
offset = "-0" + offset.toString().substr(1);
} else {
offset = "00";
}
offset += ":00";
alert(offset);
</script>
</body>
</html>
I'm not handling 00:XX in case those exists.
I'd created a function...
function timezone(date=new Date()) {
var timezoneOffset=date.getTimezoneOffset();
var sign=(timezoneOffset<0)?"+":"-";
var minutes=Math.abs(timezoneOffset);
var hours=Math.floor(minutes/60);
minutes=minutes-60*hours;
return sign+("0"+hours).slice(-2)+":"+("0"+minutes).slice(-2);
}
You can pass a Date object, if you don't, one will be created.
timezoneOffset is in integer minutes: East of GMT = negative, West = positive.
sign is the opposite of the offset.
minutes abs = we've already got the sign, let's deal with absolute value.
hours - whole number of multiples of 60 minutes.
minutes - reminder of what it was minus 60 times whole hours. Could be done with %, it's a matter of preference.
return -
sign is a string: "+" or "-"
("0"+hours) is now a string: 7 becomes "07", 11 becomes "011", that's why:
.slice(-2) return the last 2 characters: "07" returns just that, "011" returns "11".
same for minutes.
and a ":" between.
You can test on different timezoneOffset values manually by replacing date.getTimezoneOffset() with a number.
Here's a possible solution:
const date = new Date()
const offset = date.getTimezoneOffset()
const sign = offset >= 0 ? '-' : '+'
const hours = Math.abs(offset / 60)
const minutes = Math.abs(offset % 60)
const hoursStr = `0${hours}`.slice(0, 2)
const minutesStr = `0${minutes}`.slice(0, 2)
console.log(`${sign}${hoursStr}:${minutesStr}`)
Note that not all timezones end at hours. Some countries use half hour timezones, like +03:30.
This seems to work...
function getTimeZoneOffset() {
var t = new Date().toString().match(/[-\+]\d{4}/)[0];
return t.substring(0,3) + ":" + t.substr(3);
}
Here's my solution. Rather then do your own division to get the hours, just use the functionality already in the date object:
const date = new Date();
const tzOffsetNumber = date.getTimezoneOffset();
const tzDate = new Date(0,0,0,0,Math.abs(tzOffsetNumber));
console.log(`${ tzOffsetNumber > 0 ? '-' : '+'}${tzDate.getHours()}:${("" + tzDate.getMinutes()).padStart(2,'0')}`)

Converting to duration from milliseconds

I am trying to convert time duration from the format of mm:ss.mss to entirely milliseconds and back.
I've already have a working function for converting from milliseconds to duration but I cannot seem to get it the other way around.
Lets say for instance that I have the duration 32:29.060, I want to convert it to milliseconds. For that I use this function:
function millisecondsToTime(ms, digits) {
digits = digits || 12;
return new Date(ms).toISOString().slice(23-digits, -1);
}
var a = millisecondsToTime(5549060, 9);
but whenever I try to convert back to time duration, I fail. I've tried parsing individually the minutes, seconds and milliseconds but it doesn't seem to work.
Here is the code that I've used for it:
var firstSplit = a.split(':')
var minutes = firstSplit[0]; //1
var secondSplit = firstSplit[1].split('.');
var seconds = secondSplit[0]; //2
var millisec = secondSplit[1]; //3
var conversion = ((+minutes) * 60 + (+seconds) * 60 + (+millisec))*1000;
I have an input bar which takes the format of mm:ss.mss and I need to convert it to milliseconds. How can I do that?
you can just return a
new Date(ms)
to get a date from ms.
And to get the same date as ms,
date.getTime() // returns ms from date object
Full example:
const ms = 5549060
const date = new Date(ms) // get a date from ms
console.log(date.getTime) // logs 5569060
If your input is a string in the format of mm:ss.mss, and you want to get a date from it, you can use moment.
const moment = require('moment')
const date = moment('22:15.143', 'mm:ss.SSS') // get date from pre specified format
You can use the string methods indexOf() and substr() to get the individual numbers out of your string and calculate the time accordingly.
I'm afraid though your millisecondsToTime() function isn't working properly.
5549060 milliseconds are roughly 92 minutes and it's returning 32:29.060
function backToTime(time) {
var index = time.indexOf(":");
var minutes = time.substr(0, index);
var seconds = time.substr(index + 1, time.indexOf(".") - (index + 1));
var milliseconds = time.substr(time.indexOf(".") + 1, time.length);
return parseInt(minutes * 60 * 1000) + parseInt(seconds * 1000) + parseInt(milliseconds);
}
console.log(backToTime("32:29.060"));
Your conversion to milliseconds is not working, this is basic math approach to both conversions:
let input = 5549060
//toDuration
let seconds = Math.floor(input / 1000);
let ms = input - seconds*1000;
let m = Math.floor(seconds / 60);
let s = seconds - m*60;
duration = m + ":" + s + "." + ms
console.log(duration)
//toMilliseconds
let holder = duration.split(":");
m = parseInt(holder[0]);
holder = holder[1].split(".");
s = parseInt(holder[0]);
ms = parseInt(holder[1]);
milliseconds = (m*60 + s)*1000 + ms
console.log(milliseconds)
If needed add check for ms length to add 0s, if you need it to have length of 3
I think your milliseconds to duration converter will be broken for durations above 60 minutes. This is because using Date the minutes field will wrap over into the minutes after 59 seconds have passed. If you want to get good support for values beyond 59 in your first field, I think maybe moving to a regex-based parser and using multiplication and addition, division and modulo to extract and reduce the fields manually might be nice. Something like this maybe:
var duration = ms => `${(ms / 60000) | 0}`.padStart(2, '0') + `:` + `${ms % 60000 / 1000 | 0}`.padStart(2, '0') + `.` + `${ms % 1000}`.padStart(3, '0')
var millisec = durat => (match => match && Number(match[1]) * 60000 + Number(match[2]) * 1000 + Number(match[3]))(/^([0-9]+)\:([0-5][0-9])\.([0-9]{3})$/.exec(durat))
You can see given the input 5549060, this function provides output 92:29.60, which is exactly 60 seconds greater than your own, and I believe to be correct. Maybe it's intentional for your usecase, but I can't imagine that being so desirable generally...

How can I format time durations exactly using Moment.js?

I would like to do the following, given two dates in UTC formatting:
var start = "2014-01-13T06:00:00.0000000Z";
var end = "2014-01-13T14:16:04.0000000Z";
I would like to get the exact time span that passes between these two times, such as
8h 16m
I have tried using the following:
var duration = moment(moment(end) - moment(start)).format('hh[h] mm[m]');
But this does not work with days. Moreover, it does not work with days, since they are always >=1 even if <24 hours pass.
I have also tried twix.js to get the length, but its formatting doesn't support creating the format specified above, or I could not find the way to do so in its documentation. Basically I am looking for an exact version of twix.humanizeLength().
Moment.js's a.diff(b) provides only total durations, it can give me the length of the time span in minutes, hours or days, but not calculated using remainders.
My current solution is to use diff to create the ranges and then use modulo to calculate remainders, but this is not very elegant:
var days = moment(end).diff(start, 'days');
var hours = moment(end).diff(start, 'hours') % 24;
var minutes = moment(end).diff(start, 'minutes') % 60;
var duration = ((days > 0) ? days + 'd ' : '') + ((hours > 0) ? hours + 'h ' : '') + ((minutes > 0) ? minutes + 'm ' : '');
The question: Is there any smarter way to do this in either moment.js or twix.js, or should I take my time and develop my own moment.js plugin?
You can try using Durations, but I'm not sure if those have the capabilities you are looking for http://momentjs.com/docs/#/durations/
Also, you can always user moment's diff to get the difference in milliseconds and then format it to your needs. It is basically the same that you are doing, but you only call diff once.
function convertMilliSecondsIntoLegibleString(milliSecondsIn) {
var secsIn = milliSecondsIn / 1000;
var milliSecs = milliSecondsIn % 1000;
var hours = secsIn / 3600,
remainder = secsIn % 3600,
minutes = remainder / 60,
seconds = remainder % 60;
return ( hours + "h: "
+ minutes + "m: "
+ seconds +"s: " + milliSecs + "ms");
}
There's a plugin for formatting duration in moment.js : moment-duration-format
If it doesn't do what you need, then you should extend moment.duration.fn. If you don't support many locales, it should be easy enough.
In any case, I'd recommend to read the thread of this feature request.

count down to multiple moments, how?

I'm creating a site for my neighbor who has a Christmas light show.
The show runs every year from 6 December till 1 January twice an evening: at 6.30pm and at 8.00pm.
We want to add a countdown on the website which says:
next show: 00:00:00 (hh:mm:ss)
But how do I do that. When I search for it on the web every one says that I have to use an API for a countdown.
But they just use one date to count down to, so I think I have to write one myself in JavaScript.
Can anyone help with that?
I guess I have to use many if/else statements, starting with "is the month 1, 12 or something else?", followed by "has it yet been 18.30?" (I want 24-hours) and "has it already been 20.00" and so on.
But is there a better way, because this seems a lot of work to me.
JavaScript has a built-in date object that makes dealing with dates and times a bit less manual:
MDN documentation for JavaScript's date object
If you supply no arguments to its constructor, it'll give you the current date (according to the end user's computer):
var now = new Date();
You can set it to a specific date by supplying the year, month (zero-indexed from January), day, and optionally hour, minute and second:
var now = new Date();
var first_show = new Date(now.getFullYear(), 11, 6, 18, 30);
You can use greater- and less-than comparisons on these date objects to check whether a date is after or before another:
var now = new Date();
var first_show = new Date(now.getFullYear(), 11, 6, 18, 30);
alert(now < first_show);// Alerts true (at date of writing)
So, you could:
Create date objects for the current date, and each show this year (and for the 1st Jan shows next year)
Loop through the show dates in chronological order, and
Use the first one that's greater than the current date as the basis for your countdown.
Note: you should use something server-side to set now with accurate parameters, instead of just relying on new Date(), because if the end-user's computer is set to the wrong time, it'll give the wrong result.
Here's an example that will count down for 4 hours starting now() :
<script type="text/javascript">
var limit = new Date(), element, interval;
limit.setHours(limit.getHours() + 4);
window.onload = function() {
element = document.getElementById("countdown");
interval = setInterval(function() {
var now = new Date();
if (now.getTime() >= limit.getTime()) {
clearInterval(interval);
return;
}
var diff = limit.getTime() - now.getTime();
var hours = parseInt(diff / (60 * 60 * 1000));
diff = diff % (60 * 60 * 1000);
minutes = parseInt(diff / (60 * 1000));
diff = diff % (60 * 1000);
seconds = parseInt(diff / 1000);
if (hours < 10) {
hours = "0" + hours;
}
if (minutes < 10) {
minutes = "0" + minutes;
}
if (seconds < 10) {
seconds = "0" + seconds;
}
miliseconds = diff % 1000;
miliseconds = miliseconds.toString().substring(0, 2);
element.innerHTML = hours + ":" + minutes + ":" + seconds + ":" + miliseconds;
}, 10);
}
See it live here

Jquery time difference in hours from two fields

I have two fields in my form where users select an input time (start_time, end_time) I would like to, on the change of these fields, recalcuate the value for another field.
What I would like to do is get the amount of hours between 2 times. So for instance if I have a start_time of 5:30 and an end time of 7:50, I would like to put the result 2:33 into another field.
My inputted form times are in the format HH:MM:SS
So far I have tried...
$('#start_time,#end_time').on('change',function()
{
var start_time = $('#start_time').val();
var end_time = $('#end_time').val();
var diff = new Date(end_time) - new Date( start_time);
$('#setup_hours').val(diff);
try
var diff = ( new Date("1970-1-1 " + end_time) - new Date("1970-1-1 " + start_time) ) / 1000 / 60 / 60;
have a fiddle
It depends on what format you want your output in. When doing math with Date objects, it converts them into milliseconds since Epoch time (January 1, 1970, 00:00:00 UTC). By subtracting the two (and taking absolute value if you don't know which is greater) you get the raw number of milliseconds between the two.
From there, you can convert it into whatever format you want. To get the number of seconds, just divide that number by 1000. To get hours, minutes, and seconds:
var diff = Math.abs(new Date(end_time) - new Date(start_time));
var seconds = Math.floor(diff/1000); //ignore any left over units smaller than a second
var minutes = Math.floor(seconds/60);
seconds = seconds % 60;
var hours = Math.floor(minutes/60);
minutes = minutes % 60;
alert("Diff = " + hours + ":" + minutes + ":" + seconds);
You could of course make this smarter with some conditionals, but this is just to show you that using math you can format it in whatever form you want. Just keep in mind that a Date object always has a date, not just a time, so you can store this in a Date object but if it is greater than 24 hours you will end up with information not really representing a "distance" between the two.
var start = '5:30';
var end = '7:50';
s = start.split(':');
e = end.split(':');
min = e[1]-s[1];
hour_carry = 0;
if(min < 0){
min += 60;
hour_carry += 1;
}
hour = e[0]-s[0]-hour_carry;
min = ((min/60)*100).toString()
diff = hour + ":" + min.substring(0,2);
alert(diff);
try this :
var diff = new Date("Aug 08 2012 9:30") - new Date("Aug 08 2012 5:30");
diff_time = diff/(60*60*1000);

Categories