Search code examples
javascriptdatecalendar

How to increment days in JavaScript ignoring time zones and daylight saving time?


Given a date (no time) in an ISO8601 format (e.g. 2022-10-01), how could I reliably increment a given amount of days to it and get back the same ISO8601 format?

I tried the approach below but it fails due to time zones / daylight saving time:

function incrementDays(dateStr, daysToIncrement) {
  const dateAtUTC = new Date(`${dateStr}T00:00:00.000Z`);

  dateAtUTC.setDate(dateAtUTC.getDate() + daysToIncrement);

  return dateAtUTC.toISOString().slice(0, 10);
}

const tests = [{
    dateStr: "2022-04-01",
    daysToIncrement: 10,
    expectedResult: "2022-04-11"
  },
  {
    dateStr: "2022-10-01",
    daysToIncrement: 1,
    expectedResult: "2022-10-02" // This is failing with "2022-10-01"
  },
  {
    dateStr: "2020-02-29",
    daysToIncrement: 3,
    expectedResult: "2020-03-03"
  },
]

tests.forEach(({
  dateStr,
  daysToIncrement,
  expectedResult
}) => {
  const result = incrementDays(dateStr, daysToIncrement);

  if (result === expectedResult) {
    console.log("PASSED", `${dateStr} + ${daysToIncrement} = ${result}`)
  } else {
    console.log("FAILED", `${dateStr} + ${daysToIncrement} = ${result} (expected: ${expectedResult})`)
  }
})


Solution

  • use .setUTCDate and .getUTCDate instead

    function incrementDays(dateStr, daysToIncrement) {
      const dateAtUTC = new Date(`${dateStr}T00:00:00.000Z`);
    
      dateAtUTC.setUTCDate(dateAtUTC.getUTCDate() + daysToIncrement);
    
      return dateAtUTC.toISOString().slice(0, 10);
    }
    
    const tests = [{
        dateStr: "2022-04-01",
        daysToIncrement: 10,
        expectedResult: "2022-04-11"
      },
      {
        dateStr: "2022-10-01",
        daysToIncrement: 1,
        expectedResult: "2022-10-02" // This is failing with "2022-10-01"
      },
      {
        dateStr: "2020-02-29",
        daysToIncrement: 3,
        expectedResult: "2020-03-03"
      },
    ]
    
    tests.forEach(({
      dateStr,
      daysToIncrement,
      expectedResult
    }) => {
      const result = incrementDays(dateStr, daysToIncrement);
    
      if (result === expectedResult) {
        console.log("PASSED", `${dateStr} + ${daysToIncrement} = ${result}`)
      } else {
        console.log("FAILED", `${dateStr} + ${daysToIncrement} = ${result} (expected: ${expectedResult})`)
      }
    })