[javascript] Difference in Months between two dates in JavaScript

How would I work out the difference for two Date() objects in JavaScript, while only return the number of months in the difference?

Any help would be great :)

This question is related to javascript date datediff

The answer is


Number Of Months When Day & Time Doesn't Matter

In this case, I'm not concerned with full months, part months, how long a month is, etc. I just need to know the number of months. A relevant real world case would be where a report is due every month, and I need to know how many reports there should be.

Example:

  • January = 1 month
  • January - February = 2 months
  • November - January = 3 months

This is an elaborated code example to show where the numbers are going.

Let's take 2 timestamps that should result in 4 months

  • November 13, 2019's timestamp: 1573621200000
  • February 20, 2020's timestamp: 1582261140000

May be slightly different with your timezone / time pulled. The day, minutes, and seconds don't matter and can be included in the timestamp, but we will disregard it with our actual calculation.

Step 1: convert the timestamp to a JavaScript date

let dateRangeStartConverted = new Date(1573621200000);
let dateRangeEndConverted = new Date(1582261140000);

Step 2: get integer values for the months / years

let startingMonth = dateRangeStartConverted.getMonth();
let startingYear = dateRangeStartConverted.getFullYear();
let endingMonth = dateRangeEndConverted.getMonth();
let endingYear = dateRangeEndConverted.getFullYear();

This gives us

  • Starting month: 11
  • Starting Year: 2019
  • Ending month: 2
  • Ending Year: 2020

Step 3: Add (12 * (endYear - startYear)) + 1 to the ending month.

  • This makes our starting month stay at 11
  • This makes our ending month equal 15 2 + (12 * (2020 - 2019)) + 1 = 15

Step 4: Subtract the months

15 - 11 = 4; we get our 4 month result.

29 Month Example Example

November 2019 through March 2022 is 29 months. If you put these into an excel spreadsheet, you will see 29 rows.

  • Our starting month is 11
  • Our ending month is 40 3 + (12 * (2022-2019)) + 1

40 - 11 = 29


If you need to count full months, regardless of the month being 28, 29, 30 or 31 days. Below should work.

var months = to.getMonth() - from.getMonth() 
    + (12 * (to.getFullYear() - from.getFullYear()));

if(to.getDate() < from.getDate()){
    months--;
}
return months;

This is an extended version of the answer https://stackoverflow.com/a/4312956/1987208 but fixes the case where it calculates 1 month for the case from 31st of January to 1st of February (1day).

This will cover the following;

  • 1st Jan to 31st Jan ---> 30days ---> will result in 0 (logical since it is not a full month)
  • 1st Feb to 1st Mar ---> 28 or 29 days ---> will result in 1 (logical since it is a full month)
  • 15th Feb to 15th Mar ---> 28 or 29 days ---> will result in 1 (logical since a month passed)
  • 31st Jan to 1st Feb ---> 1 day ---> will result in 0 (obvious but the mentioned answer in the post results in 1 month)

One approach would be to write a simple Java Web Service (REST/JSON) that uses JODA library

http://joda-time.sourceforge.net/faq.html#datediff

to calculate difference between two dates and call that service from javascript.

This assumes your back end is in Java.


I know this is really late, but posting it anyway just in case it helps others. Here is a function I came up with that seems to do a good job of counting differences in months between two dates. It is admittedly a great deal raunchier than Mr.Crowder's, but provides more accurate results by stepping through the date object. It is in AS3 but you should just be able to drop the strong typing and you'll have JS. Feel free to make it nicer looking anyone out there!

    function countMonths ( startDate:Date, endDate:Date ):int
    {
        var stepDate:Date = new Date;
        stepDate.time = startDate.time;
        var monthCount:int;

        while( stepDate.time <= endDate.time ) { 
            stepDate.month += 1;
            monthCount += 1;
        }           

        if ( stepDate != endDate ) { 
            monthCount -= 1;
        }

        return monthCount;
    }

