iamkun / iamkun/dayjs

`dayjs.tz` is not idempotent with dates in DST when it's not currently DST

Open
#1,805 12 comments 4 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
48.7k
Forks
2.5k
PR merge metrics
No merged PRs in 30d

Description

**Describe the bug**
Given:
* it is currently Standard Time (i.e. not Daylight Saving Time)
* the date being manipulated is in Daylight Saving Time

When `Dayjs#tz` is called more than once on a `Dayjs` object, the time moves back 1 hour each time `Dayjs#tz` is called.
```js
> dayjs('2020-08-08T00:00:00.000Z').toString()
//=> 'Sat, 08 Aug 2020 00:00:00 GMT'

> dayjs('2020-08-08T00:00:00.000Z').tz('America/Chicago').toString()
//=> 'Fri, 07 Aug 2020 23:00:00 GMT'

> dayjs('2020-08-08T00:00:00.000Z').tz('America/Chicago').tz('America/Chicago').toString()
//=> 'Fri, 07 Aug 2020 22:00:00 GMT'

> dayjs('2020-08-08T00:00:00.000Z').tz('America/Chicago').tz('America/Chicago').tz('America/Chicago').toString()
//=> 'Fri, 07 Aug 2020 21:00:00 GMT'
```

The result is the same regardless of what timezones are used, or whether a timezone arg is passed in at all:
```js
> dayjs('2020-08-08T00:00:00.001Z').tz('UTC').tz().tz('UTC').toString()
//=> 'Fri, 07 Aug 2020 21:00:00 GMT'

> dayjs('2020-08-08T00:00:00.001Z').tz('America/Chicago').tz('UTC').tz().toString()
//=> 'Fri, 07 Aug 2020 21:00:00 GMT'

> dayjs('2020-08-08T00:00:00.001Z').tz().tz().tz().toString()
//=> 'Fri, 07 Aug 2020 21:00:00 GMT'
```

It's February and I'm in Chicago, so I've only been able to confirm this issue occurs during CST with a date in CDT. I suspect that the opposite will be true in a few weeks (that calling `Dayjs#tz` on a CST time during CDT will result in a one-hour shift the other way).

And I saw several open issue tickets that are likely related or the result of the same underlying problem:
* #1804
* #1803
* #1801
* #1795
* #1791
* #1690
* #1664
* #1657
* #1635
* #1622
* #1260
* #1001

**Expected behavior**
Applying a timezone should not change the underlying time.

**Information**
- Day.js v1.10.7
- OS: iOS 12.1
- Time zone: GMT-06:00 (Central Standard Time)

Contributor guide

Open the contributing guide

Research direction

Start at the timezone plugin's Dayjs#tz entry point and reproduce the chained calls shown in the report, including dates crossing standard and daylight time. Trace how repeated timezone application calculates offsets; done means applying tz repeatedly preserves the underlying time and the reported examples no longer shift by an hour.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.