`dayjs.tz` parses ISO string as local time instead of UTC
- Dominant language
- JavaScript
- Stars
- 48.7k
- Forks
- 2.5k
- PR merge metrics
- No merged PRs in 30d
Description
**Describe the bug**
Using `moment-timezone`, this code will parse as UTC, then convert to the default timezone, which is what I would expect:
```javascript
moment.tz.setDefault("Australia/Melbourne");
const dt = moment("2025-10-24T05:00:00Z");
console.log(dt.toISOString()); // 2025-10-24T05:00:00.000Z
console.log(dt.tz()); // Australia/Melbourne
```
In Dayjs however, the equivalent parses the ISO string as local time, despite the `Z` suffix:
```javascript
dayjs.tz.setDefault("Australia/Melbourne");
const dt = dayjs.tz("2025-10-24T05:00:00Z");
console.log(dt.toISOString()); // 2025-10-23T18:00:00.000Z
console.log(dt["$x"]?.["$timezone"]); // Australia/Melbourne
```
The non-tz way of constructing a dayjs obj correctly parses as UTC, however the resulting object is not in the default timezone:
```javascript
const dt = dayjs("2025-10-24T05:00:00Z");
console.log(dt.toISOString()); // 2025-10-24T05:00:00.000Z
console.log(dt["$x"]?.["$timezone"]); // undefined
```
**Expected behavior**
I would expect `dayjs.tz` to parse `2025-10-24T05:00:00Z` as UTC, not local time.
Maybe I'm missing something, but it seems like this is a bug.
**Workaround**
To workaround it, I need to parse using `dayjs(timestamp)` then convert to the correct timezone. Since there's no function to get the default timezone, I need to cache the default somewhere (note: for this example 'caching' seems pointless, the point is the default tz needs to be stored somewhere accessible because `dayjs.tz.getDefault` doesn't exist). E.g.
```javascript
// This doesn't actually help for this use case
dayjs.tz.setDefault("Australia/Melbourne");
// Also cache the default timezone
const defaultTz = "Australia/Melbourne";
// Don't use dayjs.tz, just use dayjs
let dt = dayjs("2025-10-24T05:00:00Z");
// Convert to timezone
dt = dt.tz(defaultTz);
console.log(dt.toISOString()); // 2025-10-24T05:00:00.000Z
console.log(dt["$x"]?.["$timezone"]); // Australia/Melbourne
```
**Information**
- Day.js Version: v1.11.18
- OS: MacOS
- Browser: Firefox 143.0.4
- Time zone: GMT+11:00 AEDT (Australia/Melbourne)
Contributor guide
Assessment
This issue has not been assessed yet.