From 897783ed94622dac8862835d055e58cdb38fc639 Mon Sep 17 00:00:00 2001 From: Justin Grant Date: Thu, 29 Jun 2023 12:50:33 -0700 Subject: [PATCH] Catch up with upstream proposal-temporal Align with upstream refactoring of offset time zone parsing and formatting. --- polyfill/polyfill.diff | 33 +++++++++++++++++---------------- spec/intl.html | 4 ++-- spec/temporal-biblio.json | 25 ++++++++++++++++++++----- spec/timezone.html | 38 ++++++++++++++++++++++++++++++-------- temporal | 2 +- 5 files changed, 70 insertions(+), 32 deletions(-) diff --git a/polyfill/polyfill.diff b/polyfill/polyfill.diff index 7c40dd88..ca858732 100644 --- a/polyfill/polyfill.diff +++ b/polyfill/polyfill.diff @@ -9,7 +9,7 @@ index 1c6831c7..73008e46 100644 + url = https://github.com/justingrant/test262 + branch = proposal-canonical-tz-tests diff --git a/polyfill/index.d.ts b/polyfill/index.d.ts -index 244067cb..d4b6f741 100644 +index 784677c9..b11758ea 100644 --- a/polyfill/index.d.ts +++ b/polyfill/index.d.ts @@ -1138,6 +1138,7 @@ export namespace Temporal { @@ -21,11 +21,11 @@ index 244067cb..d4b6f741 100644 getOffsetStringFor(instant: Temporal.Instant | string): string; getPlainDateTimeFor(instant: Temporal.Instant | string, calendar?: CalendarLike): Temporal.PlainDateTime; diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs -index 25d54d96..8359e4a0 100644 +index e7f04c0b..53d5ed81 100644 --- a/polyfill/lib/ecmascript.mjs +++ b/polyfill/lib/ecmascript.mjs -@@ -371,7 +371,7 @@ export function ParseTemporalTimeZone(stringIdent) { - if (IsTimeZoneOffsetString(tzName)) return CanonicalizeTimeZoneOffsetString(tzName); +@@ -2101,7 +2101,7 @@ export function ToTemporalTimeZoneSlotValue(temporalTimeZoneLike) { + const record = GetAvailableNamedTimeZoneIdentifier(tzName); if (!record) throw new RangeError(`Unrecognized time zone ${tzName}`); - return record.primaryIdentifier; @@ -33,15 +33,16 @@ index 25d54d96..8359e4a0 100644 } if (z) return 'UTC'; // if !tzName && !z then offset must be present -@@ -2119,7 +2119,16 @@ export function TimeZoneEquals(one, two) { +@@ -2126,7 +2126,17 @@ export function TimeZoneEquals(one, two) { if (one === two) return true; const tz1 = ToTemporalTimeZoneIdentifier(one); const tz2 = ToTemporalTimeZoneIdentifier(two); - return tz1 === tz2; + if (tz1 === tz2) return true; -+ if (IsTimeZoneOffsetString(tz1)) { -+ if (!IsTimeZoneOffsetString(tz2)) return false; -+ return CanonicalizeTimeZoneOffsetString(tz1) === CanonicalizeTimeZoneOffsetString(tz2); ++ const offsetNanoseconds1 = ParseTimeZoneIdentifier(tz1).offsetNanoseconds; ++ const offsetNanoseconds2 = ParseTimeZoneIdentifier(tz2).offsetNanoseconds; ++ if (offsetNanoseconds1 !== undefined || offsetNanoseconds2 !== undefined) { ++ return offsetNanoseconds1 === offsetNanoseconds2; + } + const idRecord1 = GetAvailableNamedTimeZoneIdentifier(tz1); + if (!idRecord1) return false; @@ -52,7 +53,7 @@ index 25d54d96..8359e4a0 100644 export function TemporalDateTimeToDate(dateTime) { diff --git a/polyfill/lib/intl.mjs b/polyfill/lib/intl.mjs -index e3c6a403..4870d3d1 100644 +index 9d78ee43..d86269a5 100644 --- a/polyfill/lib/intl.mjs +++ b/polyfill/lib/intl.mjs @@ -139,7 +139,7 @@ Object.defineProperty(DateTimeFormat, 'prototype', { @@ -65,10 +66,10 @@ index e3c6a403..4870d3d1 100644 } diff --git a/polyfill/lib/timezone.mjs b/polyfill/lib/timezone.mjs -index 9796e980..eb957267 100644 +index 7c6c8a2e..857385ad 100644 --- a/polyfill/lib/timezone.mjs +++ b/polyfill/lib/timezone.mjs -@@ -32,7 +32,7 @@ export class TimeZone { +@@ -33,7 +33,7 @@ export class TimeZone { } else { const record = ES.GetAvailableNamedTimeZoneIdentifier(stringIdentifier); if (!record) throw new RangeError(`Invalid time zone identifier: ${stringIdentifier}`); @@ -77,7 +78,7 @@ index 9796e980..eb957267 100644 } CreateSlots(this); SetSlot(this, TIMEZONE_ID, stringIdentifier); -@@ -50,6 +50,11 @@ export class TimeZone { +@@ -51,6 +51,11 @@ export class TimeZone { if (!ES.IsTemporalTimeZone(this)) throw new TypeError('invalid receiver'); return GetSlot(this, TIMEZONE_ID); } @@ -90,7 +91,7 @@ index 9796e980..eb957267 100644 if (!ES.IsTemporalTimeZone(this)) throw new TypeError('invalid receiver'); instant = ES.ToTemporalInstant(instant); diff --git a/polyfill/lib/zoneddatetime.mjs b/polyfill/lib/zoneddatetime.mjs -index 1a593c7f..06de9d5f 100644 +index cbd4f8c8..ed1a4143 100644 --- a/polyfill/lib/zoneddatetime.mjs +++ b/polyfill/lib/zoneddatetime.mjs @@ -478,7 +478,7 @@ export class ZonedDateTime { @@ -103,9 +104,9 @@ index 1a593c7f..06de9d5f 100644 const formatter = new DateTimeFormat(locales, optionsCopy); diff --git a/polyfill/test262 b/polyfill/test262 -index 3e858ef0..041e65e3 160000 +index c5b24c64..e7d9edfe 160000 --- a/polyfill/test262 +++ b/polyfill/test262 @@ -1 +1 @@ --Subproject commit 3e858ef02d2eda1e1e7eeff89ad7deeaf99d2766 -+Subproject commit 041e65e336e35f1989ec5f0fcf8b2ac745837ab0 +-Subproject commit c5b24c64c3c27544f15e1c18ef274924cff1e32c ++Subproject commit e7d9edfe3866bac9eb4be01619b99748cc0209b2 diff --git a/spec/intl.html b/spec/intl.html index 58037deb..0818d7b1 100644 --- a/spec/intl.html +++ b/spec/intl.html @@ -14,7 +14,7 @@

