I am trying to work out a difference in months between two dates without taking days into consideration.
I was trying to use Math.ceil
but if the day in 2022 was ahead of the one in 2021 then I got 2 months instead of 1 month difference.
const diff = moment([2022, 0, 1]).diff(moment([2021, 11, 3]), 'months', true);
console.log(diff); // 0.935483870967742, expected 1
const diffCeil = Math.ceil(
moment([2022, 0, 3]).diff(moment([2021, 11, 1]), 'months', true)
);
console.log('diffCeil', diffCeil); // 2, expected 1
// Inaccurate diff doesn't work when 2021 day is bigger than in 2022
const inacurrateDiff = moment([2022, 0, 3]).diff(moment([2021, 11, 1]), 'months');
console.log('inacurrateDiff', inacurrateDiff); // 1, as expected
const inacurrateDiff2 = moment([2022, 0, 1]).diff(moment([2021, 11, 3]), 'months');
console.log('inacurrateDiff2', inacurrateDiff2); // 0, expected 1
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.3/moment.min.js"></script>
I did try it with and without diff
's third precise
parameter.
CodePudding user response:
You get 2 because you're using Math.ceil
, which always raises the fractional value to the next whole number.
There's no one right answer here, you'll have to decide how much of a fractional month you want to count.
For instance, if you want only whole months, use Math.floor
rather than Math.ceil
. If you want to count anything up to 1.5 months as one but 1.5 months and above as 2, use Math.round
. Or you could set your own threshold, like 1.2 (it's a bit more work, but not that much).
Examples:
function example(date1, date2) {
const rawDiff = date1.diff(date2, "months", true);
const diffFloored = Math.floor(rawDiff);
const diffRounded = Math.round(rawDiff);
const diffCeiled = Math.ceil(rawDiff);
const neg = rawDiff < 0;
const fractional = neg
? rawDiff Math.trunc(rawDiff)
: rawDiff - Math.trunc(rawDiff);
const diffOnePointTwo = Math.abs(fractional) > 0.2
? Math.ceil(rawDiff)
: Math.floor(rawDiff);
console.log({
date1: date1.toString(),
date2: date2.toString(),
rawDiff,
diffFloored,
diffRounded,
diffCeiled,
diffOnePointTwo,
});
}
example(
moment([2022, 0, 1]),
moment([2021, 11, 3])
);
example(
moment([2022, 0, 3]),
moment([2021, 11, 1])
);
example(
moment([2022, 0, 10]),
moment([2021, 11, 1])
);
.as-console-wrapper {
max-height: 100% !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.3/moment.min.js"></script>
Only you and your project can say what definition you want to use.
CodePudding user response:
You could use startOf(d, 'month')
to compare start of months:
a.startOf('month').diff(b.startOf('month'), 'month');