diff options
Diffstat (limited to '')
8 files changed, 183 insertions, 71 deletions
diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/div-zero.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/div-zero.js index 776cb7454f..dd912f46d4 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/div-zero.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/div-zero.js @@ -18,10 +18,8 @@ class TimeZone extends Temporal.TimeZone { } } -const units = ["hour", "minute", "second", "millisecond", "microsecond", "nanosecond"]; -for (const smallestUnit of units) { - const zdt = new Temporal.ZonedDateTime(0n, new TimeZone("UTC")); - assert.throws(RangeError, () => zdt.round({ smallestUnit, roundingIncrement: 2 }), `zero day-length with smallestUnit ${smallestUnit}`); -} +const zdt = new Temporal.ZonedDateTime(0n, new TimeZone("UTC")); + +assert.throws(RangeError, () => zdt.round({ smallestUnit: "day" }), `zero day-length with smallestUnit 'day'`); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/getoffsetnanosecondsfor-maximum-forward-offset-shift.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/getoffsetnanosecondsfor-maximum-forward-offset-shift.js new file mode 100644 index 0000000000..1d3a5425d0 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/getoffsetnanosecondsfor-maximum-forward-offset-shift.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2024 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 +description: > + UTC offset shift returned by adjacent invocations of getOffsetNanosecondsFor + in DisambiguatePossibleInstants can be at most 24 hours. +features: [Temporal] +info: | + DisambiguatePossibleInstants: + 18. If abs(_nanoseconds_) > nsPerDay, throw a *RangeError* exception. +---*/ + +let calls = 0; + +class Shift24Hour extends Temporal.TimeZone { + id = 'TestTimeZone'; + _shiftEpochNs = 12n * 3600n * 1_000_000_000n; // 1970-01-01T12:00Z + + constructor() { + super('UTC'); + } + + getOffsetNanosecondsFor(instant) { + calls++; + if (instant.epochNanoseconds < this._shiftEpochNs) return -12 * 3600e9; + return 12 * 3600e9; + } + + getPossibleInstantsFor(plainDateTime) { + const [utcInstant] = super.getPossibleInstantsFor(plainDateTime); + const { year, month, day } = plainDateTime; + + if (year < 1970) return [utcInstant.subtract({ hours: 12 })]; + if (year === 1970 && month === 1 && day === 1) return []; + return [utcInstant.add({ hours: 12 })]; + } +} + +const timeZone = new Shift24Hour(); + +const instance = new Temporal.ZonedDateTime(0n, timeZone); +instance.round({ smallestUnit: "hours" }); + +assert(calls >= 2, "getOffsetNanosecondsFor should be called at least twice"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/getpossibleinstantsfor-called-with-iso8601-calendar.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/getpossibleinstantsfor-called-with-iso8601-calendar.js index 0c622df167..91c8ec7bc2 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/getpossibleinstantsfor-called-with-iso8601-calendar.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/getpossibleinstantsfor-called-with-iso8601-calendar.js @@ -51,8 +51,8 @@ const nonBuiltinISOCalendar = new Temporal.Calendar("iso8601"); const timeZone = new SkippedDateTime(); const instance = new Temporal.ZonedDateTime(0n, timeZone, nonBuiltinISOCalendar); -instance.round({ smallestUnit: "hours" }); +instance.round({ smallestUnit: "day" }); -assert.sameValue(timeZone.calls, 6, "getPossibleInstantsFor should have been called 6 times"); +assert.sameValue(timeZone.calls, 4, "getPossibleInstantsFor should have been called 4 times"); reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/getpossibleinstantsfor-maximum-backward-offset-shift.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/getpossibleinstantsfor-maximum-backward-offset-shift.js new file mode 100644 index 0000000000..0c60d44311 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/getpossibleinstantsfor-maximum-backward-offset-shift.js @@ -0,0 +1,53 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2024 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 +description: > + UTC offset shift returned by getPossibleInstantsFor can be at most 24 hours. +features: [Temporal] +info: | + GetPossibleInstantsFor: + 5.b.i. Let _numResults_ be _list_'s length. + ii. If _numResults_ > 1, then + 1. Let _epochNs_ be a new empty List. + 2. For each value _instant_ in list, do + a. Append _instant_.[[EpochNanoseconds]] to the end of the List _epochNs_. + 3. Let _min_ be the least element of the List _epochNs_. + 4. Let _max_ be the greatest element of the List _epochNs_. + 5. If abs(ℝ(_max_ - _min_)) > nsPerDay, throw a *RangeError* exception. +---*/ + +let calls = 0; + +class Shift24Hour extends Temporal.TimeZone { + id = 'TestTimeZone'; + + constructor() { + super('UTC'); + } + + getOffsetNanosecondsFor(instant) { + return 0; + } + + getPossibleInstantsFor(plainDateTime) { + calls++; + const utc = new Temporal.TimeZone("UTC"); + const [utcInstant] = utc.getPossibleInstantsFor(plainDateTime); + return [ + utcInstant.subtract({ hours: 12 }), + utcInstant.add({ hours: 12 }) + ]; + } +} + +const timeZone = new Shift24Hour(); + +const instance = new Temporal.ZonedDateTime(0n, timeZone); +instance.round({ smallestUnit: "hours" }); + +assert(calls >= 1, "getPossibleInstantsFor should be called at least once"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/getpossibleinstantsfor-out-of-range-backward-offset-shift.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/getpossibleinstantsfor-out-of-range-backward-offset-shift.js new file mode 100644 index 0000000000..dabcfe8ed6 --- /dev/null +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/getpossibleinstantsfor-out-of-range-backward-offset-shift.js @@ -0,0 +1,49 @@ +// |reftest| skip-if(!this.hasOwnProperty('Temporal')) -- Temporal is not enabled unconditionally +// Copyright (C) 2024 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 +description: > + UTC offset shift returned by getPossibleInstantsFor can be at most 24 hours. +features: [Temporal] +info: | + GetPossibleInstantsFor: + 5.b.i. Let _numResults_ be _list_'s length. + ii. If _numResults_ > 1, then + 1. Let _epochNs_ be a new empty List. + 2. For each value _instant_ in list, do + a. Append _instant_.[[EpochNanoseconds]] to the end of the List _epochNs_. + 3. Let _min_ be the least element of the List _epochNs_. + 4. Let _max_ be the greatest element of the List _epochNs_. + 5. If abs(ℝ(_max_ - _min_)) > nsPerDay, throw a *RangeError* exception. +---*/ + +class ShiftLonger24Hour extends Temporal.TimeZone { + id = 'TestTimeZone'; + + constructor() { + super('UTC'); + } + + getOffsetNanosecondsFor(instant) { + return 0; + } + + getPossibleInstantsFor(plainDateTime) { + const utc = new Temporal.TimeZone("UTC"); + const [utcInstant] = utc.getPossibleInstantsFor(plainDateTime); + return [ + utcInstant.subtract({ hours: 12, nanoseconds: 1 }), + utcInstant.add({ hours: 12 }), + utcInstant, // add a third value in case the implementation doesn't sort + ]; + } +} + +const timeZone = new ShiftLonger24Hour(); + +const instance = new Temporal.ZonedDateTime(0n, timeZone); +assert.throws(RangeError, () => instance.round({ smallestUnit: "hours" }), "RangeError should be thrown"); + +reportCompare(0, 0); diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/order-of-operations.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/order-of-operations.js index 48ca638b39..65fac9036c 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/order-of-operations.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/order-of-operations.js @@ -24,10 +24,6 @@ const expected = [ "get this.timeZone.getPossibleInstantsFor", // GetPlainDateTimeFor on receiver's instant "call this.timeZone.getOffsetNanosecondsFor", - // GetInstantFor on preceding midnight - "call this.timeZone.getPossibleInstantsFor", - // AddDaysToZonedDateTime - "call this.timeZone.getPossibleInstantsFor", // InterpretISODateTimeOffset "call this.timeZone.getPossibleInstantsFor", "call this.timeZone.getOffsetNanosecondsFor", @@ -84,36 +80,8 @@ beforeFallBackInstance.round(nextHourOptions); assert.compareArray(actual, expected, "order of operations with rounding result at repeated wall-clock time"); actual.splice(0); // clear -const expectedSkippedDateTime = [ - "get options.roundingIncrement", - "get options.roundingIncrement.valueOf", - "call options.roundingIncrement.valueOf", - "get options.roundingMode", - "get options.roundingMode.toString", - "call options.roundingMode.toString", - "get options.smallestUnit", - "get options.smallestUnit.toString", - "call options.smallestUnit.toString", - // lookup - "get this.timeZone.getOffsetNanosecondsFor", - "get this.timeZone.getPossibleInstantsFor", - // GetPlainDateTimeFor on receiver's instant - "call this.timeZone.getOffsetNanosecondsFor", - // GetInstantFor on preceding midnight - "call this.timeZone.getPossibleInstantsFor", - // DisambiguatePossibleInstants - "call this.timeZone.getOffsetNanosecondsFor", - "call this.timeZone.getOffsetNanosecondsFor", - "call this.timeZone.getPossibleInstantsFor", - // AddZonedDateTime - "call this.timeZone.getPossibleInstantsFor", - // InterpretISODateTimeOffset - "call this.timeZone.getPossibleInstantsFor", - "call this.timeZone.getOffsetNanosecondsFor", -]; - springForwardInstance.round(options); -assert.compareArray(actual, expectedSkippedDateTime, "order of operations with preceding midnight at skipped wall-clock time"); +assert.compareArray(actual, expected, "order of operations with preceding midnight at skipped wall-clock time"); actual.splice(0); // clear const expectedSkippedResult = [ @@ -131,14 +99,6 @@ const expectedSkippedResult = [ "get this.timeZone.getPossibleInstantsFor", // GetPlainDateTimeFor on receiver's instant "call this.timeZone.getOffsetNanosecondsFor", - // GetInstantFor on preceding midnight - "call this.timeZone.getPossibleInstantsFor", - // AddDaysToZonedDateTime - "call this.timeZone.getPossibleInstantsFor", - // DisambiguatePossibleInstants - "call this.timeZone.getOffsetNanosecondsFor", - "call this.timeZone.getOffsetNanosecondsFor", - "call this.timeZone.getPossibleInstantsFor", // InterpretISODateTimeOffset "call this.timeZone.getPossibleInstantsFor", // DisambiguatePossibleInstants diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallest-unit-day-rounding-modes.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallest-unit-day-rounding-modes.js index f694712457..435bfa16d8 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallest-unit-day-rounding-modes.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/smallest-unit-day-rounding-modes.js @@ -41,21 +41,22 @@ class TimeZone extends Temporal.TimeZone { #count = 0; #nanoseconds; - constructor(nanoseconds) { + constructor(todayEpochNanoseconds, tomorrowEpochNanoseconds) { super("UTC"); - this.#nanoseconds = nanoseconds; + this.#nanoseconds = [todayEpochNanoseconds, tomorrowEpochNanoseconds]; } getPossibleInstantsFor(dateTime) { - if (++this.#count === 2) { - return [new Temporal.Instant(this.#nanoseconds)]; + const nanoseconds = this.#nanoseconds[this.#count++]; + if (nanoseconds === undefined) { + return super.getPossibleInstantsFor(dateTime); } - return super.getPossibleInstantsFor(dateTime); + return [new Temporal.Instant(nanoseconds)]; } } -function test(epochNanoseconds, tomorrowEpochNanoseconds, testCases) { +function test(epochNanoseconds, todayEpochNanoseconds, tomorrowEpochNanoseconds, testCases) { for (let [roundingMode, expected] of Object.entries(testCases)) { - let timeZone = new TimeZone(tomorrowEpochNanoseconds); + let timeZone = new TimeZone(todayEpochNanoseconds, tomorrowEpochNanoseconds); let zoned = new Temporal.ZonedDateTime(epochNanoseconds, timeZone); let result = zoned.round({ smallestUnit: "days", roundingMode }); assert.sameValue(result.epochNanoseconds, expected); @@ -64,31 +65,35 @@ function test(epochNanoseconds, tomorrowEpochNanoseconds, testCases) { const oneDay = 24n * 60n * 60n * 1000n * 1000n * 1000n; -// Test positive divisor (dayLengthNs). -test(3n, 10n, { - ceil: oneDay, +test(3n, undefined, 10n, { + ceil: 10n, // end-of-day according to TimeZone protocol floor: 0n, trunc: 0n, halfExpand: 0n, }); -test(-3n, 10n, { - ceil: 0n, +test(-3n, undefined, 10n, { + ceil: 10n, // end-of-day according to TimeZone protocol floor: -oneDay, trunc: -oneDay, - halfExpand: 0n, + halfExpand: 10n, // end-of-day according to TimeZone protocol }); -test(-3n, -10n, { - ceil: oneDay, - floor: 0n, - trunc: 0n, - halfExpand: 0n, -}); +assert.throws(RangeError, () => { + test(-3n, 0n, 10n, { ceil: undefined }); +}, "instant is before TimeZone protocol's start-of-day"); + +assert.throws(RangeError, () => { + test(-3n, undefined, -10n, { ceil: undefined }); +}, "instant is after TimeZone protocol's end-of-day"); + +assert.throws(RangeError, () => { + test(0n, 0n, 0n, { ceil: undefined }); +}, "instant is within zero-duration day"); // Test values at int64 boundaries. -test(3n, /*INT64_MAX=*/ 9223372036854775807n, { - ceil: oneDay, +test(3n, undefined, /*INT64_MAX=*/ 9223372036854775807n, { + ceil: /*INT64_MAX=*/ 9223372036854775807n, // end-of-day according to TimeZone protocol floor: 0n, trunc: 0n, halfExpand: 0n, diff --git a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getpossibleinstantsfor-iterable.js b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getpossibleinstantsfor-iterable.js index 922b114e0b..28c064e24d 100644 --- a/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getpossibleinstantsfor-iterable.js +++ b/js/src/tests/test262/built-ins/Temporal/ZonedDateTime/prototype/round/timezone-getpossibleinstantsfor-iterable.js @@ -23,8 +23,6 @@ features: [Temporal] ---*/ 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 ]; |