Date subtraction returns unexpected result - javascript

I have some JavaScript that pulls dates out of two fields on my web page:
var StartDate = document.getElementById('StartDate');
var EndDate = document.getElementById('EndDate');
When I get these two dates I have the following snippet of code that performs the date subtraction:
var day = 1000*60*60*24;
var d1 = new Date(StartDate.value);
var d2 = new Date(EndDate.value);
var difference = (Math.ceil((d2.getTime() - d1.getTime()) / day))
Now is when the problem comes in. Say that my two dates are as such:
StartDate = 2013-05-01
EndDate = 2013-06-30
Using the calculator we get:
1372564800000 - 1367380800000 = 5184000000
5184000000 / 86400000 = 60 days
However, next let's use the following dates:
StartDate = 2013-10-01
EndDate = 2013-11-30
Again, using the calculator we get:
1385787600000 - 1380600000000 = 5187600000
5187600000 / 86400000 = 60.04166666666667 days
I'm just not sure how this is possible, I am using two identical date ranges. Both start days start on the first of a month with 31 days, and both end days end on the last day of a month with 30 days. When I put these date ranges into a MS Excel workbook I get the correct number of days:
=(EndCell-StartCell)
And I again get the 60 days for both sets of date ranges.
This seems to only happen when I cross into November of 2013. It doesn't happen when I cross into November of 2014, and I cannot find any other times when this happens. I know 2013 is gone, but my application will deal heavily with 2013 dates. Does anybody know of a reason why/how this is happening? Does anybody know of a better way to do date subtraction with JavaScript that will not cause this issue?

Related

Why does javascript subtract an entire month rather than one day if the time isn't zeroed out?

