Moment.js months difference

JavascriptMomentjs

Javascript Problem Overview


I've been using moment.js for a short while now, and it's made date manipulation a lot easier but I have a specific case that is failing, and I can't see why.

When calculating the diff between today (31st October 2013) and the 1st February 2014, the months diff comes back as 2, although there are 3 complete months and one day between the two dates.

Diff between 31st October and 31st January works fine: 3 months and zero days.

var mStartDate = moment([ periodStartDate.getFullYear(), periodStartDate.getMonth(), periodStartDate.getDate() ]);
var mTermDate = moment([ someDate.getFullYear(), someDate.getMonth(), someDate.getDate() ]);
	
console.log('periodStartDate: ' + periodStartDate);
console.log('someDate: ' + someDate);

// Years
var yearsDiff = mTermDate.diff(mStartDate, 'years');
	
// Months
var monthsDiff = mTermDate.diff(mStartDate, 'months', true);

The console logs the following:

periodStartDate: Thu Oct 31 2013 11:13:51 GMT+0000 (GMT)
someDate: Sat Feb 01 2014 11:13:51 GMT+0000 (GMT)
monthsDiff: 2

If I pass true as the boolean not to round, the months diff is

monthsDiff: 2.983050847457627 

Is this just a bug in Moment.js.diff()? Every single one of my other test cases pass successfully.

Javascript Solutions


Solution 1 - Javascript

I think this has to do with the 'special handling' as described in The Fine Manual:

> It is optimized to ensure that two months with the same date are > always a whole number apart. > > So Jan 15 to Feb 15 should be exactly 1 month. > > Feb 28 to Mar 28 should be exactly 1 month. > > Feb 28 2011 to Feb 28 2012 should be exactly 1 year.

Moment.js applies this special handling when dealing with 31 Jan and 31 Oct (having the same day):

// 31 Oct 2013 - 1 Feb 2014
> moment([2014, 1, 1]).diff(moment([2013, 9, 31]), 'months', true)
2.983050847457627

// 31 Oct 2013 - 31 Jan 2014
> moment([2014, 0, 31]).diff(moment([2013, 9, 31]), 'months', true)
3

// 31 Oct 2013 - 30 Jan 2014
> moment([2014, 0, 30]).diff(moment([2013, 9, 31]), 'months', true)
2.967741935483871

So the 2.98 value is correct, it's just that the second example turns the result into a 'calender months' difference.

(as for rounding down to 2, that's also documented on the same page)

Solution 2 - Javascript

I went a different route trying to get the difference between two months

function getAbsoluteMonths(momentDate) {
  var months = Number(momentDate.format("MM"));
  var years = Number(momentDate.format("YYYY"));
  return months + (years * 12);
}

var startMonths = getAbsoluteMonths(start);
var endMonths = getAbsoluteMonths(end);

var monthDifference = endMonths - startMonths;

This made sense to me and since moment is doing some strange things with diff I just decided to make it clear what my result will be.

Solution 3 - Javascript

Simple And Easy Solution with correct value difference between two months if you are using moment Library

  const monthDifference =  moment(new Date(endDate)).diff(new Date(startDate), 'months', true);

If you want to add the number of days in endDate

 const monthDifference = moment(new Date(endDate.add(1, 'days'))).diff(new Date(startDate), 'months', true);

Solution 4 - Javascript

Try out this method;

function getMonthDifference(startDate, endDate) {
    const increment = startDate.getMonth() === endDate.getMonth() ? 2 : 1;
    const diff = moment(endDate).diff(moment(startDate), 'months', true);
    return Math.ceil(diff) + increment;    // this increment is opitional and totally depends on your need.
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKhainView Question on Stackoverflow
Solution 1 - JavascriptrobertklepView Answer on Stackoverflow
Solution 2 - JavascriptMrBView Answer on Stackoverflow
Solution 3 - JavascriptGaurav vermaView Answer on Stackoverflow
Solution 4 - JavascriptArsman AhmadView Answer on Stackoverflow