diff --git a/polyfill/test/Duration/constructor/compare/timezone-getpossibleinstantsfor-iterable.js b/polyfill/test/Duration/constructor/compare/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..586bc1bff6 --- /dev/null +++ b/polyfill/test/Duration/constructor/compare/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,36 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.compare +info: | + sec-temporal.duration.compare steps 4–6: + 4. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + 5. Let _shift1_ be ! CalculateOffsetShift(_relativeTo_, _one_.[[Years]], [...], _one_.[[Nanoseconds]]). + 6. Let _shift2_ be ! CalculateOffsetShift(_relativeTo_, _two_.[[Years]], [...], _two_.[[Nanoseconds]]). + sec-temporal-torelativetemporalobject step 6.d: + d. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNs_, _timeZone_, *"compatible"*, *"reject"*). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-calculateoffsetshift step 4: + 4. Let _after_ be ? AddZonedDateTime(_relativeTo_.[[Nanoseconds]], _relativeTo_.[[TimeZone]], _relativeTo_.[[Calendar]], _y_, [...], _ns_). + sec-temporal-addzoneddatetime step 8: + 8. Let _intermediateInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _intermediateDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +---*/ + +const expected = [ + "2000-01-01T00:00:00", // called once on the input relativeTo object + "2001-01-01T00:00:00", // called once on relativeTo plus the first operand + "2001-02-01T00:00:00", // called once on relativeTo plus the second operand +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(0, 13); + Temporal.Duration.compare(duration1, duration2, { relativeTo: { year: 2000, month: 1, day: 1, timeZone } }); +}, expected); diff --git a/polyfill/test/Duration/prototype/add/timezone-getpossibleinstantsfor-iterable.js b/polyfill/test/Duration/prototype/add/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..6aee2688e9 --- /dev/null +++ b/polyfill/test/Duration/prototype/add/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,41 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.add +info: | + sec-temporal.duration.prototype.add steps 5–6: + 5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + 6. Let _result_ be ? AddDuration(_duration_.[[Years]], [...], _duration_.[[Nanoseconds]], _other_.[[Years]], [...], _other_.[[Nanoseconds]], _relativeTo_). + sec-temporal-torelativetemporalobject step 6.d: + d. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNs_, _timeZone_, *"compatible"*, *"reject"*). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-addduration steps 7.d–e and 7.g.i: + d. Let _intermediateNs_ be ? AddZonedDateTime(_relativeTo_.[[Nanoseconds]], _timeZone_, _calendar_, _y1_, [...], _ns1_). + e. Let _endNs_ be ? AddZonedDateTime(_intermediateNs_, _timeZone_, _calendar_, _y2_, [...], _ns2_). + [...] + i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_). + sec-temporal-differencezoneddatetime step 8: + 8. Let _intermediateNs_ be ? AddZonedDateTime(_ns1_, _timeZone_, _calendar_, _dateDifference_.[[Years]], _dateDifference_.[[Months]], _dateDifference_.[[Weeks]], 0, 0, 0, 0, 0, 0, 0). + sec-temporal-addzoneddatetime step 8: + 8. Let _intermediateInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _intermediateDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +---*/ + +const expected = [ + "2000-01-01T09:00:00", // called once on the input relativeTo object + "2001-01-01T09:00:00", // called once on relativeTo plus the receiver + "2002-01-01T09:00:00", // called once on relativeTo plus the receiver plus the argument + "2002-01-01T09:00:00", // called once on relativeTo plus the years, months, and weeks from the difference of relativeTo minus endNs +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(0, 12); + duration1.add(duration2, { relativeTo: { year: 2000, month: 1, day: 1, hour: 9, timeZone } }); +}, expected); diff --git a/polyfill/test/Duration/prototype/round/timezone-getpossibleinstantsfor-iterable.js b/polyfill/test/Duration/prototype/round/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..dacdc9e97b --- /dev/null +++ b/polyfill/test/Duration/prototype/round/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,43 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.round +info: | + sec-temporal.duration.prototype.round steps 19, 21, and 24: + 19. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + 21. Let _roundResult_ be ? RoundDuration(_unbalanceResult_.[[Years]], [...], _unbalanceResult_.[[Days]], _duration_.[[Hours]], [...], _duration_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _relativeTo_). + 24. If _relativeTo_ has an [[InitializedTemporalZonedDateTime]] internal slot, then + a. Set _relativeTo_ to ? MoveRelativeZonedDateTime(_relativeTo_, _balanceResult_.[[Years]], _balanceResult_.[[Months]], _balanceResult_.[[Weeks]], 0). + sec-temporal-torelativetemporalobject step 6.d: + d. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNs_, _timeZone_, *"compatible"*, *"reject"*). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-roundduration step 5.c–d: + c. If _zonedRelativeTo_ is not *undefined*, then + i. Let _intermediate_ be ? MoveRelativeZonedDateTime(_zonedRelativeTo_, _years_, _months_, _weeks_, _days_). + d. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _intermediate_). + sec-temporal-moverelativezoneddatetime step 1: + 1. Let _intermediateNs_ be ? AddZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _zonedDateTime_.[[TimeZone]], _zonedDateTime_.[[Calendar]], _years_, _months_, _weeks_, _days_, 0, 0, 0, 0, 0, 0). + sec-temporal-nanosecondstodays step 13: + 13. Let _intermediateNs_ be ? AddZonedDateTime(_startNs_, _relativeTo_.[[TimeZone]], _relativeTo_.[[Calendar]], 0, 0, 0, _days_, 0, 0, 0, 0, 0, 0). + sec-temporal-addzoneddatetime step 8: + 8. Let _intermediateInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _intermediateDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +---*/ + +const expected = [ + "2000-01-01T00:00:00", // called once on the input relativeTo object + "2001-02-09T00:00:00", // called once on relativeTo plus years, months, weeks, days from the receiver + "2001-02-10T00:00:00", // called once on the previous value plus the calendar days difference between that and the time part of the duration + "2001-02-01T00:00:00", // called once on relativeTo plus the years, months, and weeks part of the balance result +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const duration = new Temporal.Duration(1, 1, 1, 1, 1, 1, 1); + duration.round({ smallestUnit: 'months', relativeTo: { year: 2000, month: 1, day: 1, timeZone } }); +}, expected); diff --git a/polyfill/test/Duration/prototype/subtract/timezone-getpossibleinstantsfor-iterable.js b/polyfill/test/Duration/prototype/subtract/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..d0112ed9d2 --- /dev/null +++ b/polyfill/test/Duration/prototype/subtract/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,41 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.subtract +info: | + sec-temporal.duration.prototype.subtract steps 5–6: + 5. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + 6. Let _result_ be ? AddDuration(_duration_.[[Years]], [...], _duration_.[[Nanoseconds]], −_other_.[[Years]], [...], −_other_.[[Nanoseconds]], _relativeTo_). + sec-temporal-torelativetemporalobject step 6.d: + d. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNs_, _timeZone_, *"compatible"*, *"reject"*). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-addduration steps 7.d–e and 7.g.i: + d. Let _intermediateNs_ be ? AddZonedDateTime(_relativeTo_.[[Nanoseconds]], _timeZone_, _calendar_, _y1_, [...], _ns1_). + e. Let _endNs_ be ? AddZonedDateTime(_intermediateNs_, _timeZone_, _calendar_, _y2_, [...], _ns2_). + [...] + i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_). + sec-temporal-differencezoneddatetime step 8: + 8. Let _intermediateNs_ be ? AddZonedDateTime(_ns1_, _timeZone_, _calendar_, _dateDifference_.[[Years]], _dateDifference_.[[Months]], _dateDifference_.[[Weeks]], 0, 0, 0, 0, 0, 0, 0). + sec-temporal-addzoneddatetime step 8: + 8. Let _intermediateInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _intermediateDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +---*/ + +const expected = [ + "2000-01-01T09:00:00", // called once on the input relativeTo object + "2001-01-01T09:00:00", // called once on relativeTo plus the receiver + "1999-12-01T09:00:00", // called once on relativeTo plus the receiver minus the argument + "1999-12-01T09:00:00", // called once on relativeTo plus the years, months, and weeks from the difference of relativeTo minus endNs +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const duration1 = new Temporal.Duration(1); + const duration2 = new Temporal.Duration(0, 13); + duration1.subtract(duration2, { relativeTo: { year: 2000, month: 1, day: 1, hour: 9, timeZone } }); +}, expected); diff --git a/polyfill/test/Duration/prototype/total/timezone-getpossibleinstantsfor-iterable.js b/polyfill/test/Duration/prototype/total/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..0308cd7665 --- /dev/null +++ b/polyfill/test/Duration/prototype/total/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,31 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.duration.prototype.total +info: | + sec-temporal.duration.prototype.total steps 4 and 10: + 4. Let _relativeTo_ be ? ToRelativeTemporalObject(_options_). + 10. Let _balanceResult_ be ? BalanceDuration(_unbalanceResult_.[[Days]], [...], _unbalanceResult_.[[Nanoseconds]], _unit_, _intermediate_). + sec-temporal-torelativetemporalobject step 6.d: + d. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNs_, _timeZone_, *"compatible"*, *"reject"*). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-addzoneddatetime step 8: + 8. Let _intermediateInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _intermediateDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +---*/ + +const expected = [ + "2000-01-01T00:00:00", // called once on the input relativeTo if ZonedDateTime + "2001-02-09T00:00:00", // called once on the intermediate ZonedDateTime with the calendar parts of the Duration added +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const duration = new Temporal.Duration(1, 1, 1, 1, 1, 1, 1); + duration.total({ unit: 'seconds', relativeTo: { year: 2000, month: 1, day: 1, timeZone } }); +}, expected); diff --git a/polyfill/test/PlainDate/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js b/polyfill/test/PlainDate/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..e74609ee70 --- /dev/null +++ b/polyfill/test/PlainDate/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,40 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindate.prototype.tozoneddatetime +info: | + sec-temporal.plaindate.prototype.tozoneddatetime step 7: + 7. Let _instant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _temporalDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-builtintimezonegetinstantfor step 14: + 14. Assert: _disambiguation_ is *"compatible"* or *"later"*. + sec-temporal-builtintimezonegetinstantfor step 16: + 16. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _later_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [compareArray.js, temporalHelpers.js] +---*/ + +const expected1 = [ + "2000-05-02T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const date = new Temporal.PlainDate(2000, 5, 2); + date.toZonedDateTime(timeZone); +}, expected1); + +// Same, but test the other path where the time doesn't exist and +// GetPossibleInstantsFor is called again on a later time + +const expected2 = [ + "2030-01-01T00:30:00", + "2030-01-01T01:30:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const date = new Temporal.PlainDate(2030, 1, 1); + date.toZonedDateTime({ plainTime: new Temporal.PlainTime(0, 30), timeZone }); +}, expected2); diff --git a/polyfill/test/PlainDateTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js b/polyfill/test/PlainDateTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..69cc0843a6 --- /dev/null +++ b/polyfill/test/PlainDateTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,40 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaindatetime.prototype.tozoneddatetime +info: | + sec-temporal.plaindatetime.prototype.tozoneddatetime step 6: + 6. Let _instant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _temporalDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-builtintimezonegetinstantfor step 14: + 14. Assert: _disambiguation_ is *"compatible"* or *"later"*. + sec-temporal-builtintimezonegetinstantfor step 16: + 16. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _later_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [compareArray.js, temporalHelpers.js] +---*/ + +const expected1 = [ + "2000-05-02T12:34:56.987654321", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.PlainDateTime(2000, 5, 2, 12, 34, 56, 987, 654, 321); + datetime.toZonedDateTime(timeZone); +}, expected1); + +// Same, but test the other path where the time doesn't exist and +// GetPossibleInstantsFor is called again on a later time + +const expected2 = [ + "2030-01-01T00:30:00", + "2030-01-01T01:30:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.PlainDateTime(2030, 1, 1, 0, 30); + datetime.toZonedDateTime(timeZone); +}, expected2); diff --git a/polyfill/test/PlainTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js b/polyfill/test/PlainTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..88c276294a --- /dev/null +++ b/polyfill/test/PlainTime/prototype/toZonedDateTime/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,40 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.plaintime.prototype.tozoneddatetime +info: | + sec-temporal.plaintime.prototype.tozoneddatetime step 10: + 10. Let _instant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _temporalDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-builtintimezonegetinstantfor step 14: + 14. Assert: _disambiguation_ is *"compatible"* or *"later"*. + sec-temporal-builtintimezonegetinstantfor step 16: + 16. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _later_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [compareArray.js, temporalHelpers.js] +---*/ + +const expected1 = [ + "2000-05-02T12:34:56.987654321", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const time = new Temporal.PlainTime(12, 34, 56, 987, 654, 321); + time.toZonedDateTime({ plainDate: new Temporal.PlainDate(2000, 5, 2), timeZone }); +}, expected1); + +// Same, but test the other path where the time doesn't exist and +// GetPossibleInstantsFor is called again on a later time + +const expected2 = [ + "2030-01-01T00:30:00", + "2030-01-01T01:30:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const time = new Temporal.PlainTime(0, 30); + time.toZonedDateTime({ plainDate: new Temporal.PlainDate(2030, 1, 1), timeZone }); +}, expected2); diff --git a/polyfill/test/ZonedDateTime/constructor/compare/timezone-getpossibleinstantsfor-iterable.js b/polyfill/test/ZonedDateTime/constructor/compare/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..5e068c0979 --- /dev/null +++ b/polyfill/test/ZonedDateTime/constructor/compare/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,41 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.compare +info: | + sec-temporal.zoneddatetime.compare steps 1–2: + 1. Set _one_ to ? ToTemporalZonedDateTime(_one_). + 2. Set _two_ to ? ToTemporalZonedDateTime(_two_). + sec-temporal-totemporalzoneddatetime step 7: + 7. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, _disambiguation_, _offset_). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +---*/ + +const expected1 = [ + "2000-05-02T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + Temporal.ZonedDateTime.compare( + { year: 2000, month: 5, day: 2, timeZone }, + { year: 2001, month: 6, day: 3, timeZone: "UTC" }, + ); +}, expected1); + +// Same, but on the other operand + +const expected2 = [ + "2001-06-03T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + Temporal.ZonedDateTime.compare( + { year: 2000, month: 5, day: 2, timeZone: "UTC" }, + { year: 2001, month: 6, day: 3, timeZone }, + ); +}, expected2); diff --git a/polyfill/test/ZonedDateTime/constructor/from/timezone-getpossibleinstantsfor-iterable.js b/polyfill/test/ZonedDateTime/constructor/from/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..0d9376c364 --- /dev/null +++ b/polyfill/test/ZonedDateTime/constructor/from/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,24 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.from +info: | + sec-temporal.zoneddatetime.from step 3: + 3. Return ? ToTemporalZonedDateTime(_item_, _options_). + sec-temporal-totemporalzoneddatetime step 7: + 7. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, _disambiguation_, _offset_). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +---*/ + +const expected = [ + "2000-05-02T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + Temporal.ZonedDateTime.from({ year: 2000, month: 5, day: 2, timeZone }); +}, expected); diff --git a/polyfill/test/ZonedDateTime/prototype/equals/timezone-getpossibleinstantsfor-iterable.js b/polyfill/test/ZonedDateTime/prototype/equals/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..460063be18 --- /dev/null +++ b/polyfill/test/ZonedDateTime/prototype/equals/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,36 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.equals +info: | + sec-temporal.zoneddatetime.prototype.equals step 3: + 3. Set _other_ to ? ToTemporalZonedDateTime(_other_). + sec-temporal-totemporalzoneddatetime step 7: + 7. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, _disambiguation_, _offset_). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +---*/ + +// Not called on the instance's time zone + +const expected1 = []; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, timeZone); + datetime.equals({ year: 2005, month: 6, day: 2, timeZone: "UTC" }); +}, expected1); + +// Called on the argument's time zone + +const expected2 = [ + "2005-06-02T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); + datetime.equals({ year: 2005, month: 6, day: 2, timeZone }); +}, expected2); diff --git a/polyfill/test/ZonedDateTime/prototype/hoursInDay/timezone-getpossibleinstantsfor-iterable.js b/polyfill/test/ZonedDateTime/prototype/hoursInDay/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..184319bef8 --- /dev/null +++ b/polyfill/test/ZonedDateTime/prototype/hoursInDay/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,43 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-get-temporal.zoneddatetime.prototype.hoursinday +info: | + sec-get-temporal.zoneddatetime.prototype.hoursinday steps 13–14: + 13. Let _todayInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _today_, *"compatible"*). + 14. Let _tomorrowInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _tomorrow_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-builtintimezonegetinstantfor step 14: + 14. Assert: _disambiguation_ is *"compatible"* or *"later"*. + sec-temporal-builtintimezonegetinstantfor step 16: + 16. Set _possibleInstants_ to ? GetPossibleInstantsFor(_timeZone_, _later_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [compareArray.js, temporalHelpers.js] +---*/ + +const expected1 = [ + "2001-09-09T00:00:00", + "2001-09-10T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, timeZone); + datetime.hoursInDay; +}, expected1); + +// Same, but test the other path where the time doesn't exist and +// GetPossibleInstantsFor is called again on a later time + +const expected2 = [ + "2030-01-01T00:00:00", + "2030-01-01T01:00:00", + "2030-01-02T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_893_457_800_000_000_000n, timeZone); + datetime.hoursInDay; +}, expected2); diff --git a/polyfill/test/ZonedDateTime/prototype/round/timezone-getpossibleinstantsfor-iterable.js b/polyfill/test/ZonedDateTime/prototype/round/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..cb1a64ebef --- /dev/null +++ b/polyfill/test/ZonedDateTime/prototype/round/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,31 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.round +info: | + sec-temporal.zoneddatetime.prototype.round steps 14, 16, and 20: + 14. Let _instantStart_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _dtStart_, *"compatible"*). + 16. Let _endNs_ be ? AddZonedDateTime(_startNs_, _timeZone_, _zonedDateTime_.[[Calendar]], 0, 0, 0, 1, 0, 0, 0, 0, 0, 0). + 20. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_roundResult_.[[Year]], [...], _roundResult_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, *"compatible"*, *"prefer"*). + sec-temporal-addzoneddatetime step 8: + 8. Let _intermediateInstant_ be ? BuiltinTimeZoneGetInstantFor(_timeZone_, _intermediateDateTime_, *"compatible"*). + sec-temporal-builtintimezonegetinstantfor step 1: + 1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +---*/ + +const expected = [ + "2001-09-09T00:00:00", // called once on midnight of the input datetime + "2001-09-10T00:00:00", // called once on the previous value plus one calendar day + "2001-09-09T02:00:00", // called once on the rounding result +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, timeZone); + datetime.round({ smallestUnit: 'hour' }); +}, expected); diff --git a/polyfill/test/ZonedDateTime/prototype/since/timezone-getpossibleinstantsfor-iterable.js b/polyfill/test/ZonedDateTime/prototype/since/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..7c657f3cd2 --- /dev/null +++ b/polyfill/test/ZonedDateTime/prototype/since/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,36 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.since +info: | + sec-temporal.zoneddatetime.prototype.since step 3: + 3. Set _other_ to ? ToTemporalZonedDateTime(_other_). + sec-temporal-totemporalzoneddatetime step 7: + 7. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, _disambiguation_, _offset_). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +---*/ + +// Not called on the instance's time zone + +const expected1 = []; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, timeZone); + datetime.since({ year: 2005, month: 6, day: 2, timeZone: "UTC" }); +}, expected1); + +// Called on the argument's time zone + +const expected2 = [ + "2005-06-02T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); + datetime.since({ year: 2005, month: 6, day: 2, timeZone }); +}, expected2); diff --git a/polyfill/test/ZonedDateTime/prototype/until/timezone-getpossibleinstantsfor-iterable.js b/polyfill/test/ZonedDateTime/prototype/until/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..b38d65e10d --- /dev/null +++ b/polyfill/test/ZonedDateTime/prototype/until/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,36 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.until +info: | + sec-temporal.zoneddatetime.prototype.until step 3: + 3. Set _other_ to ? ToTemporalZonedDateTime(_other_). + sec-temporal-totemporalzoneddatetime step 7: + 7. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_result_.[[Year]], [...], _result_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, _disambiguation_, _offset_). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +---*/ + +// Not called on the instance's time zone + +const expected1 = []; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, timeZone); + datetime.until({ year: 2005, month: 6, day: 2, timeZone: "UTC" }); +}, expected1); + +// Called on the argument's time zone + +const expected2 = [ + "2005-06-02T00:00:00", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); + datetime.until({ year: 2005, month: 6, day: 2, timeZone }); +}, expected2); diff --git a/polyfill/test/ZonedDateTime/prototype/with/timezone-getpossibleinstantsfor-iterable.js b/polyfill/test/ZonedDateTime/prototype/with/timezone-getpossibleinstantsfor-iterable.js new file mode 100644 index 0000000000..8a169ec71b --- /dev/null +++ b/polyfill/test/ZonedDateTime/prototype/with/timezone-getpossibleinstantsfor-iterable.js @@ -0,0 +1,23 @@ +// Copyright (C) 2021 Igalia, S.L. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. + +/*--- +esid: sec-temporal.zoneddatetime.prototype.with +info: | + sec-temporal.zoneddatetime.prototype.with step 24: + 24. Let _epochNanoseconds_ be ? InterpretISODateTimeOffset(_dateTimeResult_.[[Year]], [...], _dateTimeResult_.[[Nanosecond]], _offsetNanoseconds_, _timeZone_, _disambiguation_, _offset_). + sec-temporal-interpretisodatetimeoffset step 7: + 7. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _dateTime_). + sec-temporal-getpossibleinstantsfor step 2: + 2. Let _list_ be ? IterableToList(_possibleInstants_). +includes: [temporalHelpers.js] +---*/ + +const expected = [ + "2005-09-09T01:46:40", +]; + +TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { + const datetime = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, timeZone); + datetime.with({ year: 2005 }); +}, expected); diff --git a/polyfill/test/helpers/temporalHelpers.js b/polyfill/test/helpers/temporalHelpers.js index 4975fee94b..005539c362 100644 --- a/polyfill/test/helpers/temporalHelpers.js +++ b/polyfill/test/helpers/temporalHelpers.js @@ -374,6 +374,79 @@ var TemporalHelpers = { resultAssertions(result); }, + /* + * Check that any iterable returned from a custom time zone's + * getPossibleInstantsFor() method is exhausted. + * The custom time zone object is passed in to func(). + * expected is an array of strings representing the expected calls to the + * getPossibleInstantsFor() method. The PlainDateTimes that it is called with, + * are compared (using their toString() results) with the array. + */ + checkTimeZonePossibleInstantsIterable(func, expected) { + // A custom time zone that returns an iterable instead of an array from its + // getPossibleInstantsFor() method, and for testing purposes skips + // 00:00-01:00 UTC on January 1, 2030, and repeats 00:00-01:00 UTC+1 on + // January 3, 2030. Otherwise identical to the UTC time zone. + class TimeZonePossibleInstantsIterable extends Temporal.TimeZone { + constructor() { + super("UTC"); + this.getPossibleInstantsForCallCount = 0; + this.getPossibleInstantsForCalledWith = []; + this.getPossibleInstantsForReturns = []; + this.iteratorExhausted = []; + } + + toString() { + return "Custom/Iterable"; + } + + getOffsetNanosecondsFor(instant) { + if (Temporal.Instant.compare(instant, "2030-01-01T00:00Z") >= 0 && + Temporal.Instant.compare(instant, "2030-01-03T01:00Z") < 0) { + return 3600_000_000_000; + } else { + return 0; + } + } + + getPossibleInstantsFor(dateTime) { + this.getPossibleInstantsForCallCount++; + this.getPossibleInstantsForCalledWith.push(dateTime); + + // Fake DST transition + let retval = super.getPossibleInstantsFor(dateTime); + if (dateTime.toPlainDate().equals("2030-01-01") && dateTime.hour === 0) { + retval = []; + } else if (dateTime.toPlainDate().equals("2030-01-03") && dateTime.hour === 0) { + retval.push(retval[0].subtract({ hours: 1 })); + } else if (dateTime.year === 2030 && dateTime.month === 1 && dateTime.day >= 1 && dateTime.day <= 2) { + retval[0] = retval[0].subtract({ hours: 1 }); + } + + this.getPossibleInstantsForReturns.push(retval); + this.iteratorExhausted.push(false); + return { + callIndex: this.getPossibleInstantsForCallCount - 1, + timeZone: this, + *[Symbol.iterator]() { + yield* this.timeZone.getPossibleInstantsForReturns[this.callIndex]; + this.timeZone.iteratorExhausted[this.callIndex] = true; + }, + }; + } + } + + const timeZone = new TimeZonePossibleInstantsIterable(); + func(timeZone); + + assert.sameValue(timeZone.getPossibleInstantsForCallCount, expected.length, "getPossibleInstantsFor() method called correct number of times"); + + for (let index = 0; index < expected.length; index++) { + assert.sameValue(timeZone.getPossibleInstantsForCalledWith[index].toString(), expected[index], "getPossibleInstantsFor() called with expected PlainDateTime"); + assert(timeZone.iteratorExhausted[index], "iterated through the whole iterable"); + } + }, + /* * Check that any calendar-carrying Temporal object has its [[Calendar]] * internal slot read by ToTemporalCalendar, and does not fetch the calendar