moment.js fromNow() gives 1 day less if more than 30 days

91 Views Asked by At

I have following custom javascript function to get duration in days/hours/minutes -

daysFromNow(time) {
    let oldThreshold = <number>Moment.relativeTimeThreshold('d');

    try {
        Moment.relativeTimeThreshold('m', 60);
        Moment.relativeTimeThreshold('h', 24);
        Moment.relativeTimeThreshold('d', 999999);
        return Moment(time).fromNow();
     } finally {
        Moment.relativeTimeThreshold('d', oldThreshold);
     }
   }

Now

console.log(daysFromNow('2024-01-11T23:59:59.000+10:30')); // gives 'in 29 days'
console.log(daysFromNow('2024-01-12T23:59:59.000+10:30')); // gives 'in 30 days'
console.log(daysFromNow('2024-01-13T23:59:59.000+10:30')); // gives 'in 30 days', should be 31
console.log(daysFromNow('2024-01-14T15:10:59.000+10:30')) // gives 'in 31 days' - should be 32

Not sure where I did the wrong. Is that something about timezone?

1

There are 1 best solutions below

0
On

For your specific case, I would suggest using the startOf() method to normalize the time to the start of the day and then comparing the difference.

function daysFromNow(time) {
  let oldThreshold = moment.relativeTimeThreshold("d");

  try {
    moment.relativeTimeThreshold("m", 60);
    moment.relativeTimeThreshold("h", 24);
    moment.relativeTimeThreshold("d", 999999);

    let currentTime = moment().startOf("day");
    let inputTime = moment(time).startOf("day");
    // ensures that the difference between the two times is calculated in whole days.

    return moment.duration(inputTime.diff(currentTime)).humanize(true);
  } finally {
    moment.relativeTimeThreshold("d", oldThreshold);
  }
}

console.log(daysFromNow("2024-01-11T23:59:59.000+10:30"));
console.log(daysFromNow("2024-01-12T23:59:59.000+10:30"));
console.log(daysFromNow("2024-01-13T23:59:59.000+10:30"));
console.log(daysFromNow("2024-01-14T15:10:59.000+10:30"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>

NOTE: There are other alternatives of using momentjs library which is recommended by the momentjs docs itself. For your specific case, I would be tilted to use Intl object which is natively introduced in Javascript. So, you might want to take a look at this as well.