I have four fields in my HTML. Two are datepicker fields (one for from-date the other for the to-date). Similarly, the other two are timepicker fields (one for the from-time and other for the to-time) .
<input type="text" id="from-datepicker"/>
<input class="timepicker" name="timepicker" id="from-timepicker"/>
<input type="text" id="to-datepicker"/>
<input class="timepicker" name="timepicker" id="to-timepicker"/>
The dates are displayed and used in yyyy-mm-dd format, while the time format is 24-hour clock like 23:45:52.
Now, I just want to know how can I calculate the time difference between two timestamps such that the difference between
20 Oct 2015 11:00:00 and 28 Oct 2015 13:15:00shall return 7 days 2 hours and 15 minutes
I know how can I get the difference between two dates in JavaScript, but is there any library that provides differences using the timestamp?
Here is a function I use. Just modify the output to remove the "ago" part. Maybe change client_time and server_time to be more descriptive of your particular use.
And actually maybe add another if/else for your particular need following the general format.
Pub.prettyTime = function (server_time) {
var MINUTE = 60, // 000060 seconds in a minute
HOUR = 3600, // 003600 seconds in an hour
DAY = 43200, // 43,200 seconds in a day
NORMALIZE = 1000, // 00.001 seconds in a millisecond, flipped due to the .1 inaccuracy rule
// Date.now() is in milliseconds so divide by 1000, to get client_time in seconds
// this way client time and server time have the same units for comparison
// this is UTC time
client_time = Math.round(Date.now() / NORMALIZE),
rounded_time,
elapsed_time,
string = '';
// here we ensure we never get a negative elapsed time
// because clients are not synched to the server
// in the case of negative elapsed time, the server is ahead of the client
// and we will jus say "just a second ago"
if (client_time < server_time) {
client_time = server_time;
}
elapsed_time = (client_time - server_time);
// create the output string
if (elapsed_time === 0) {
string = ' just a second ago';
// 0 to 1 minute ago
} else if ((elapsed_time > 0) && (elapsed_time < MINUTE)) {
string = (elapsed_time === 1) ? 'one second ago' :
(elapsed_time + ' seconds ago');
// 1 minute to 1 hour ago
} else if ((elapsed_time >= MINUTE) && (elapsed_time < HOUR)) {
rounded_time = Math.floor(elapsed_time / MINUTE);
string = (rounded_time === 1) ? 'one minute ago' :
(rounded_time + ' minutes ago');
// 1 hour to to 1 day ago
} else if ((elapsed_time >= HOUR) && (elapsed_time < DAY)) {
rounded_time = Math.floor(elapsed_time / HOUR);
string = (rounded_time === 1) ? 'one hour ago' :
(rounded_time + ' hours ago');
// more than 1 day ago
} else if ((elapsed_time >= DAY)) {
rounded_time = new Date(server_time * NORMALIZE);
string = 'on ' + rounded_time.toLocaleDateString();
}
return string;
};
Furthermore you can plug in your format above in your Question into the constructor to obtain the normalized timestamp - var d2 = new Date("28 Oct 2015 13:15:00") and finally apply d2.valueOf() to get the unix timestamp. You can also take the difference of dates ( d2 - d1 ).
Using this info. you should be able to achieve what you need.
You can use momentjs.
Check substract part in docs.
Related
I'm having to hit an API I have no access to fixing and I need to start a timer showing how long someone has been in a queue for. The date I get back is in this format 1556214336.316. The problem is the year always shows up as 1970, but the time is the correct start time. I need to calculate the difference between the time now, and the time the conversation was created at. I have tried this with little success and was wondering if there is an elegant way to only get the difference in time and not the total amount of seconds.
convertDateToTimerFormat = (time) => {
const now = new Date();
const diff = Math.round((now - parseInt(time.toString().replace('.', ''))) / 1000);
const hours = new Date(diff).getHours();
const minutes = new Date(diff).getMinutes();
const seconds = new Date(diff).getSeconds();
return `${hours}:${minutes}:${seconds}`;
}
The weird parseInt(time.toString().replace('.', ''))) seems to fix the 1970 issue, but I still can't get the data to be manipulated how I need.
I tried the momentjs library, but their diff method only appears to allow for days and hours.
Any help/guidance, would be much appreciated.
Edit with working code:
convertDateToTimerFormat = (time) => {
const now = new Date();
// eslint-disable-next-line radix
const diff = new Date(Number(now - parseInt(time.toString().replace(/\./g, ''))));
const hours = diff.getHours();
const minutes = diff.getMinutes();
const seconds = diff.getSeconds();
return `${hours}:${minutes}:${seconds}`;
}
Unix time values are the number of seconds since the Epoch and won't have a decimal like your 1556214336.316
If I take 1556214336 (without the .316) and put it in a converter I get the output 04/25/2019 # 5:45pm (UTC) which is not 1970 — it seems an accurate time (I haven't independently verified)
It seems, then, your 1556214336.316 is the seconds.milliseconds since the epoch.
Javascript uses the same epoch, but is the number of milliseconds since the epoch, not seconds, so if I'm correct about the time you're getting you should be able to just remove the decimal place and use the resulting number string. Indeed
var d = new Date(1556214336316);
console.log('Date is: ' + d.toUTCString());
produces
Date is: Thu, 25 Apr 2019 17:45:36 GMT
which exactly matches the converter's time of "5:45pm"
var d = new Date(1556214336316);
console.log('Date is: ' + d.toUTCString());
Assuming your value 1556214336.316 is a String coming back from a web API, you can remove the decimal and your conversion can be done like this (note you don't have to keep creating new Date objects):
convertDateToTimerFormat = (time) => {
const d = new Date( Number(time.replace(/\./g, '')) );
return `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}`;
};
console.log( 'time: ' + convertDateToTimerFormat('1556214336.316') );
Depending on your use, you may want to use getUTCHours() etc. instead.
I don't know about elegant, but this calculates and displays the expired time in h:mm:ss format:
console.log(convertDateToTimerFormat(1556215236.316));
function convertDateToTimerFormat(time){
// Converts `time` to milliseconds to make a JS Date object, then back to seconds
const expiredSeconds = Math.floor(new Date()/1000) - Math.floor(new Date(time * 1000)/1000);
// Calculates component values
const hours = Math.floor(expiredSeconds / 3600), //3600 seconds in an hour
minutes = Math.floor(expiredSeconds % 3600 / 60),
seconds = expiredSeconds % 3600 % 60;
// Adds initial zeroes if needed
if (minutes < 10) { minutes = "0" + minutes; }
if (seconds < 10) { seconds = "0" + seconds; }
// Returns a formatted string
return `${hours}:${minutes}:${seconds}`;
}
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')))
Hey javascript masters,
Attempting to create an age verification page to a client's site. Code below is not functioning as it doesn't matter what year you select, it will still allow you to enter the site. Not sure what I should be looking at to correct.
Any help is appreciated.
<script type="text/javascript"><!--
function checkAge(f){
var dob=new Date();
var date=dob.getDate();
var month=dob.getMonth() + 1;
var year=dob.getFullYear();
var cmbmonth=parseInt(document.getElementById("cmbmonth").options[document.getElementById("cmbmonth").selectedIndex].value);
var cmbday=parseInt(document.getElementById("cmbday").options[document.getElementById("cmbday").selectedIndex].value);
var cmbyear=parseInt(document.getElementById("cmbyear").options[document.getElementById("cmbyear").selectedIndex].value);
age=year-cmbyear;
if(cmbmonth>month){age--;}
else{if(cmbmonth==month && cmbday>=date){age--;}}
if(cmbmonth==0){alert("You must enter the month you were born in.");return false;}
else if(cmbday==0){alert("You must enter the day you were born on.");return false;}
else if(cmbyear==2005){alert("You must enter the year you were born in.");return false;}
else if(age<13){alert("You are unable to view this site!");location.replace("http://www.dharmatalks.org");return false;}
else{return true;}
}
// --></script>
Calculating age in years, months and days is a bit trickier than it should be due to the differences in month and year lengths. Here's a function that will return the difference between two dates in years, months, days, hours, minutes and seconds.
function dateDifference(start, end) {
// Copy date objects so don't modify originals
var s = new Date(+start);
var e = new Date(+end);
var timeDiff, years, months, days, hours, minutes, seconds;
// Get estimate of year difference
years = e.getFullYear() - s.getFullYear();
// Add difference to start, if greater than end, remove one year
// Note start from restored start date as adding and subtracting years
// may not be symetric
s.setFullYear(s.getFullYear() + years);
if (s > e) {
--years;
s = new Date(+start);
s.setFullYear(s.getFullYear() + years);
}
// Get estimate of months
months = e.getMonth() - s.getMonth();
months += months < 0? 12 : 0;
// Add difference to start, adjust if greater
s.setMonth(s.getMonth() + months);
if (s > e) {
--months;
s = new Date(+start);
s.setFullYear(s.getFullYear() + years);
s.setMonth(s.getMonth() + months);
}
// Get remaining time difference, round to next full second
timeDiff = (e - s + 999) / 1e3 | 0;
days = timeDiff / 8.64e4 | 0;
hours = (timeDiff % 8.64e4) / 3.6e3 | 0;
minutes = (timeDiff % 3.6e3) / 6e1 | 0;
seconds = timeDiff % 6e1;
return [years, months, days, hours, minutes, seconds];
}
You can abbreviate the above just after the year part and return just that if you want.
Note that in your code:
var cmbmonth=parseInt(document.getElementById("cmbmonth").options[document.getElementById("cmbmonth").selectedIndex].value);
can be:
var cmbmonth = document.getElementById("cmbmonth").value;
There is no need for parseInt, the Date constructor will happily work with string values. If you have used calendar month numbers for the values (i.e. Jan = 1) then subtract 1 before giving it to the Date constructor, but simpler to use javascript month indexes for the values (i.e. Jan = 0).
You can then do:
var diff = dateDifference(new Date(cmbyear, cmbmonth, cmbdate), new Date());
if (diff[0] < 18) {
// sorry, under 18
}
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);
I'm using this plugin called timeago found here: timeago.yarp.com
It works great, except that it operates in what appears to be a different timezone. I live in Eastern US (Philadelphia timezone) and when I put the exact time EST into the timeago plugin (say 2011-05-28, 13:47:18), it reprints as four hours later on my html page. When I write 2011-05-28, 17:47:18 (four hours later than my actual time from where I live), THEN it reprints as "less than a minute ago"
Here's the jquery plugin code:
(function($) {
$.timeago = function(timestamp) {
if (timestamp instanceof Date) {
return inWords(timestamp);
} else if (typeof timestamp === "string") {
return inWords($.timeago.parse(timestamp));
} else {
return inWords($.timeago.datetime(timestamp));
}
};
var $t = $.timeago;
$.extend($.timeago, {
settings: {
refreshMillis: 60000,
allowFuture: false,
strings: {
prefixAgo: "added",
prefixFromNow: "added",
suffixAgo: "ago",
suffixFromNow: "from now",
seconds: "less than a minute",
minute: "about a minute",
minutes: "%d minutes",
hour: "about an hour",
hours: "about %d hours",
day: "a day",
days: "%d days",
month: "about a month",
months: "%d months",
year: "about a year",
years: "%d years",
numbers: []
}
},
inWords: function(distanceMillis) {
var $l = this.settings.strings;
var prefix = $l.prefixAgo;
var suffix = $l.suffixAgo;
if (this.settings.allowFuture) {
if (distanceMillis < 0) {
prefix = $l.prefixFromNow;
suffix = $l.suffixFromNow;
}
distanceMillis = Math.abs(distanceMillis);
}
var seconds = distanceMillis / 1000;
var minutes = seconds / 60;
var hours = minutes / 60;
var days = hours / 24;
var years = days / 365;
function substitute(stringOrFunction, number) {
var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
var value = ($l.numbers && $l.numbers[number]) || number;
return string.replace(/%d/i, value);
}
var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
seconds < 90 && substitute($l.minute, 1) ||
minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
minutes < 90 && substitute($l.hour, 1) ||
hours < 24 && substitute($l.hours, Math.round(hours)) ||
hours < 48 && substitute($l.day, 1) ||
days < 30 && substitute($l.days, Math.floor(days)) ||
days < 60 && substitute($l.month, 1) ||
days < 365 && substitute($l.months, Math.floor(days / 30)) ||
years < 2 && substitute($l.year, 1) ||
substitute($l.years, Math.floor(years));
return $.trim([prefix, words, suffix].join(" "));
},
parse: function(iso8601) {
var s = $.trim(iso8601);
s = s.replace(/\.\d\d\d+/,""); // remove milliseconds
s = s.replace(/-/,"/").replace(/-/,"/");
s = s.replace(/T/," ").replace(/Z/," UTC");
s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
return new Date(s);
},
datetime: function(elem) {
// jQuery's `is()` doesn't play well with HTML5 in IE
var isTime = $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
var iso8601 = isTime ? $(elem).attr("datetime") : $(elem).attr("title");
return $t.parse(iso8601);
}
});
$.fn.timeago = function() {
var self = this;
self.each(refresh);
var $s = $t.settings;
if ($s.refreshMillis > 0) {
setInterval(function() { self.each(refresh); }, $s.refreshMillis);
}
return self;
};
function refresh() {
var data = prepareData(this);
if (!isNaN(data.datetime)) {
$(this).text(inWords(data.datetime));
}
return this;
}
function prepareData(element) {
element = $(element);
if (!element.data("timeago")) {
element.data("timeago", { datetime: $t.datetime(element) });
var text = $.trim(element.text());
if (text.length > 0) {
element.attr("title", text);
}
}
return element.data("timeago");
}
function inWords(date) {
return $t.inWords(distance(date));
}
function distance(date) {
return (new Date().getTime() - date.getTime());
}
// fix for IE6 suckage
document.createElement("abbr");
document.createElement("time");
}(jQuery));
I realize this problem is something very minor and can be easily fixed if I were to just remember the plugin works on a 4 hour delay, but I'd still like to know the answer if possible to provide.
Thanks!
Updated
I'm going to give this a shot but I must add the disclaimer that I'm a little fuzzy on this myself so I might be quite wrong!
The plugin expects the time in the ISO 8601 format which can also include offset information. I've now tried using the plugin and this is what I see (at 14:42 EDT, about 3 minutes from the test time string):
When a trailing Z is used, indicating Zulu time or an offset of 0 from UTC, the plugin interprets it as UTC (obviously) and when printing the relative time string, it takes into consideration your actual timezone. This causes the extra 4 hours to be added (EST is UTC-5 (UTC-4 when following DST, like now)).
2011-05-28T14:39:33Z prints as about 4 hours ago
When a trailing Z is not used, the plugin interprets the time specified according to your timezone and it seems to work just fine (as long as the timezone for the timestamp and the timezone you're viewing this timestamp in are the same). This is in line with what the Wikipedia article has to say:
If no UTC relation information is given with a time representation, the time is assumed to be in local time. While it may be safe to assume local time when communicating in the same time zone, it is ambiguous when used in communicating across different time zones. It is usually preferable to indicate a time zone (zone designator) using the standard’s notation.
This would not be a recommended way since it's going to mess up the times when viewed from elsewhere since the timestamp will be interpreted as being the timestamp for that timezone which is incorrect.
2011-05-28T14:39:33 prints as 3 minutes ago
When a trailing Z is specified along with the timezone offset (in the format of hh:mm, only hh seems to be ignored), it still seems to work just fine.
2011-05-28T14:39:33Z-04:00 prints as 3 minutes ago
You can see a working example here: http://jsfiddle.net/nogoodatcoding/SVgck/
You shouldn't be changing the timezone/offset of the plugin itself since that will cause visitors from other timezones to see incorrect values.
One fix is to also specify the timezone offset in your date-time strings: 2011-05-28, 13:47:18Z-04:00 - in a sense, a more complete description of the time since it also includes the UTC offset information.
Depending on how you're generating this page (if it's not just static HTML), the other option is to fix your server-side code so that the date-time string it outputs is in the UTC format - if not built in, you should be able to find a library that does the conversion from a timestamp in your local timezone into UTC. This is how sites I've seen do it - for example, the timestamps here on StackOverflow (or on Twitter and Facebook) are in UTC time - they are then formatted differently based on the user's timezone.
Hey, I use this plugin. It's not the javascript you have to edit. Look for the php file, in wordpress it's called 'wpTimeAgo.php' it should be something similar to that.
In that file look for this:
var $_gmtOffset = '';
Add a number there, I believe that should do the trick.
If you're using timeago in the .NET world, you'll find it's very fussy about the offset it gets. z and zz won't work, it needs to be zzz and should include the delimiting big "Z" and "T".
For example:
string.Format("{0}Z{1:%zzz}", DateTime.Now.ToString("s"), DateTime.Now);
This displays as:
2013-01-06T12:46:28Z-08:00