UTC time unexpectedly mutates under certain conditions
- Dominant language
- JavaScript
- Stars
- 48.7k
- Forks
- 2.5k
- PR merge metrics
- No merged PRs in 30d
Description
**Describe the bug**
_UTC time mutates unexpectedly under certain conditions_
After setting a UTC timezone, the time can mutate under certain conditions, such as a call to `.clone` or `.locale`. This only happens with UTC times, and appears to only happen once per instance (future calls to `.clone` or `.locale` are fine).
**Example:**
```js
const dayjs = require('dayjs');
const utc = require('dayjs/plugin/utc');
const timezone = require('dayjs/plugin/timezone');
dayjs.extend(utc);
dayjs.extend(timezone);
const t = '2023-08-23T14:09:52-06:00';
const baseDate = dayjs(t); // running in MDT context (-06:00)
const utcTimezone = dayjs(t).tz('UTC');
const madridTimezone = dayjs(t).tz('Europe/Madrid');
const baseFormat = baseDate.format();
const utcFormat = utcTimezone.format();
const madridFormat = madridTimezone.format();
// Expected values are all correct
console.log({
baseFormat, // logs '2023-08-23T14:09:52-06:00'
utcFormat, // logs '2023-08-23T20:09:52Z'
madridFormat, // logs '2023-08-23T22:09:52+02:00'
});
const clonedBaseFormat = baseDate.clone().format();
const clonedUTCFormat = utcTimezone.clone().format();
const clonedMadridFormat = madridTimezone.clone().format();
// UTC has an incorrect value
console.log({
clonedBaseFormat, // logs '2023-08-23T14:09:52-06:00'
clonedUTCFormat, // !!! logs '2023-08-24T02:09:52Z' - The time is +6 hours (my local time) the expected value
clonedMadridFormat, // logs '2023-08-23T22:09:52+02:00'
});
const utcCustomLocale = utcTimezone.locale({
name: 'locale_test',
weekStart: 4,
}).format();
console.log({
utcCustomLocale, // !!! logs '2023-08-24T02:09:52Z' - Same problem, +6 hours (my local context)
});
```
I believe this is because a `$u` property is getting set on the dayjs object when the timezone is set.
> https://github.com/iamkun/dayjs/blob/a9d7d0398d22ebd4bfc3812ca0134a97606d54d9/src/plugin/timezone/index.js#L101
The following call to `utcOffset` sets that `$u` property because `keepLocalTime` is set to true. This causes an issue later when the `init` function is called later, since that property causes us to compute UTC time as if we haven't already.
> https://github.com/iamkun/dayjs/blob/a9d7d0398d22ebd4bfc3812ca0134a97606d54d9/src/plugin/utc/index.js#L56
**Expected behavior**
UTC should not mutate with calls to `.clone` or other methods unless explicitly stated.
**Information**
- Day.js _Version: v1.11.9_
- OS: _MacOS 12.4_
- Browser: _Version 116.0.5845.110 (Official Build) (arm64)_
- Time zone: _MDT-06:00 DST_
Contributor guide
Research direction
Start by reproducing the UTC clone and locale examples, then inspect the referenced lines in src/plugin/timezone/index.js and src/plugin/utc/index.js, especially the keepLocalTime and $u handling. Verify that cloning or applying a locale no longer changes the UTC value, and run the project's existing tests to confirm the reported behavior is fixed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 58/100