1
0
mirror of https://github.com/tc39/test262.git synced 2025-04-08 19:35:28 +02:00

Temporal: Add TemporalHelpers.crossDateLineTimeZone

Several tests in staging use the Pacific/Apia IANA time zone to test the
behaviour of various algorithms for the case where Samoa skipped the
entire day of Dec. 30, 2011, when they switched from one side of the
International Date Line to the other. Since implementations are not
technically required to support IANA time zones, add a fake Samoa time
zone to TemporalHelpers that has the same transition, and use it in those
tests.

(The time zone isn't exactly the same as Pacific/Apia, since Samoa also
observes DST and this time zone doesn't. It's only the same for this one
transition.)

See: 
This commit is contained in:
Philip Chimento 2022-09-30 13:08:36 -07:00 committed by Ms2ger
parent 886f091bd3
commit 46c3823117
8 changed files with 131 additions and 11 deletions

@ -1303,6 +1303,66 @@ var TemporalHelpers = {
return new CalendarMergeFieldsPrimitive(primitive);
},
/*
* crossDateLineTimeZone():
*
* This returns an instance of a custom time zone class that implements one
* single transition where the time zone moves from one side of the
* International Date Line to the other, for the purpose of testing time zone
* calculations without depending on system time zone data.
*
* The transition occurs at epoch second 1325239200 and goes from offset
* -10:00 to +14:00. In other words, the time zone skips the whole calendar
* day of 2011-12-30. This is the same as the real-life transition in the
* Pacific/Apia time zone.
*/
crossDateLineTimeZone() {
const { compare } = Temporal.PlainDateTime;
const skippedDay = new Temporal.PlainDate(2011, 12, 30);
const transitionEpoch = 1325239200_000_000_000n;
const beforeOffset = new Temporal.TimeZone("-10:00");
const afterOffset = new Temporal.TimeZone("+14:00");
class CrossDateLineTimeZone extends Temporal.TimeZone {
constructor() {
super("+14:00");
}
getOffsetNanosecondsFor(instant) {
if (instant.epochNanoseconds < transitionEpoch) {
return beforeOffset.getOffsetNanosecondsFor(instant);
}
return afterOffset.getOffsetNanosecondsFor(instant);
}
getPossibleInstantsFor(datetime) {
const comparison = Temporal.PlainDate.compare(datetime.toPlainDate(), skippedDay);
if (comparison === 0) {
return [];
}
if (comparison < 0) {
return [beforeOffset.getInstantFor(datetime)];
}
return [afterOffset.getInstantFor(datetime)];
}
getPreviousTransition(instant) {
if (instant.epochNanoseconds > transitionEpoch) return new Temporal.Instant(transitionEpoch);
return null;
}
getNextTransition(instant) {
if (instant.epochNanoseconds < transitionEpoch) return new Temporal.Instant(transitionEpoch);
return null;
}
toString() {
return "Custom/Date_Line";
}
}
return new CrossDateLineTimeZone();
},
/*
* observeProperty(calls, object, propertyName, value):
*

@ -0,0 +1,56 @@
// Copyright (C) 2022 Igalia, S.L. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
description: >
Verify the time zone arithmetic used in
TemporalHelpers.crossDateLineTimeZone() against the Pacific/Apia time zone in
the implementation's time zone database
includes: [compareArray.js, temporalHelpers.js]
features: [Temporal]
---*/
// No need to test this on hosts that don't provide an Intl object. It's
// sufficient that the logic is tested on at least one host.
if (typeof globalThis.Intl !== "undefined") {
const tz = TemporalHelpers.crossDateLineTimeZone();
const realTz = new Temporal.TimeZone('Pacific/Apia');
const shiftInstant = Temporal.Instant.from('2011-12-30T10:00:00Z');
assert.sameValue(
tz.getOffsetNanosecondsFor(shiftInstant),
realTz.getOffsetNanosecondsFor(shiftInstant),
'offset at shift instant'
);
const minus1 = shiftInstant.subtract({ hours: 1 });
assert.sameValue(
tz.getOffsetNanosecondsFor(minus1),
realTz.getOffsetNanosecondsFor(minus1),
'offset at 1 hour before shift'
);
const plus1 = shiftInstant.add({ hours: 1 });
assert.sameValue(
tz.getOffsetNanosecondsFor(plus1),
realTz.getOffsetNanosecondsFor(plus1),
'offset at 1 hour after shift'
);
const middleOfSkippedDayWallTime = Temporal.PlainDateTime.from("2011-12-30T12:00");
assert.compareArray(
tz.getPossibleInstantsFor(middleOfSkippedDayWallTime).map((i) => i.epochNanoseconds),
realTz.getPossibleInstantsFor(middleOfSkippedDayWallTime).map((i) => i.epochNanoseconds),
'possible instants for middle of skipped day wall time'
);
const before1 = middleOfSkippedDayWallTime.subtract({ days: 1 });
assert.compareArray(
tz.getPossibleInstantsFor(before1).map((i) => i.epochNanoseconds),
realTz.getPossibleInstantsFor(before1).map((i) => i.epochNanoseconds),
'possible instants for 1 day before skipped day'
);
const after1 = middleOfSkippedDayWallTime.add({ days: 1 });
assert.compareArray(
tz.getPossibleInstantsFor(after1).map((i) => i.epochNanoseconds),
realTz.getPossibleInstantsFor(after1).map((i) => i.epochNanoseconds),
'possible instants for 1 day after skipped day'
);
}

