Calculate the exact time difference using moment JS - javascript

I need to calculate the exact time diffrence using moment JS .
My JS code is :
var a = moment(from_url);
a.format('DD/MM/YYYY hh:mm:ss');
var b = moment(to_url);
b.format('DD/MM/YYYY hh:mm:ss');
console.log("from URL")
var from_hours = from_url()
console.log(b.diff(a, 'minutes')) //
console.log(b.diff(a, 'hours')) //
console.log(b.diff(a, 'days')) //
console.log(b.diff(a, 'weeks')) //
console.log("Time interval: "+b.diff(a, 'days')+ " days "+ b.diff(a, 'hours') +" hours " +b.diff(a, 'minutes')+" mintes");
Now,
from_url = '2016-05-03T08:00:00';
to_url = '2016-05-04T09:00:00';
Now, for these timings, I am getting output as :
Time interval: 1 days 25 hours 1500 minutes It is converting everything to the days (1 day ~25 hours).
However, the output that I want is : 1 day 1 hour 0 minutes.
Can anyone please help me in this ?
I am newbie to JS and unable to figure this out.
Thanks.

To parse strings, you should always tell the parser the format you are providing. Moment.js can help with that, but you can also use your own small functions.
For getting the difference in days, hours, etc. you can simply subtract one date from another to get milliseconds, then convert that to the format you want.
Note that date arithmetic is not simple, there are many rules that change depending on custom or administrative rules. Also, when going over daylight saving boundaries, some days are 23 hours long and some 25.
The following is a simple approach that does not take account of daylight saving. Hopefully the comments are sufficient, play with the output format to get whatever you need.
// Parse ISO format string as local, ignore timezone
// E.g. 2016-05-29T23:32:15
function parseISOLocal(s) {
// Split string into its parts
var b = s.split(/\D/);
// Create and return a date object
return new Date(b[0], b[1]-1, b[2], b[3], b[4], b[5]);
}
// Convert a millisecond value to days, hours, minutes and seconds
function formatDHMS(ms) {
// Helper to add 's' to a number if other than 1
function addS(n){return n == 1? '' : 's';}
// Get the whole values of each unit, rounded down ( |0 truncates)
var d = ms/8.64e7 | 0; // days
var h = (ms%8.64e7) / 3.6e6 | 0; // hours
var m = (ms%3.6e6) / 6e4 | 0; // minutes
var s = (ms%6e4) / 1e3 | 0; // seconds
// Return a formatted string
return d + ' day' + addS(d) + ', ' +
h + ' hour' + addS(h) + ', ' +
m + ' minute' + addS(m) + ' and ' +
s + ' second' + addS(s);
}
document.write(formatDHMS(parseISOLocal('2016-05-04T09:00:00') - parseISOLocal('2016-05-03T08:00:00')))

Related

Timestamp on Google Tag Manager

I need a little help to create a variable on google tag manager that takes me the timestamp of when an event is triggered.
Now I have implemented this custom javascript but it takes me as the timezone that of the country of the user who will trigger the event.
On the other hand, I would like timezone always +02.00, can someone teach me which part of the code I need to modify to have my timezone always set?
Thank you
function()
{
var now = new Date();
var tzo = -now.getTimezoneOffset();
var dif = tzo >= 0 ? '+' : '-';
var pad = function(num) {
var norm = Math.abs(Math.floor(num));
return (norm < 10 ? '0' : '') + norm;
};
return now.getHours()
+ ':' + pad(now.getMinutes())
+ ':' + pad(now.getSeconds())
+ '.' + pad(now.getMilliseconds())
+ dif + pad(tzo / 60)
+ ':' + pad(tzo % 60);
}
This should be ample:
function qwe() {
var d = new Date();
nd = new Date((d.getTime() + (d.getTimezoneOffset() * 60000)) + (3600000 * 2));
var tzo = 120;
var dif = tzo >= 0 ? '+' : '-';
var pad = function (num) {
var norm = Math.abs(Math.floor(num));
return (norm < 10 ? '0' : '') + norm;
};
return nd.getHours()
+ ':' + pad(nd.getMinutes())
+ ':' + pad(nd.getSeconds())
+ '.' + pad(nd.getMilliseconds())
+ dif + pad(tzo / 60)
+ ':' + pad(tzo % 60);
}
Try to see this answer to "How to ignore user's time zone and force Date() use specific time zone": How to ignore user's time zone and force Date() use specific time zone
It says:
A Date object's underlying value is actually in UTC. To prove this, notice that if you type new Date(0) you'll see something like: Wed Dec 31 1969 16:00:00 GMT-0800 (PST). 0 is treated as 0 in GMT, but .toString() method shows the local time.
Big note, UTC stands for Universal time code. The current time right now in 2 different places is the same UTC, but the output can be formatted differently.
What we need here is some formatting
var _date = new Date(1270544790922);
// outputs > "Tue Apr 06 2010 02:06:30 GMT-0700 (PDT)", for me
_date.toLocaleString('fi-FI', { timeZone: 'Europe/Helsinki' });
// outputs > "6.4.2010 klo 12.06.30"
_date.toLocaleString('en-US', { timeZone: 'Europe/Helsinki' });
// outputs > "4/6/2010, 12:06:30 PM"
This works but.... you can't really use any of the other date methods for your purposes since they describe the user's timezone. What you want is a date object that's related to the Helsinki timezone. Your options at this point are to use some 3rd party library (I recommend this), or hack-up the date object so you can use most of it's methods.
Option 1 - a 3rd party like moment-timezone
moment(1270544790922).tz('Europe/Helsinki').format('YYYY-MM-DD HH:mm:ss')
// outputs > 2010-04-06 12:06:30
moment(1270544790922).tz('Europe/Helsinki').hour()
// outputs > 12
This looks a lot more elegant than what we're about to do next.
Option 2 - Hack up the date object
var currentHelsinkiHoursOffset = 2; // sometimes it is 3
var date = new Date(1270544790922);
var helsenkiOffset = currentHelsinkiHoursOffset*60*60000;
var userOffset = _date.getTimezoneOffset()*60000; // [min*60000 = ms]
var helsenkiTime = new Date(date.getTime()+ helsenkiOffset + userOffset);
// Outputs > Tue Apr 06 2010 12:06:30 GMT-0700 (PDT)
It still thinks it's GMT-0700 (PDT), but if you don't stare too hard you may be able to mistake that for a date object that's useful for your purposes.
I conveniently skipped a part. You need to be able to define currentHelsinkiOffset. If you can use date.getTimezoneOffset() on the server side, or just use some if statements to describe when the time zone changes will occur, that should solve your problem.
Conclusion - I think especially for this purpose you should use a date library like moment-timezone.

jonthornton timepicker : How to get hours and minues

I'm using the jonthornton/jquery-timepicker and could not find the hours and minutes selected.
All I could find was a string output of the form '10:30pm'.
Can the hours and minutes be accessed directly from the control?
I imagined you would be able to do this but could not find it.
The best I've been able to do is what follows, anyone got anything better?
$('#StartTime').on('change', function (timeControl) {
var hoursString;
if (timeControl.target.value.indexOf("am") >= 0) {
hoursString = timeControl.target.value.replace("am", ":00 AM");
}
else {
hoursString = timeControl.target.value.replace("pm", ":00 PM");
}
var oneDate = new Date(Date.parse("2000-01-01 " + hoursString));
var minutes = oneDate.getMinutes();
var hours = oneDate.getHours();
console.log("Hours : " + hours + " | Minutes : " + minutes);
});
The long-standing answer would be Moment.js but it is now considered a legacy project in maintenance mode and not recommended for new projects. There are recommendations on their website for replacements, but bringing in a new dependency for this may be overkill.
The value coming in seems to follow a format which we can rely on to make parsing easy.
Format: H:MMxx
Key:
H = hour, 1-2 characters
MM = minutes, always 2 characters
xx = am or pm, always 2 characters
var timeArray = timeControl.split(':');
var meridiem = timeArray[1].substring(2, 4);
var hours = parseInt(timeArray[0]) + (meridiem === 'pm' ? 12 : 0);
var minutes = parseInt(timeArray[1].substring(0, 2));
var seconds = 0;
// Local time zone, read more: https://stackoverflow.com/a/29297375/5988852
var date = new Date();
date.setHours(hours, minutes, seconds);
// If you want UTC instead
utc = Date.UTC(
date.getUTCFullYear(),
date.getUTCMonth(),
date.getUTCDate(),
hours,
minutes,
seconds
);
var date = new Date(utc);

Extract time from JS Date object without offsetting the Time zone

So we have multiple clients, that are in multiple time zones. I'm pulling some dates from an API, and the dates/times that are in this string are exactly what I need to display. I've been researching this, and digging for some time, and still haven't come up with a clear answer. The string coming in is formatted as such:
"2017-12-29T20:00:00"
What I'm wanting is to extract both the date and time as is, into two strings (no timezone offsetting, no matter where the viewer is located) but am having some issues doing so. Also hoping to format it in the correct fashion as well. Example:
"M/d/yyyy"
"hh:mm AM/PM" (12 hour)
I've tried numerous ways to battle this, and don't really want to just grab substrings, but am half tempted to do so. Any help is appreciated.
Consider just reformatting the string, it avoids all issues with the built-in parser and timezones:
function reformatTimestamp(s) {
function z(n){return (n<10?'0':'')+ +n}
var b = s.split(/\D/);
var h = b[3]%12 || 12;
var ap = b[3] < 12? 'AM':'PM';
return b[1] + '/' + b[2] + '/' + b[0] +
' ' + z(h) + ':' + z(b[4]) + ' ' + ap;
}
console.log(reformatTimestamp('2017-12-29T20:00:00')) // 12/29/2017 08:00 PM
I think it would be better to pad the month and day with a leading zero (but I'd also use an unambiguous date format like DD-MMM-YYYY rather than the peculiar m/d/y).
Use this code:
function formatAMPM(date) {
var hours = date.getUTCHours();
var minutes = date.getUTCMinutes();
var ampm = hours >= 12 ? 'PM' : 'AM';
hours = hours % 12;
hours = hours ? hours : 12; // the hour '0' should be '12'
minutes = minutes < 10 ? '0'+minutes : minutes;
var strTime = hours + ':' + minutes + ' ' + ampm;
return strTime;
}
var str = "2017-12-29T20:00:00";
var dt = new Date(str + "Z");
console.log("M/d/yyyy");
console.log((dt.getUTCMonth() + 1) + '/' + dt.getUTCDate() + '/' + dt.getUTCFullYear());
console.log("hh:mm AM/PM");
console.log(formatAMPM(dt));

Javascript time difference via timepicker

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.

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.

Categories