Skip to content Skip to sidebar Skip to footer

What Is The Source Of This Off-by-one Error In A Javascript Date?

I am trying to write a function that will take a string like 07/2020 and then return whether it is more than three months away. I have written a function isMoreThan3MonthsHence tha

Solution 1:

It looks like you're mixing the usage of Date.UTC and not when instantiating dates. For example, if you use the following for your validate function:

const validate = (str, 
                  [month, year] = str.split('/'), 
                  date = newDate(Date.UTC(+year, (+month)-1))) => 
    isMoreThan3MonthsHence({ utcYear: date.getUTCFullYear(), utcMonth: date.getUTCMonth() })

// Note: input is one-based monthsconsole.log(validate('07/2020')) // Now true

It works as expected: JSFiddle

Removing the usage of Date.UTC altogether would perform the calculation in the user's local timezone, with any applicable daylight saving adjustment included. This could be seen as a valid approach, however would result in the behaviour you have described.


Note I've renamed the local prefixed variables based on feedback from Bergi. Using Date.UTC implies you're passing in UTC arguments.

Solution 2:

Other than mixing UTC and local dates, the way you're adding 3 months will cause an incorrect response for dates like 31 March, where adding 3 months simply by incrementing the month number results in a date for 1 July. See Adding months to a Date in JavaScript.

So validate('07,2020') will return false if run on 31 March.

To fix that, when adding months, check that the updated date is still on the same day in the month, otherwise it's rolled over so set it to the last day of the previous month.

functionvalidate(s) {
  let testDate = addMonths(newDate(), 3);
  let [m, y] = s.split(/\D/);
  return testDate < newDate(y, m-1);
};

functionaddMonths(date, months) {
  let d = date.getDate();
  date.setMonth(date.getMonth() + +months);
  // If rolled over to next month, set to last day of previous monthif (date.getDate() != d) {
    date.setDate(0);
  }
  return date;
}

// Sampleconsole.log('On ' + newDate().toDateString() + ':');
['07/2020', '04/2020'].forEach(
  s =>console.log(s + ' - ' + validate(s))
);

Post a Comment for "What Is The Source Of This Off-by-one Error In A Javascript Date?"