Wait a minute... (pun intended) This does provide an accurate difference, but it really isn't the kind of value that people expect. If you use this code to display the difference between 1/28/2009 and 2/28/2009, the result is "31 days". Although accurate, this is not always pleasing to people, who might be expecting something like "1 month".
Can we expand this simple loop to include the calculation of the difference in months? Well, the answer to that question is "not without a bit more work". Why not? Because the length of each month is not a fixed value, that's why.
So, how do we compute a difference between two dates that takes months into consideration? Conceptually, this is pretty straight-forward:
+Compute the difference for each of the following parts of the two dates:
- Years
- Months
- Days
- Hours
- Minutes
- Seconds
+Then, check these differences (bottom to top), looking for negative values. When you find a negative value:
- decrement the next larger units
- add "the appropriate amount" to the current value.
The biggest question is: What is the "appropriate value" for the number of days in a month?
Again the answer is: it depends...
How do we compute the "appropriate" number of days for the month?
Again, we can make use of a really nice property of the JavaScript date object. That is, if you construct a Date object with the "day of the month" as 0, the result will be the last day of the preceding month. For example, to create a new Date object to display the last day in February of 2009, you could simply:
Note: the parameters for the date constructor are:
- The full (4 digit) year
- The ordinal month number (where Jan = 0, Feb = 1, ... and Dec = 11)
- The date of the month
So, the date value being constructed is for the 0th day of the 3rd month (March), which is interpreted as the last day of the 2nd month (February), and the result will be a date object for: Sat Feb 28, 2009
So, how do we use this in our script?
Technique #2
var day1 = new Date( 'Dec 29, 1977 23:59:58' );var day2 = new Date( 'Mar 2, 2009 12:00:00' );var diff = [ day2.getFullYear() - day1.getFullYear(), day2.getMonth() - day1.getMonth(), day2.getDate() - day1.getDate(), day2.getHours() - day1.getHours(), day2.getMinutes() - day1.getMinutes(), day2.getSeconds() - day1.getSeconds() ];var delta = [ 12, 31, 24, 60, 60 ];delta[ 1 ] = ( new Date( day2.getFullYear(), day2.getMonth(), 0 ) ).getDate();for ( var i = diff.length - 1; i > -1; i-- ) { if ( diff[ i ] < 0 ) { if ( i > -1 ) { var j = i - 1; diff[ i ] += delta[ j ]; diff[ j ]--; } else { alert( 'Negative year difference: ' + diff[ 0 ] ); } }}
Before adjusting the values, the original contents of the 'diff' array were [ 32,-9,-27,-11,-59,-58 ].
After adjusting the values, we have [ 31,2,0,12,0,2 ] (i.e., 31 years, 2 months, 12 hours, and 2 seconds).
This looks reasonable, but if we compare the output of the two techniques, we find that the result of the first technique shows that the difference between "Dec 29, 1977 23:59:58" and "Mar 2, 2009 12:00:00" is:
So technique #1 has 70 days, and technique #2 has 2 months. Wait a minute. The longest month of the year has 31 days. So two months has to be less than 63 days. Why is there a difference between these two techniques?
Take a look at the difference in years. Over a 31 year span, how many leap years do you think there are? That's where the difference exists. How do we determine the number of leap days that exist between two dates?
First, we need an easy way to determine whether or not a specific year is a leap year. We could use one of the readily available expressions, or we could let the JavaScript date object do it for us. For example:
function isLeapYear( y ) { return ( new Date( y, 1, 29 ).getDate() == 29 );}
This simply tries to create a date object for Feb 29 of a specified year. If the result isn't on the 29th, then it isn't a leap year, and the function returns false.
So, to determine the number of leap days between two particular days, we need something like this, which handles the starting and ending dates differently.
So adding the above to the calculations found in technique #2, we find that 8 leap days exist between the two dates. So, the total difference, as calculated by technique #2 is:
Our community of experts have been thoroughly vetted for their expertise and industry experience. Experts with Gold status have received one of our highest-level Expert Awards, which recognize experts for their valuable contributions.
Here is the standard way to create a date
var date = new Date(2009,11,1,0,0,0); // months start at 0
And before you compare dates like
var today = new Date(); // today
var someDate(2009,11,2);
you should normalise such dates by doing
today.setHours(0,0,0,0); // set hours, minutes, seconds and milliseconds to 0
so you can test
if (someDate.getTime() > today.getTime()) ....
this is great, thanks. What about when the dates are in "short" format, providing time in 12-hour AM/PM format? (e.g. dd/mm/yyy hh:mm TT - 01/06/16 01:43 PM) How would you subtract date and time in that case?
Have a question about something in this article?
You can receive help directly from the article author.
Sign up for a free trial to get started.
Comments (4)
Commented:
Commented:
var date = new Date(2009,11,1,0,0,0); // months start at 0
And before you compare dates like
var today = new Date(); // today
var someDate(2009,11,2);
you should normalise such dates by doing
today.setHours(0,0,0,0); // set hours, minutes, seconds and milliseconds to 0
so you can test
if (someDate.getTime() > today.getTime()) ....
Author
Commented:I had not realized that setHours() also had optional parameters for minutes, seconds & milliseconds!
Thanks
Bob
Commented: