iamkun / iamkun/dayjs

UTC time unexpectedly mutates under certain conditions

Open
#2,422 0 comments 0 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**

_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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.