Amendments to the ECMAScript® 2024 Internationalization API Specification - +

Use of the IANA Time Zone Database

@@ -73,7 +73,7 @@

Temporal.ZonedDateTime.prototype.toLocaleString ( [ _locales_ [ , _options_ 1. Perform ? RequireInternalSlot(_zonedDateTime_, [[InitializedTemporalZonedDateTime]]). 1. Let _dateTimeFormat_ be ! OrdinaryCreateFromConstructor(%DateTimeFormat%, %DateTimeFormat.prototype%, « [[InitializedDateTimeFormat]], [[Locale]], [[Calendar]], [[NumberingSystem]], [[TimeZone]], [[Weekday]], [[Era]], [[Year]], [[Month]], [[Day]], [[DayPeriod]], [[Hour]], [[Minute]], [[Second]], [[FractionalSecondDigits]], [[TimeZoneName]], [[HourCycle]], [[Pattern]], [[BoundFormat]] »). 1. Let _timeZone_ be ? ToTemporalTimeZoneIdentifier(_zonedDateTime_.[[TimeZone]]). - 1. If IsTimeZoneOffsetString(_timeZone_) is *true*, throw a *RangeError* exception. + 1. If IsOffsetTimeZoneIdentifier(_timeZone_) is *true*, throw a *RangeError* exception. 1. Let _timeZoneIdentifierRecord_ be GetAvailableNamedTimeZoneIdentifier(_timeZone_). 1. If _timeZoneIdentifierRecord_ is ~empty~, throw a *RangeError* exception. 1. Set _timeZone_ to _timeZoneIdentifierRecord_.[[PrimaryIdentifierIdentifier]]. diff --git a/spec/temporal-biblio.json b/spec/temporal-biblio.json index c5217697..913a6c05 100644 --- a/spec/temporal-biblio.json +++ b/spec/temporal-biblio.json @@ -9,13 +9,28 @@ }, { "type": "op", - "aoid": "CanonicalizeTimeZoneOffsetString", - "id": "sec-temporal-canonicalizetimezoneoffsetstring" + "aoid": "IsOffsetTimeZoneIdentifier", + "id": "sec-temporal-isoffsettimezoneidentifier" + }, + { + "type": "op", + "aoid": "FormatOffsetTimeZoneIdentifier", + "id": "sec-temporal-formatoffsettimezoneidentifier" + }, + { + "type": "op", + "aoid": "ParseDateTimeUTCOffset", + "id": "sec-temporal-parsedatetimeutcoffset" + }, + { + "type": "op", + "aoid": "ParseTimeZoneIdentifier", + "id": "sec-parsetimezoneidentifier" }, { "type": "op", "aoid": "ObjectImplementsTemporalTimeZoneProtocol", - "id": "sec-objectimplementstemporaltimezoneprotocol" + "id": "sec-temporal-objectimplementstemporaltimezoneprotocol" }, { "type": "op", @@ -30,12 +45,12 @@ { "type": "op", "aoid": "ToTemporalCalendarIdentifier", - "id": "sec-totemporalcalendaridentifier" + "id": "sec-temporal-totemporalcalendaridentifier" }, { "type": "op", "aoid": "CreateTemporalInstant", - "id": "sec-createtemporalinstant" + "id": "sec-temporal-createtemporalinstant" }, { "type": "op", diff --git a/spec/timezone.html b/spec/timezone.html index 1483917e..8a148e18 100644 --- a/spec/timezone.html +++ b/spec/timezone.html @@ -22,14 +22,22 @@

SystemTimeZoneIdentifier ( ): a String

description
- It returns a String representing the host environment's current time zone, which is either a String representing a UTC offset for which IsTimeZoneOffsetString returns *true*, or a primary time zone identifier. + It returns a String representing the host environment's current time zone, which is either a primary time zone identifier or an offset time zone identifier.
+ +

+ Updates to this abstract operation overlap with a Temporal PR (#2607 - Normative: Limit offset time zones to minutes precision) being presented in the July 2023 TC39 meeting. + If that PR is approved, SystemTimeZoneIdentifier changes will be removed from this proposal. +

+
+ 1. If the implementation only supports the UTC time zone, return *"UTC"*. 1. Let _systemTimeZoneString_ be the String representing the host environment's current time zone, either a primary time zone identifier or an offset time zone identifier. - 1. If IsTimeZoneOffsetString(_systemTimeZoneString_) is *true*, return CanonicalizeTimeZoneOffsetString(_systemTimeZoneString_). + 1. Let _offsetNanoseconds_ be ! ParseTimeZoneIdentifier(_systemTimeZoneString_). + 1. If _offsetNanoseconds_ is not ~empty~, return FormatOffsetTimeZoneIdentifier(_offsetNanoseconds_, ~separated~). 1. Return _systemTimeZoneString_. @@ -48,7 +56,10 @@

Temporal.TimeZone ( _identifier_ )

1. If NewTarget is *undefined*, then 1. Throw a *TypeError* exception. 1. Set _identifier_ to ? ToString(_identifier_). - 1. If IsTimeZoneOffsetString(_identifier_) is *false*, then + 1. Let _parseResult_ be ? ParseTimeZoneIdentifier(_identifier_). + 1. If _parseResult_.[[OffsetNanoseconds]] is not ~empty~, then + 1. Set _identifier_ to FormatOffsetTimeZoneIdentifier(_parseResult_.[[OffsetNanoseconds]], ~separated~). + 1. Else, 1. Let _timeZoneIdentifierRecord_ be GetAvailableNamedTimeZoneIdentifier(_identifier_). 1. If _timeZoneIdentifierRecord_ is ~empty~, throw a *RangeError* exception. 1. Set _identifier_ to _timeZoneIdentifierRecord_.[[PrimaryIdentifierIdentifier]]. @@ -87,10 +98,13 @@

1. If _newTarget_ is not present, set _newTarget_ to %Temporal.TimeZone%. 1. Let _object_ be ? OrdinaryCreateFromConstructor(_newTarget_, *"%Temporal.TimeZone.prototype%"*, « [[InitializedTemporalTimeZone]], [[Identifier]], [[OffsetNanoseconds]] »). - 1. If IsTimeZoneOffsetString(_identifier_) is *true*, then + 1. Assert: _identifier_ is an available named time zone identifier or an offset time zone identifier. + 1. Let _parseResult_ be ! ParseTimeZoneIdentifier(_identifier_). + 1. If _parseResult_.[[OffsetNanoseconds]] is not ~empty~, then 1. Set _object_.[[Identifier]] to ~empty~. - 1. Set _object_.[[OffsetNanoseconds]] to ParseTimeZoneOffsetString(_identifier_). + 1. Set _object_.[[OffsetNanoseconds]] to _parseResult_.[[OffsetNanoseconds]]. 1. Else, + 1. Assert: _parseResult_.[[Name]] is not ~empty~. 1. Assert: GetAvailableNamedTimeZoneIdentifier(_identifier_).[[PrimaryIdentifierIdentifier]] is _identifier_. 1. Set _object_.[[Identifier]] to _identifier_. 1. Set _object_.[[OffsetNanoseconds]] to ~empty~. @@ -118,12 +132,15 @@

1. Let _parseResult_ be ? ParseTemporalTimeZoneString(_identifier_). 1. If _parseResult_.[[Name]] is not *undefined*, then 1. Let _name_ be _parseResult_.[[Name]]. - 1. If IsTimeZoneOffsetString(_name_) is *true*, return CanonicalizeTimeZoneOffsetString(_name_). + 1. Let _offsetNanoseconds_ be ? ParseTimeZoneIdentifier(_name_).[[OffsetNanoseconds]]. + 1. If _offsetNanoseconds_ is not ~empty~, return FormatOffsetTimeZoneIdentifier(_offsetNanoseconds_, ~separated~). 1. Let _timeZoneIdentifierRecord_ be GetAvailableNamedTimeZoneIdentifier(_name_). 1. If _timeZoneIdentifierRecord_ is ~empty~, throw a *RangeError* exception. 1. Return _timeZoneIdentifierRecord_.[[PrimaryIdentifierIdentifier]]. 1. If _parseResult_.[[Z]] is *true*, return *"UTC"*. - 1. Return CanonicalizeTimeZoneOffsetString(_parseResult_.[[OffsetString]]). + 1. Let _offsetParseResult_ be ! ParseDateTimeUTCOffset(_parseResult_.[[OffsetString]]). + 1. If _offsetParseResult_.[[HasSubMinutePrecision]] is *true*, throw a *RangeError* exception. + 1. Return FormatOffsetTimeZoneIdentifier(_offsetParseResult_.[[OffsetNanoseconds]], ~separated~). @@ -136,13 +153,18 @@

description
-
It returns *true* if its arguments represent time zones using the same identifierthe same time zones, either because their identifiers are equal or because those identifiers resolve to the same primary time zone identifier.
+
It returns *true* if its arguments represent time zones using the same identifierthe same time zones, either because their identifiers are equal or because those identifiers resolve to the same primary time zone identifier or UTC offset.
1. If _one_ and _two_ are the same Object value, return *true*. 1. Let _timeZoneOne_ be ? ToTemporalTimeZoneIdentifier(_one_). 1. Let _timeZoneTwo_ be ? ToTemporalTimeZoneIdentifier(_two_). 1. If _timeZoneOne_ is _timeZoneTwo_, return *true*. + 1. Let _offsetNanosecondsOne_ be ? ParseTimeZoneIdentifier(_timeZoneOne_).[[OffsetNanoseconds]]. + 1. Let _offsetNanosecondsTwo_ be ? ParseTimeZoneIdentifier(_timeZoneTwo_).[[OffsetNanoseconds]]. + 1. If _offsetNanosecondsOne_ is not ~empty~ or _offsetNanosecondsTwo_ is not ~empty~, then + 1. If _offsetNanosecondsOne_ is not ~empty~ and _offsetNanosecondsTwo_ is not ~empty~ and _offsetNanosecondsOne_ = _offsetNanosecondsTwo_, return *true*. + 1. Return *false*. 1. Let _recordOne_ be GetAvailableNamedTimeZoneIdentifier(_timeZoneOne_). 1. Let _recordTwo_ be GetAvailableNamedTimeZoneIdentifier(_timeZoneTwo_). 1. If _recordOne_ is not ~empty~ and _recordTwo_ is not ~empty~ and _recordOne_.[[PrimaryIdentifier]] is _recordTwo_.[[PrimaryIdentifier]], return *true*. diff --git a/temporal b/temporal index 667e4a25..6d6d2313 160000 --- a/temporal +++ b/temporal @@ -1 +1 @@ -Subproject commit 667e4a25dfc24b44c2f721eb0668b0ac7cc01c5c +Subproject commit 6d6d231309450260956613ee39a24f695597d0f0