<

2 Dates - What's the difference?

Published on
13,298 Points
4,798 Views
5 Endorsements
Last Modified:
Approved
Community Pick
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' );
  alert( day2 - day1 )

Open in new window


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;
  }
  alert( msg.substr( 1 ) );

Open in new window


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 ) );

Open in new window


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 ] );
    }
  }
}

Open in new window


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

Open in new window


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 );
}

Open in new window


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++;
}

Open in new window


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

Open in new window


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

Hopefully you find this article, and these samples helpful...  
5
Comment
Author:HonorGod
4 Comments
LVL 61

Expert Comment

by:Kevin Cross
Another nice article, HonorGod; you have my vote on this one above also!
0
LVL 75

Expert Comment

by:Michel Plungjan
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()) ....
0
LVL 41

Author Comment

by:HonorGod
Michel:

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

Thanks
Bob
0

Expert Comment

by:websss
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?
0

Featured Post

Cloud Class® Course: C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

Join & Write a Comment

The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month