function monthDiff(d1, d2) {
var months, d1day, d2day, d1new, d2new, diffdate,d2month,d2year,d1maxday,d2maxday;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
months += d2.getMonth();
months = (months <= 0 ? 0 : months);
d1day = d1.getDate();
d2day = d2.getDate();
if(d1day > d2day)
{
    d2month = d2.getMonth();
    d2year = d2.getFullYear();
    d1new = new Date(d2year, d2month-1, d1day,0,0,0,0);
    var timeDiff = Math.abs(d2.getTime() - d1new.getTime());
          diffdate = Math.abs(Math.ceil(timeDiff / (1000 * 3600 * 24))); 
    d1new = new Date(d2year, d2month, 1,0,0,0,0);
    d1new.setDate(d1new.getDate()-1);
    d1maxday = d1new.getDate();
    months += diffdate / d1maxday;
}
else
{
      if(!(d1.getMonth() == d2.getMonth() && d1.getFullYear() == d2.getFullYear()))
    {
        months += 1;
    }
    diffdate = d2day - d1day + 1;
    d2month = d2.getMonth();
    d2year = d2.getFullYear();
    d2new = new Date(d2year, d2month + 1, 1, 0, 0, 0, 0);
    d2new.setDate(d2new.getDate()-1);
    d2maxday = d2new.getDate();
    months += diffdate / d2maxday;
}

return months;

}


anyVar = (((DisplayTo.getFullYear() * 12) + DisplayTo.getMonth()) - ((DisplayFrom.getFullYear() * 12) + DisplayFrom.getMonth()));

function calcualteMonthYr(){
    var fromDate =new Date($('#txtDurationFrom2').val()); //date picker (text fields)
    var toDate = new Date($('#txtDurationTo2').val());

var months=0;
        months = (toDate.getFullYear() - fromDate.getFullYear()) * 12;
        months -= fromDate.getMonth();
        months += toDate.getMonth();
            if (toDate.getDate() < fromDate.getDate()){
                months--;
            }
    $('#txtTimePeriod2').val(months);
}

below logic will fetch difference in months

(endDate.getFullYear()*12+endDate.getMonth())-(startDate.getFullYear()*12+startDate.getMonth())

Here you go other approach with less looping:

calculateTotalMonthsDifference = function(firstDate, secondDate) {
        var fm = firstDate.getMonth();
        var fy = firstDate.getFullYear();
        var sm = secondDate.getMonth();
        var sy = secondDate.getFullYear();
        var months = Math.abs(((fy - sy) * 12) + fm - sm);
        var firstBefore = firstDate > secondDate;
        firstDate.setFullYear(sy);
        firstDate.setMonth(sm);
        firstBefore ? firstDate < secondDate ? months-- : "" : secondDate < firstDate ? months-- : "";
        return months;
}

You could also consider this solution, this function returns the month difference in integer or number

Passing the start date as the first or last param, is fault tolerant. Meaning, the function would still return the same value.

_x000D_
_x000D_
const diffInMonths = (end, start) => {_x000D_
   var timeDiff = Math.abs(end.getTime() - start.getTime());_x000D_
   return Math.round(timeDiff / (2e3 * 3600 * 365.25));_x000D_
}_x000D_
_x000D_
const result = diffInMonths(new Date(2015, 3, 28), new Date(2010, 1, 25));_x000D_
_x000D_
// shows month difference as integer/number_x000D_
console.log(result);
_x000D_
_x000D_
_x000D_


Calculate the difference between two dates include fraction of month (days).


var difference = (date2.getDate() - date1.getDate()) / 30 +
    date2.getMonth() - date1.getMonth() +
    (12 * (date2.getFullYear() - date1.getFullYear()));

For example:
date1: 24/09/2015 (24th Sept 2015)
date2: 09/11/2015 (9th Nov 2015)
the difference: 2.5 (months)


It also counts the days and convert them in months.

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;   //calculates months between two years
    months -= d1.getMonth() + 1; 
    months += d2.getMonth();  //calculates number of complete months between two months
    day1 = 30-d1.getDate();  
    day2 = day1 + d2.getDate();
    months += parseInt(day2/30);  //calculates no of complete months lie between two dates
    return months <= 0 ? 0 : months;
}