@ -87,8 +87,9 @@ var relativeTo = Temporal.PlainDateTime.from("2000-10-29T12:00").toZonedDateTime
assert.sameValue(`${ hours12.negated().add(oneDay.negated(), { relativeTo }) }`, "-P1DT11H");
assert.sameValue(`${ oneDay.negated().add(hours12.negated(), { relativeTo }) }`, "-P1DT12H");
// Samoa skipped 24 hours",
var relativeTo = Temporal.ZonedDateTime.from("2011-12-29T12:00-10:00[Pacific/Apia]");
// Samoa skipped 24 hours
var fakeSamoa = TemporalHelpers.crossDateLineTimeZone();
var relativeTo = Temporal.PlainDateTime.from("2011-12-29T12:00").toZonedDateTime(fakeSamoa);
assert.sameValue(`${ hours25.add(oneDay, { relativeTo }) }`, "P3DT1H");
assert.sameValue(`${ oneDay.add(hours25, { relativeTo }) }`, "P3DT1H");

@ -157,8 +157,9 @@ assert.sameValue(`${ hours12.negated().round({
relativeTo
}) }`, "-PT12H");
// Samoa skipped 24 hours",
var relativeTo = Temporal.ZonedDateTime.from("2011-12-29T12:00-10:00[Pacific/Apia]");
// Samoa skipped 24 hours
var fakeSamoa = TemporalHelpers.crossDateLineTimeZone();
var relativeTo = Temporal.PlainDateTime.from("2011-12-29T12:00").toZonedDateTime(fakeSamoa);
assert.sameValue(`${ hours25.round({
largestUnit: "days",
relativeTo

@ -53,7 +53,8 @@ assert.sameValue(`${ twoDays.subtract(hours24, { relativeTo: repeatedHourDay })
assert.sameValue(`${ hours24.subtract(twoDays, { relativeTo: repeatedHourDay }) }`, "-P1DT1H");
// Samoa skipped 24 hours
var relativeTo = Temporal.ZonedDateTime.from("2011-12-29T12:00-10:00[Pacific/Apia]");
var fakeSamoa = TemporalHelpers.crossDateLineTimeZone();
var relativeTo = Temporal.PlainDateTime.from("2011-12-29T12:00").toZonedDateTime(fakeSamoa);
assert.sameValue(`${ twoDays.subtract(Temporal.Duration.from({ hours: 48 }), { relativeTo }) }`, "-P1D");
assert.sameValue(`${ Temporal.Duration.from({ hours: 48 }).subtract(twoDays, { relativeTo }) }`, "P2D");

@ -373,8 +373,9 @@ var totalDays = hours12.negated().total({
});
assert(Math.abs(totalDays - -12 / 25) < Number.EPSILON);
// Samoa skipped 24 hours",
var relativeTo = Temporal.ZonedDateTime.from("2011-12-29T12:00-10:00[Pacific/Apia]");
// Samoa skipped 24 hours
var fakeSamoa = TemporalHelpers.crossDateLineTimeZone();
var relativeTo = Temporal.PlainDateTime.from("2011-12-29T12:00").toZonedDateTime(fakeSamoa);
var totalDays = hours25.total({
unit: "days",
relativeTo

@ -44,7 +44,7 @@ var undo = added.subtract(diff);
assert.sameValue(`${ undo }`, `${ hourBeforeDstStart }`);
// Samoa date line change (add): 10:00PM 29 Dec 2011 -> 11:00PM 31 Dec 2011
var timeZone = Temporal.TimeZone.from("Pacific/Apia");
var timeZone = TemporalHelpers.crossDateLineTimeZone();
var dayBeforeSamoaDateLineChangeAbs = timeZone.getInstantFor(new Temporal.PlainDateTime(2011, 12, 29, 22));
var start = dayBeforeSamoaDateLineChangeAbs.toZonedDateTimeISO(timeZone);
var added = start.add({
@ -60,7 +60,6 @@ var undo = added.subtract(diff);
assert.sameValue(`${ undo }`, `${ start }`);
// Samoa date line change (subtract): 11:00PM 31 Dec 2011 -> 10:00PM 29 Dec 2011
var timeZone = Temporal.TimeZone.from("Pacific/Apia");
var dayAfterSamoaDateLineChangeAbs = timeZone.getInstantFor(new Temporal.PlainDateTime(2011, 12, 31, 23));
var start = dayAfterSamoaDateLineChangeAbs.toZonedDateTimeISO(timeZone);
var skipped = start.subtract({

@ -27,8 +27,9 @@ var start = dayBeforeDstStart.startOfDay();
assert.sameValue(`${ start.toPlainDate() }`, `${ dayBeforeDstStart.toPlainDate() }`);
assert.sameValue(`${ start.toPlainTime() }`, "00:00:00");
var dayAfterSamoaDateLineChange = Temporal.ZonedDateTime.from("2011-12-31T22:00+14:00[Pacific/Apia]");
var dayBeforeSamoaDateLineChange = Temporal.ZonedDateTime.from("2011-12-29T22:00-10:00[Pacific/Apia]");
var samoa = TemporalHelpers.crossDateLineTimeZone();
var dayAfterSamoaDateLineChange = Temporal.PlainDateTime.from("2011-12-31T22:00").toZonedDateTime(samoa);
var dayBeforeSamoaDateLineChange = Temporal.PlainDateTime.from("2011-12-29T22:00").toZonedDateTime(samoa);
// startOfDay works after Samoa date line change
var start = dayAfterSamoaDateLineChange.startOfDay();