-
Notifications
You must be signed in to change notification settings - Fork 173
Description
Temporal.ZonedDateTime.from("2021-01-05T16:37:40.840192769Z[Europe/London]")
// => 2021-01-05T16:37:40.840192769+00:00[Europe/London]
Temporal.ZonedDateTime.from("2021-01-05T16:37:40.840192769Z[Asia/Tokyo]")
// => RangeError: Offset +00:00 is invalid for 2021-01-05T16:37:40.840192769 in Asia/TokyoAFAICT, this behavior is contrary to the spec which says:
2. If isoString does not satisfy the syntax of a TemporalZonedDateTimeString (see 13.33), then
a. Throw a RangeError exception.
3. Let result be ! ParseISODateTime(isoString).
4. Let timeZoneResult be ? ParseTemporalTimeZoneString(isoString).
5. If timeZoneResult.[[Z]] is not undefined, then
a. Throw a RangeError exception.
and https://tc39.es/proposal-temporal/#prod-TemporalZonedDateTimeString
TemporalZonedDateTimeString :
Date TimeZoneNumericUTCOffset TimeZoneBracketedAnnotation Calendar
Date DateTimeSeparator TimeSpec TimeZoneNumericUTCOffset TimeZoneBracketedAnnotation Calendar
TimeZoneNumericUTCOffset excludes "Z". Also, even if it didn't, then an exception should be thrown per (5a) above.
At minimum this is a polyfill bug. But looking at the history of this decision (see #1075 (comment)) we anticipated that there might be feedback on this topic from implementers or users, and decided that throwing was the best short-term option to get to Stage 3 with enough flexibility to choose a different solution later. Reading the meeting notes it seems like there wasn't consensus among the champions at the time, so throwing seemed like the best way to kick the can down the road.
This week in discussions with IETF, we tripped over that can in the road. :-) It looks like there's enthusiasm in that IETF group to accept the Z format, and in fact in today's champions meeting we agreed to tell IETF that the Z format is the way for callers to signal to the recipient that the timestamp should always win over the TZID in cases where the offset and the TZID were in conflict (e.g. if time zone rules have changed since that string was stored).
So although this is a polyfill bug, it might also require a normative spec change to allow Z strings, depending on the outcome of the IETF discussions. Note that there are three possible outcomes:
- Keep current spec behavior and throw if Z is in the string
- Allow Z in the string, which would be treated the same as
{ offset: 'use' }. - Allow Z, and also change the default
offsetoption from'reject'to `'use', so that the instant would by default be projected into the time zone, even if they conflict. This is Java's behavior, FWIW.
In today's meeting, the champions discussed (3) and were opposed to it, but supported (2) although only afterwards did we realize that (2) was contrary to the spec. So I'm opening this issue to figure out what to do.
BTW, one objection in our earlier discussion was "where would the user get a string with both a Z and an IANA name?" I just ported a real app from Date to Temporal. Based on that experience, I think I have an answer to this objection. If you want to use ISO strings as the input for a library method but your original data source has only Date and a separate time zone value, then there's no easy way to know the offset to use in the ISO string. But assembling a Z string is easy:
isoString = `${date.toISOString()}[${timeZoneName}]`;This use case (combining from two separate values to one string) came up frequently in my migration work. Similarly, if users on another platform (not JS) are sending data to an ECMAScript service, they also might not be able to know the offset to use. So the "Z" seems like a valid and reasonably-common use case, although the conflicting numeric offset as in (3) above does seem to align with that original objection because AFAICT there's no common way to get those strings.