monthDiff(
    new Date(2017, 8, 8), // Aug 8th, 2017    (d1)
    new Date(2017, 12, 12)  // Dec 12th, 2017   (d2)
);
//return value will be 4 months 

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;

This should work fine:

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

I like not to reinvent a wheel keep it simple (I mean not to care about the number of days in months, the leap year, etc.) and use date-fns lib, thus

 npm install -s date-fns

and

const differenceInMonths = require('date-fns/differenceInMonths')

;(() => {
    console.log(differenceInMonths(new Date(`2015-12-01`), new Date(`2013-12-01`)))
    console.log(differenceInMonths(new Date(1582261140000), new Date(`2014-12-01`)))
    console.log(differenceInMonths(new Date(1582261140000), new Date(1573621200000)))
})()

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

_x000D_
_x000D_
function monthDiff(dateFrom, dateTo) {_x000D_
 return dateTo.getMonth() - dateFrom.getMonth() + _x000D_
   (12 * (dateTo.getFullYear() - dateFrom.getFullYear()))_x000D_
}_x000D_
_x000D_
_x000D_
//examples_x000D_
console.log(monthDiff(new Date(2000, 01), new Date(2000, 02))) // 1_x000D_
console.log(monthDiff(new Date(1999, 02), new Date(2000, 02))) // 12 full year_x000D_
console.log(monthDiff(new Date(2009, 11), new Date(2010, 0))) // 1
_x000D_
_x000D_
_x000D_

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


getMonthDiff(d1, d2) {
    var year1 = dt1.getFullYear();
    var year2 = dt2.getFullYear();
    var month1 = dt1.getMonth();
    var month2 = dt2.getMonth();
    var day1 = dt1.getDate();
    var day2 = dt2.getDate();
    var months = month2 - month1;
    var years = year2 -year1
    days = day2 - day1;
    if (days < 0) {
        months -= 1;
    }
    if (months < 0) {
        months += 12;
    }
    return months + years*!2;
}

function monthDiff(date1, date2, countDays) {

  countDays = (typeof countDays !== 'undefined') ?  countDays : false;

  if (!date1 || !date2) {
    return 0;
  }

  let bigDate = date1;
  let smallDate = date2;

  if (date1 < date2) {
    bigDate = date2;
    smallDate = date1;
  }

  let monthsCount = (bigDate.getFullYear() - smallDate.getFullYear()) * 12 + (bigDate.getMonth() - smallDate.getMonth());

  if (countDays && bigDate.getDate() < smallDate.getDate()) {
    --monthsCount;
  }

  return monthsCount;
}

Following code returns full months between two dates by taking nr of days of partial months into account as well.

var monthDiff = function(d1, d2) {
  if( d2 < d1 ) { 
    var dTmp = d2;
    d2 = d1;
    d1 = dTmp;
  }

  var months = (d2.getFullYear() - d1.getFullYear()) * 12;
  months -= d1.getMonth() + 1;
  months += d2.getMonth();

  if( d1.getDate() <= d2.getDate() ) months += 1;

  return months;
}

monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 20))
> 1

monthDiff(new Date(2015, 01, 20), new Date(2015, 02, 19))
> 0

monthDiff(new Date(2015, 01, 20), new Date(2015, 01, 22))
> 0

Any value is returned along with its absolute value.

function differenceInMonths(firstDate, secondDate) {
    if (firstDate > secondDate) [firstDate, secondDate] = [secondDate, firstDate];
    let diffMonths = (secondDate.getFullYear() - firstDate.getFullYear()) * 12;
    diffMonths -= firstDate.getMonth();
    diffMonths += secondDate.getMonth();
    return diffMonths;
}
 

To expand on @T.J.'s answer, if you're looking for simple months, rather than full calendar months, you could just check if d2's date is greater than or equal to than d1's. That is, if d2 is later in its month than d1 is in its month, then there is 1 more month. So you should be able to just do this:

function monthDiff(d1, d2) {
    var months;
    months = (d2.getFullYear() - d1.getFullYear()) * 12;
    months -= d1.getMonth() + 1;
    months += d2.getMonth();
    // edit: increment months if d2 comes later in its month than d1 in its month
    if (d2.getDate() >= d1.getDate())
        months++
    // end edit
    return months <= 0 ? 0 : months;
}

