diff --git a/polyfill/lib/timezone.mjs b/polyfill/lib/timezone.mjs index 30176ed03b..4d17dfed37 100644 --- a/polyfill/lib/timezone.mjs +++ b/polyfill/lib/timezone.mjs @@ -19,18 +19,9 @@ import { SetSlot } from './slots.mjs'; -import * as REGEX from './regex.mjs'; -const OFFSET = new RegExp(`^${REGEX.offset.source}$`); -const IANA_NAME = new RegExp(`^${REGEX.timeZoneID.source}$`); - export class TimeZone { constructor(timeZoneIdentifier) { - if (new.target === TimeZone) { - timeZoneIdentifier = ES.GetCanonicalTimeZoneIdentifier(timeZoneIdentifier); - } - if (!OFFSET.exec(timeZoneIdentifier) && !IANA_NAME.exec(timeZoneIdentifier)) { - throw new RangeError(`invalid time zone identifier ${timeZoneIdentifier}`); - } + timeZoneIdentifier = ES.GetCanonicalTimeZoneIdentifier(timeZoneIdentifier); CreateSlots(this); SetSlot(this, TIMEZONE_ID, timeZoneIdentifier); diff --git a/polyfill/test/regex.mjs b/polyfill/test/regex.mjs index b2a13cd79c..e6c82811d5 100644 --- a/polyfill/test/regex.mjs +++ b/polyfill/test/regex.mjs @@ -589,12 +589,16 @@ describe('fromString regex', () => { }); describe('time zone ID', () => { - function makeCustomTimeZone(id) { - return class extends Temporal.TimeZone { - constructor() { - super(id); - } + let oldTemporalTimeZoneFrom = Temporal.TimeZone.from; + let fromCalledWith; + before(() => { + Temporal.TimeZone.from = function (item) { + fromCalledWith = item; + return new Temporal.TimeZone('UTC'); }; + }); + function testTimeZoneID(id) { + return Temporal.ZonedDateTime.from(`1970-01-01T00:00[${id}]`); } describe('valid', () => { [ @@ -616,9 +620,8 @@ describe('fromString regex', () => { 'Etc/GMT+12' ].forEach((id) => { it(id, () => { - const Custom = makeCustomTimeZone(id); - const tz = new Custom(); - equal(tz.id, id); + testTimeZoneID(id); + equal(fromCalledWith, id); }); }); }); @@ -641,11 +644,13 @@ describe('fromString regex', () => { 'Foo/Etc/GMT-8' ].forEach((id) => { it(id, () => { - const Custom = makeCustomTimeZone(id); - throws(() => new Custom(), RangeError); + throws(() => testTimeZoneID(id), RangeError); }); }); }); + after(() => { + Temporal.TimeZone.from = oldTemporalTimeZoneFrom; + }); }); describe('calendar ID', () => { diff --git a/polyfill/test/usertimezone.mjs b/polyfill/test/usertimezone.mjs index f2c4b50880..502bb6a62b 100644 --- a/polyfill/test/usertimezone.mjs +++ b/polyfill/test/usertimezone.mjs @@ -18,7 +18,10 @@ describe('Userland time zone', () => { describe('Trivial subclass', () => { class CustomUTCSubclass extends Temporal.TimeZone { constructor() { - super('Etc/Custom/UTC_Subclass'); + super('UTC'); + } + toString() { + return 'Etc/Custom/UTC_Subclass'; } getOffsetNanosecondsFor(/* instant */) { return 0; @@ -205,7 +208,10 @@ describe('Userland time zone', () => { describe('sub-minute offset', () => { class SubminuteTimeZone extends Temporal.TimeZone { constructor() { - super('Custom/Subminute'); + super('-00:00:01.111111111'); + } + toString() { + return 'Custom/Subminute'; } getOffsetNanosecondsFor() { return -1111111111; diff --git a/spec/timezone.html b/spec/timezone.html index fb2995a427..1843796753 100644 --- a/spec/timezone.html +++ b/spec/timezone.html @@ -25,21 +25,14 @@

Temporal.TimeZone ( _identifier_ )

1. If NewTarget is *undefined*, then 1. Throw a *TypeError* exception. - 1. Let _identifier_ be ? ToString(_identifier_). - 1. If _identifier_ does not satisfy the syntax of a |TemporalTimeZoneIdentifier| (see ), then - 1. Throw a *RangeError* exception. - 1. Let _sign_, _hour_, _minute_, and _id_ be the parts of _identifier_ produced respectively by the |TimeZoneUTCOffsetSign|, |TimeZoneUTCOffsetHour|, |TimeZoneUTCOffsetMinute| and |TimeZoneIANAName| productions, or *undefined* if not present. - 1. If _hour_ is not *undefined*, then - 1. Assert: _sign_ is not *undefined*. - 1. Set _hour_ to ! ToInteger(_hour_). - 1. If _sign_ = *"-"*, then - 1. Set _hour_ to −1 × _hour_. - 1. If _minute_ is not *undefined*, then - 1. Set _minute_ to ! ToInteger(_minute_). - 1. Do something with the offset. - 1. If ! IsValidTimeZoneName(_id_) is *false*, then - 1. Throw a *TypeError* exception. - 1. Let _canonical_ be ! CanonicalizeTimeZoneName(_identifier_). + 1. Set _identifier_ to ? ToString(_identifier_). + 1. If _identifier_ satisfies the syntax of a |TimeZoneNumericUTCOffset| (see ), then + 1. Let _offsetNanoseconds_ be ? ParseTimeZoneOffsetString(_identifier_). + 1. Let _canonical_ be ? FormatTimeZoneOffsetString(_offsetNanoseconds_). + 1. Else, + 1. If ! IsValidTimeZoneName(_id_) is *false*, then + 1. Throw a *RangeError* exception. + 1. Let _canonical_ be ! CanonicalizeTimeZoneName(_identifier_). 1. Return ? CreateTemporalTimeZone(_canonical_, NewTarget).