# 2 Dates - What's the difference?

Published:
Updated:
A common challenge, or question, when working with two calendar dates is:

What is the difference between the specified days?

As is frequently the case, the answer is: It depends...

What kind of difference do you want?

Given two date objects, you can simply subtract one from the other to get a difference.

``````  var day1 = new Date( '2/29/2000 23:59:58' );
var day2 = new Date( 'Feb 27, 2009 00:00:00' );
``````

This causes us to ask: What does the displayed value (283824002000) represent?
It's the number of milliseconds between the specified dates & times.

Is there an easy way to convert this into something useable?
Sure.  This works reasonably well:

Technique #1
``````  var day1 = new Date( '2/29/2000 23:59:58' );
var day2 = new Date( 'Feb 27, 2009 00:00:00' );
var units = 'Years,Days,Hours,Minutes,Seconds'.split( ',' );
var vals = [ 365 * 24 * 60 * 60, 24 * 60 * 60, 60 * 60, 60 ];
var msg  = '';
var secs = Math.abs( Math.floor( ( day2 - day1 ) / 1000 ) );
for ( var i = 0; i < vals.length; i++ ) {
var result = Math.floor( secs / vals[ i ] );
if ( result ) {
msg += '\n' + units[ i ] + ' ' + result;
}
secs -= result * vals[ i ];
}
if ( secs ) {
msg += '\n' + units[ i ] + ' ' + secs;
}
``````

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:

``````alert( new Date( 2009, 2, 0 ) );
``````

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:

``````Difference = 31 Years 70 Days 12 Hours 2 Seconds
``````

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.

Computing the number of Leap Days
``````var leapdays = 0;
if ( ( day1.getMonth() < 2 ) && ( day1.getDate() < 29 ) )  {
if ( isLeapYear( day1.getFullYear() ) ) {
leapdays++;
}
}
for ( var year = day1.getFullYear() + 1; year < day2.getFullYear(); year++  ) {
if ( isLeapYear( year ) ) {
leapdays++;
}
}
if ( isLeapYear( day2.getFullYear() ) && ( ( day2.getMonth() > 1 ) || ( ( day2.getMonth() == 1 ) && ( day2.getDate() > 28 ) ) ) ) {
leapdays++;
}
``````

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:

``````Years: 31
Months: 2
Days : 0
Hours: 12
Minutes: 0
Seconds :  2
Leap Days: 8
``````

Sample pages are available below.
Technique-1.html.txt
Technique-2.html.txt
Technique-2b.html.txt

5
5,145 Views

Chief Technology Officer
CERTIFIED EXPERT
Most Valuable Expert 2011

Commented:
Another nice article, HonorGod; you have my vote on this one above also!
IT Expert
CERTIFIED EXPERT
Top Expert 2009

Commented:
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()) ....
Software Engineer
CERTIFIED EXPERT

Commented:
Michel:

I had not realized that setHours() also had optional parameters for minutes, seconds & milliseconds!

Thanks
Bob
CEO

Commented:
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?