monthDiff(
    new Date(2008, 10, 4), // November 4th, 2008
    new Date(2010, 2, 12)  // March 12th, 2010
);
// Result: 16; 4 Nov – 4 Dec '08, 4 Dec '08 – 4 Dec '09, 4 Dec '09 – 4 March '10

This doesn't totally account for time issues (e.g. 3 March at 4:00pm and 3 April at 3:00pm), but it's more accurate and for just a couple lines of code.


Consider each date in terms of months, then subtract to find the difference.

var past_date = new Date('11/1/2014');
var current_date = new Date();

var difference = (current_date.getFullYear()*12 + current_date.getMonth()) - (past_date.getFullYear()*12 + past_date.getMonth());

This will get you the difference of months between the two dates, ignoring the days.


There are two approaches, mathematical & quick, but subject to vagaries in the calendar, or iterative & slow, but handles all the oddities (or at least delegates handling them to a well-tested library).

If you iterate through the calendar, incrementing the start date by one month & seeing if we pass the end date. This delegates anomaly-handling to the built-in Date() classes, but could be slow IF you're doing this for a large number of dates. James' answer takes this approach. As much as I dislike the idea, I think this is the "safest" approach, and if you're only doing one calculation, the performance difference really is negligible. We tend to try to over-optimize tasks which will only be performed once.

Now, if you're calculating this function on a dataset, you probably don't want to run that function on each row (or god forbid, multiple times per record). In that case, you can use almost any of the other answers here except the accepted answer, which is just wrong (difference between new Date() and new Date() is -1)?

Here's my stab at a mathematical-and-quick approach, which accounts for differing month lengths and leap years. You really should only use a function like this if you'll be applying this to a dataset (doing this calculation over & over). If you just need to do it once, use James' iterative approach above, as you're delegating handling all the (many) exceptions to the Date() object.

function diffInMonths(from, to){
    var months = to.getMonth() - from.getMonth() + (12 * (to.getFullYear() - from.getFullYear()));

    if(to.getDate() < from.getDate()){
        var newFrom = new Date(to.getFullYear(),to.getMonth(),from.getDate());
        if (to < newFrom  && to.getMonth() == newFrom.getMonth() && to.getYear() %4 != 0){
            months--;
        }
    }

    return months;
}

See what I use:

function monthDiff() {
    var startdate = Date.parseExact($("#startingDate").val(), "dd/MM/yyyy");
    var enddate = Date.parseExact($("#endingDate").val(), "dd/MM/yyyy");
    var months = 0;
    while (startdate < enddate) {
        if (startdate.getMonth() === 1 && startdate.getDate() === 28) {
            months++;
            startdate.addMonths(1);
            startdate.addDays(2);
        } else {
            months++;
            startdate.addMonths(1);
        }
    }
    return months;
}

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

Difference in Months between two dates in JavaScript:

 start_date = new Date(year, month, day); //Create start date object by passing appropiate argument
 end_date = new Date(new Date(year, month, day)

total months between start_date and end_date :

 total_months = (end_date.getFullYear() - start_date.getFullYear())*12 + (end_date.getMonth() - start_date.getMonth())

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to date

How do I format {{$timestamp}} as MM/DD/YYYY in Postman? iOS Swift - Get the Current Local Time and Date Timestamp Typescript Date Type? how to convert current date to YYYY-MM-DD format with angular 2 SQL Server date format yyyymmdd Date to milliseconds and back to date in Swift Check if date is a valid one change the date format in laravel view page Moment js get first and last day of current month How can I convert a date into an integer?

Examples related to datediff

DATEDIFF function in Oracle How to calculate DATE Difference in PostgreSQL? How to convert number of minutes to hh:mm format in TSQL? Difference between two dates in years, months, days in JavaScript Number of days between past date and current date in Google spreadsheet How to compare two dates to find time difference in SQL Server 2005, date manipulation SQL Server Group By Month How do I check the difference, in seconds, between two dates? Date difference in years using C# Difference in days between two dates in Java?