Version
v26.5.1 (V8 14.6.202.34-node.24, ICU 78.3). Also reproduces on v22.17.1, v24.11.0 and v25.4.0.
Platform
Linux 7.0.0-31-generic x86_64
Subsystem
intl
What steps will reproduce the bug?
$ TZ=UTC+3 node -p 'Intl.DateTimeFormat().resolvedOptions().timeZone'
undefined
$ TZ=UTC+3 node -p 'new Date().getTimezoneOffset()'
180
TZ=UTC-2 gives undefined as well, with an offset of -120. IANA names are unaffected (TZ=Europe/Paris gives "Europe/Paris", TZ=EST5EDT gives "America/New_York").
How often does it reproduce? Is there a required condition?
Always, when TZ is a POSIX offset string such as UTC+3 that ICU cannot map to a time zone ID.
What is the expected behavior? Why is that the expected behavior?
A string. ECMA-262 SystemTimeZoneIdentifier "returns a String", either a primary time zone identifier or an offset time zone identifier, so here "-03:00" (POSIX UTC+3 is three hours west of UTC, matching getTimezoneOffset() === 180). Formatting already knows the offset: new Intl.DateTimeFormat("en", { timeZoneName: "short" }).format(0) gives 12/31/1969, GMT-3.
What do you see instead?
undefined. Code that keys anything on the zone name (caches, logs, Intl.DateTimeFormat(undefined, { timeZone })) sees the same value for every such offset.
Additional information
The undefined comes from V8's JSDateTimeFormat::TimeZoneId, which returns undefined when icu::TimeZone::getCanonicalID fails, "when the time_zone is neither a known system time zone ID nor a valid custom time zone ID": https://github.com/v8/v8/blob/36de2a2334c9129db7f6fe0db76fd7d5fa64df78/src/objects/js-date-time-format.cc#L612-L635. So this may need forwarding to V8. For comparison, Bun 1.4.0 returns "UTC" in the same environment.
Related but different: #50301 (macOS Sonoma), #26880 (/etc/localtime symlink).
Version
v26.5.1 (V8 14.6.202.34-node.24, ICU 78.3). Also reproduces on v22.17.1, v24.11.0 and v25.4.0.
Platform
Linux 7.0.0-31-generic x86_64
Subsystem
intl
What steps will reproduce the bug?
TZ=UTC-2givesundefinedas well, with an offset of-120. IANA names are unaffected (TZ=Europe/Parisgives"Europe/Paris",TZ=EST5EDTgives"America/New_York").How often does it reproduce? Is there a required condition?
Always, when
TZis a POSIX offset string such asUTC+3that ICU cannot map to a time zone ID.What is the expected behavior? Why is that the expected behavior?
A string. ECMA-262 SystemTimeZoneIdentifier "returns a String", either a primary time zone identifier or an offset time zone identifier, so here
"-03:00"(POSIXUTC+3is three hours west of UTC, matchinggetTimezoneOffset() === 180). Formatting already knows the offset:new Intl.DateTimeFormat("en", { timeZoneName: "short" }).format(0)gives12/31/1969, GMT-3.What do you see instead?
undefined. Code that keys anything on the zone name (caches, logs,Intl.DateTimeFormat(undefined, { timeZone })) sees the same value for every such offset.Additional information
The
undefinedcomes from V8'sJSDateTimeFormat::TimeZoneId, which returnsundefinedwhenicu::TimeZone::getCanonicalIDfails, "when the time_zone is neither a known system time zone ID nor a valid custom time zone ID": https://github.com/v8/v8/blob/36de2a2334c9129db7f6fe0db76fd7d5fa64df78/src/objects/js-date-time-format.cc#L612-L635. So this may need forwarding to V8. For comparison, Bun 1.4.0 returns"UTC"in the same environment.Related but different: #50301 (macOS Sonoma), #26880 (
/etc/localtimesymlink).