Not looking for solutions, just want to know why I get those results and get a better understanding of javascript.
I'm calculating dates and date strings for today through 3 days ago. If I zero out time for today, everything works just fine. If I don't (and maybe also it's close to midnight UTC) yesterday is a month ago, other previous day calculations work as expected.
Screenshot:
Code run in the console at about 5:30p eastern which is 11:30p UTC
Here's the code so you can run it yourself.
Zero out time and yesterday is yesterday:
let today = new Date();
today.setUTCHours(0,0,0); // remove time, otherwise yesterday if based off of today could be a month ago.
let todays_date_string = today.toISOString().slice(0, 10);
let yesterday = new Date(todays_date_string);
yesterday.setDate(today.getDate() - 1);
let yesterdays_date_string = yesterday.toISOString().slice(0, 10);
let two_days_ago = new Date(yesterdays_date_string);
two_days_ago.setDate(two_days_ago.getDate() - 1);
let two_days_ago_date_string = two_days_ago.toISOString().slice(0, 10);
let three_days_ago = new Date(two_days_ago_date_string);
three_days_ago.setDate(three_days_ago.getDate() - 1);
let three_days_ago_date_string = three_days_ago.toISOString().slice(0, 10);
console.log({today, today_s: today.toISOString(), todays_date_string, yesterdays_date_string, two_days_ago_date_string, three_days_ago_date_string});
Don't zero out time and yesterday is a month ago:
let today = new Date();
//today.setUTCHours(0,0,0); // remove time, otherwise yesterday if based off of today could be a month ago.
let todays_date_string = today.toISOString().slice(0, 10);
let yesterday = new Date(todays_date_string);
yesterday.setDate(today.getDate() - 1);
let yesterdays_date_string = yesterday.toISOString().slice(0, 10);
let two_days_ago = new Date(yesterdays_date_string);
two_days_ago.setDate(two_days_ago.getDate() - 1);
let two_days_ago_date_string = two_days_ago.toISOString().slice(0, 10);
let three_days_ago = new Date(two_days_ago_date_string);
three_days_ago.setDate(three_days_ago.getDate() - 1);
let three_days_ago_date_string = three_days_ago.toISOString().slice(0, 10);
console.log({today, today_s: today.toISOString(), todays_date_string, yesterdays_date_string, two_days_ago_date_string, three_days_ago_date_string});
Also note that I'm using today to calculate yesterday's date rather than the newly created yesterday based off today's date string which could be a contributing factor. But I wouldn't think that would affect calculating yesterday and certainly not to that degree.
Is there an explanation for this?
The key point is this: The setDate() method changes the day of the month of a given Date instance, based on local time.
Let's walk through some code.
const date = new Date('2023-02-01T22:34:47.458Z');
const todayDateString = date.toISOString().slice(0, 10); // 2023-02-01
const todayDateDate = new Date(todayDateString);
The value of todayDateDate.toISOString() is 2023-02-01T00:00:00.000Z
The value of date.getDate() is 1.
The value of todayDateDate.toString() is Tue Jan 31 2023 19:00:00 GMT-0500 (Eastern Standard Time) (this will vary depending on your time zone).
The local date is January 31!
If you setDate(0), it gives you the last day of the previous month, based on local time. Since the local time is in January, this means December 31 in local time, and will be January 1 UTC.
The exact results depend on your local time zone.
When you construct the new date that doesn't explicitly specify a time zone, e.g. new Date('2023-02-01'), the date is interpreted in your local time zone.
But when you stringify it via toISOString() you get the date in the UTC time zone, which could be a different day (the other side of midnight).
Consider:
// February 1 in UTC+05:00
const d1 = new Date('2023-02-01T01:00:00+05:00')
// is still January 31 in UTC
console.log(d1.toISOString()); // 2023-01-31T20:00:00.000Z
So if
your timezone offset means it's still yesterday in UTC, and
yesterday was still January 31 instead of February 1, then
setDate(1) makes it January 1: a month ago.

How to compare dates without including the hour

So there is a column that has the date with the hour and i was trying to create a variable date with the same date, month, year and hour to be able to compare it wiht that date but this didn't work with me so I thought I would do that by creating the same date but when i compare i won't consider the hour but im facing some difficulties.
anyone of the two solutions would be great
I wrote many other codes but none of them worked and that was the last one i wrote
var date = new Date();
var year = date.getYear();
var month = date.getMonth() + 1; if(month.toString().length==1){var month =
'0'+month;}
var day = date.getDate(); if(day.toString().length==1){var day = '0'+day;}
var date = month+'/'+day+'/'+year;
Logger.log(date);
Im using JavaScript in google app script.
Thank you!
From MDN
We have a first step to create an object date.
let today = new Date()
let birthday = new Date('December 17, 1995 03:24:00')
let birthday = new Date('1995-12-17T03:24:00')
let birthday = new Date(1995, 11, 17) // the month is 0-indexed
let birthday = new Date(1995, 11, 17, 3, 24, 0)
let birthday = new Date(628021800000) // passing epoch timestamp
You can create your Date object following the example above that fits you better. I also recommend giving a good look into this page.
For the second step...
From there, you can use Date.now(). As explained here, this will return "A Number representing the milliseconds elapsed since the UNIX epoch."
The third step is...
comparing both numbers. Which one is smaller will be an "earlier date" and vice-versa.
If some dates don't have time, I would consider it as midnight. Using the default Date format, that would be something like this.
yyyy-mm-ddThh:mm:ssZ
Ex:
2022-02-21T09:39:23Z
The Z at the end means UTC+0.
More about this on this link.
So, a date without time would be:
2022-02-21T00:00:00Z

Comparing jQuery date to Rails date

I have a rails-generated date, and a jQuery-generated date.
The rails date prints as such: 2002-10-27
and the jQuery date prints as such: Tue Aug 14 2001 00:00:00 GMT-0500 (CDT)
I want to check if the jQuery date is greater or less than the rails date. But no matter the dates, the jQuery date is always interpreted as larger than the rails date.
Why is that, and how can I successfully compare the two dates?
var year = 2001
var month = 9
month --
var day = 14
var date = new Date(year, month, day);
<% #date = Date.today - 18.years %>
if( date > <%= #date %> ) {
//this code is always executed, no matter what dates I choose
}
UPDATE:
Actually I just figured out the problem is that it only allows dates before 1969. I intended the code to only allow dates over 18 years old. Does anyone know why the difference?
UPDATE 2:
I tested the time output of October 5th, 2000 in my js console and rails consoles, and they give the same first six digits, but the js console adds three zeros.
var year = 2000
var month = 10
month --
var day = 5
var date = new Date(year, month, day);
date.getTime();
=> 970722000000
Date.new(2000,10,5).to_time.to_i
=> 970722000
So it turns out the issue is that the js console prints times in milliseconds, which is why I was getting 973404000000, versus 973404000 in the rails console.
All I had to do was divide the js time by 1000, and comparing the js time to the rails time works perfectly.
var year = 2000
var month = 10
month --
var day = 5
var date = (new Date(year, month, day).getTime() / 1000);
date
=> 970722000
Date.new(2000,10,5).to_time.to_i
=> 970722000
User date Format patterns for Jquery Date, for changing the format of date according to ruby date , or second option is convert ruby date format according to jquery , using strftime.
You might try converting them both to their unix timestamps and comparing those. If you don't care about the hours, and simply the dates, it should work.
var year = 2001
var month = 9
var day = 14
var date = new Date(year, month, day);
<% #date = Date.today - 18.years %>
if ( date.getTime() > <%= #date.to_time.to_i %>) {
// do something
}
I'd use a library like Moment.JS to handle your date parsing needs on the client side. And then send the server something in a standard format like ISO8601 to ensure you don't have any problems in misintrepretation.
Epoch time will work as well, but as you've seen you have to carry the burden of ensuring that they're in the same units.
To compare 2 dates for me u can use moment.js
With ur rails date create a moment date. Do the same with ur jquery date.
U can compare easily the 2 dates now.
If u need help see this post : moment-js-date-time-comparison

Working out the numbers of hours elapsed between two dates using datejs and timejs

I'm using the datejs library with timejs module. We receive contact requests into a table and want to work out our response times. So i have start date with timestamp and response date.
I used date.js to work out the time difference between the two dates. Problem is that it does a simple math calculation between the two numbers provided from each timestamp rather than taking into account that 24 hours elapse for each day difference.
So for example:
var start = Date.parse("Feb 16 2012 15:30:00");
var end = Date.parse("Feb 19 2012 09:30:00");
var span = new TimeSpan(end - start);
var tdiff = span.hours;
console.log(tdiff);
This gives me a result of 18 hours, when the actual time elapsed between those two dates is 66hours. How can i use this library to give me the actual time elapsed?
Secondly, the working day is from 9am to 5.30pm, how can i exclude the hours that are not part of the working day from this calculation?
var start = Date.parse("Feb 16 2012 15:30:00");
var end = Date.parse("Feb 19 2012 09:30:00");
var numOfHrs = (end-start) / (1000*60*60);
alert(numOfHrs);
alert((24-15.5) * (numOfHrs/24));

How to subtract date/time in JavaScript? [duplicate]

This question already has answers here:
How do I get the difference between two Dates in JavaScript?
(18 answers)
Closed 8 years ago.
I have a field at a grid containing date/time and I need to know the difference between that and the current date/time. What could be the best way of doing so?
The dates are stored like "2011-02-07 15:13:06".
This will give you the difference between two dates, in milliseconds
var diff = Math.abs(date1 - date2);
In your example, it'd be
var diff = Math.abs(new Date() - compareDate);
You need to make sure that compareDate is a valid Date object.
Something like this will probably work for you
var diff = Math.abs(new Date() - new Date(dateStr.replace(/-/g,'/')));
i.e. turning "2011-02-07 15:13:06" into new Date('2011/02/07 15:13:06'), which is a format the Date constructor can comprehend.
You can just substract two date objects.
var d1 = new Date(); //"now"
var d2 = new Date("2011/02/01"); // some date
var diff = Math.abs(d1-d2); // difference in milliseconds
If you wish to get difference in wall clock time, for local timezone and with day-light saving awareness.
Date.prototype.diffDays = function (date: Date): number {
var utcThis = Date.UTC(this.getFullYear(), this.getMonth(), this.getDate(), this.getHours(), this.getMinutes(), this.getSeconds(), this.getMilliseconds());
var utcOther = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds());
return (utcThis - utcOther) / 86400000;
};
Test
it('diffDays - Czech DST', function () {
// expect this to parse as local time
// with Czech calendar DST change happened 2012-03-25 02:00
var pre = new Date('2012/03/24 03:04:05');
var post = new Date('2012/03/27 03:04:05');
// regardless DST, you still wish to see 3 days
expect(pre.diffDays(post)).toEqual(-3);
});
Diff minutes or seconds is in same fashion.
Unless you are subtracting dates on same browser client and don't care about edge cases like day light saving time changes, you are probably better off using moment.js which offers powerful localized APIs. For example, this is what I have in my utils.js:
subtractDates: function(date1, date2) {
return moment.subtract(date1, date2).milliseconds();
},
millisecondsSince: function(dateSince) {
return moment().subtract(dateSince).milliseconds();
},
You can use getTime() method to convert the Date to the number of milliseconds since January 1, 1970. Then you can easy do any arithmetic operations with the dates. Of course you can convert the number back to the Date with setTime(). See here an example.

Categories

Resources