Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug with addDays()? #3767

Closed
77it opened this issue Apr 13, 2024 · 3 comments
Closed

bug with addDays()? #3767

77it opened this issue Apr 13, 2024 · 3 comments

Comments

@77it
Copy link

77it commented Apr 13, 2024

When testing addDays() I found a strange behaviour: date 1917/04/01 + 1 day is not equal to 1917/04/02, that is wrong.
Instead, the date 1917/03/31 + 2 days is equal to 1917/04/02, which is correct.

Follows the code

import * as datefns from 'https://esm.run/date-fns@3.6.0';

const date_20170401 = new Date(1917, 3 /* Apr */, 1);
const date_20170402 = new Date(1917, 3 /* Apr */, 2);
const date_20170401_plus1 = datefns.addDays(date_20170401, 1);

if (date_20170401_plus1.getTime() !== date_20170402.getTime()) {
  console.log(`date_20170331_plus1_plus1: ${date_20170401_plus1}`);
  console.log(`date_20170402: ${date_20170402}`);
  console.log("test #1 failed");
}

const date_20170331 = new Date(1917, 2 /* Mar */, 31);
const date_20170331_plus2 = datefns.addDays(date_20170331, 2);

if (date_20170331_plus2.getTime() !== date_20170402.getTime()) {
  console.log(`date_20170331_plus2: ${date_20170331_plus2}`);
  console.log(`date_20170402: ${date_20170402}`);
  console.log("test #2 failed");
}
@fturmel
Copy link
Member

fturmel commented Apr 13, 2024

I can't reproduce the problem. Which version of date-fns is this? Can you share your IANA time zone and which JS runtime you are using? What are the console.log() outputs?

This might overlap a daylight saving transition, but I can't think of a reason why the dates wouldn't match up.

@77it
Copy link
Author

77it commented Apr 13, 2024

I'm in Italy, zone Europe/Rome

I tried with Nodejs version v21.6.2 and Deno version deno 1.41.0, same result.

Test run with Nodejs node --experimental-network-imports test.mjs

date_20170331_plus1_plus1: Mon Apr 02 1917 01:00:00 GMT+0200 (Ora legale dell’Europa centrale)
date_20170402: Mon Apr 02 1917 00:00:00 GMT+0200 (Ora legale dell’Europa centrale)
test #1 failed

Test run with Deno deno run test.mjs

date_20170331_plus1_plus1: Mon Apr 02 1917 01:00:00 GMT+0200 (Ora legale dell’Europa centrale)
date_20170402: Mon Apr 02 1917 00:00:00 GMT+0200 (Ora legale dell’Europa centrale)
test #1 failed

Same output running the code online with Chrome with https://playcode.io/1834998

For my needs I use the following code to add days; it ignores the time part and works with any day I've tried:

new Date(date.getFullYear(), date.getMonth(), date.getDate() + amount)

PS
I updated the code posted in the issue to add the import statement.

@fturmel
Copy link
Member

fturmel commented Apr 13, 2024

Thanks for the additional details. Here's what's happening:

new Date(1917, 3, 1) is actually Sun Apr 01 1917 01:00:00 GMT+0200 (Central European Summer Time) because it is exactly during a daylight saving transition and midnight technically doesn't exist.

new Date(1917, 3, 2) is Mon Apr 02 1917 00:00:00 GMT+0200 (Central European Summer Time) as expected.

So if you add a day to April 1st at 1AM, you get April 2nd at 1AM, not midnight.


If you don't want to take into account local time zone and DST, you should use UTC instead, either through the UTCDate package :

// process.env.TZ = 'Europe/Rome';

import { UTCDate } from '@date-fns/utc';
import { addDays } from 'date-fns';

const april1 = new UTCDate(1917, 3, 1);
const april2 = new UTCDate(1917, 3, 2);
const april1Plus1Day = addDays(april1, 1);

console.log(april1.toISOString());
console.log(april2.toISOString());
console.log(april1Plus1Day.toISOString());

// 1917-04-01T00:00:00.000Z
// 1917-04-02T00:00:00.000Z
// 1917-04-02T00:00:00.000Z

...or directly with the native JS Date for such a simple operation:

// process.env.TZ = 'Europe/Rome';

const april1 = new Date(Date.UTC(1917, 3, 1));
const april2 = new Date(Date.UTC(1917, 3, 2));
const april1Plus1Day = new Date(april1);
april1Plus1Day.setUTCDate(april1.getUTCDate() + 1);

console.log(april1.toISOString());
console.log(april2.toISOString());
console.log(april1Plus1Day.toISOString());

// 1917-04-01T00:00:00.000Z
// 1917-04-02T00:00:00.000Z
// 1917-04-02T00:00:00.000Z

@77it 77it closed this as completed Apr 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants