Difference in Months between two dates in JavaScript

The definition of "the number of months in the difference" is subject to a lot of interpretation. :-)

You can get the year, month, and day of month from a JavaScript date object. Depending on what information you're looking for, you can use those to figure out how many months are between two points in time.

For instance, off-the-cuff:

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months -= d1.getMonth();
    months += d2.getMonth();
    return months <= 0 ? 0 : months;
}

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months -= d1.getMonth();
    months += d2.getMonth();
    return months <= 0 ? 0 : months;
}

function test(d1, d2) {
    var diff = monthDiff(d1, d2);
    console.log(
        d1.toISOString().substring(0, 10),
        "to",
        d2.toISOString().substring(0, 10),
        ":",
        diff
    );
}

test(
    new Date(2008, 10, 4), // November 4th, 2008
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 16

test(
    new Date(2010, 0, 1),  // January 1st, 2010
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 2

test(
    new Date(2010, 1, 1),  // February 1st, 2010
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 1

(Note that month values in JavaScript start with 0 = January.)

Including fractional months in the above is much more complicated, because three days in a typical February is a larger fraction of that month (~10.714%) than three days in August (~9.677%), and of course even February is a moving target depending on whether it's a leap year.

There are also some date and time libraries available for JavaScript that probably make this sort of thing easier.


Note: There used to be a + 1 in the above, here:

months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
// −−−−−−−−−−−−−−−−−−−−^^^^
months += d2.getMonth();

That's because originally I said:

...this finds out how many full months lie between two dates, not counting partial months (e.g., excluding the month each date is in).

I've removed it for two reasons:

  1. Not counting partial months turns out not to be what many (most?) people coming to the answer want, so I thought I should separate them out.

  2. It didn't always work even by that definition. :-D (Sorry.)


Sometimes you may want to get just the quantity of the months between two dates totally ignoring the day part. So for instance, if you had two dates- 2013/06/21 and 2013/10/18- and you only cared about the 2013/06 and 2013/10 parts, here are the scenarios and possible solutions:

var date1=new Date(2013,5,21);//Remember, months are 0 based in JS
var date2=new Date(2013,9,18);
var year1=date1.getFullYear();
var year2=date2.getFullYear();
var month1=date1.getMonth();
var month2=date2.getMonth();
if(month1===0){ //Have to take into account
  month1++;
  month2++;
}
var numberOfMonths; 

1.If you want just the number of the months between the two dates excluding both month1 and month2

numberOfMonths = (year2 - year1) * 12 + (month2 - month1) - 1;

2.If you want to include either of the months

numberOfMonths = (year2 - year1) * 12 + (month2 - month1);

3.If you want to include both of the months

numberOfMonths = (year2 - year1) * 12 + (month2 - month1) + 1;

Here's a function that accurately provides the number of months between 2 dates.
The default behavior only counts whole months, e.g. 3 months and 1 day will result in a difference of 3 months. You can prevent this by setting the roundUpFractionalMonths param as true, so a 3 month and 1 day difference will be returned as 4 months.

The accepted answer above (T.J. Crowder's answer) isn't accurate, it returns wrong values sometimes.

For example, monthDiff(new Date('Jul 01, 2015'), new Date('Aug 05, 2015')) returns 0 which is obviously wrong. The correct difference is either 1 whole month or 2 months rounded-up.

Here's the function I wrote:

function getMonthsBetween(date1,date2,roundUpFractionalMonths)
{
    //Months will be calculated between start and end dates.
    //Make sure start date is less than end date.
    //But remember if the difference should be negative.
    var startDate=date1;
    var endDate=date2;
    var inverse=false;
    if(date1>date2)
    {
        startDate=date2;
        endDate=date1;
        inverse=true;
    }

    //Calculate the differences between the start and end dates
    var yearsDifference=endDate.getFullYear()-startDate.getFullYear();
    var monthsDifference=endDate.getMonth()-startDate.getMonth();
    var daysDifference=endDate.getDate()-startDate.getDate();

    var monthCorrection=0;
    //If roundUpFractionalMonths is true, check if an extra month needs to be added from rounding up.
    //The difference is done by ceiling (round up), e.g. 3 months and 1 day will be 4 months.
    if(roundUpFractionalMonths===true && daysDifference>0)
    {
        monthCorrection=1;
    }
    //If the day difference between the 2 months is negative, the last month is not a whole month.
    else if(roundUpFractionalMonths!==true && daysDifference<0)
    {
        monthCorrection=-1;
    }

    return (inverse?-1:1)*(yearsDifference*12+monthsDifference+monthCorrection);
};

If you do not consider the day of the month, this is by far the simpler solution

function monthDiff(dateFrom, dateTo) {
 return dateTo.getMonth() - dateFrom.getMonth() + 
   (12 * (dateTo.getFullYear() - dateFrom.getFullYear()))
}


//examples
console.log(monthDiff(new Date(2000, 01), new Date(2000, 02))) // 1
console.log(monthDiff(new Date(1999, 02), new Date(2000, 02))) // 12 full year
console.log(monthDiff(new Date(2009, 11), new Date(2010, 0))) // 1

Be aware that month index is 0-based. This means that January = 0 and December = 11.