Temporal: Use TemporalHelpers.springForwardFallBackTimeZone in staging

Some tests in staging used various IANA time zones in order to test DST
behaviour. Since implementations are technically not required to
understand IANA time zones, we have a fake DST time zone in
TemporalHelpers. Use that instead.

For a few cases where it's not practical to use the fake DST time zone
(because it only has one spring-forward and one fall-back transition, for
example), move a few tests into staging/Intl402/Temporal/.

See: 
This commit is contained in:
Philip Chimento 2022-09-30 13:05:57 -07:00 committed by Ms2ger
parent 42074e7fe7
commit 886f091bd3
17 changed files with 482 additions and 333 deletions

@ -0,0 +1,73 @@
// Copyright (C) 2018 Bloomberg LP. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal-duration-objects
description: >
Various DST arithmetic tests that it's impractical to do without a time zone
database in the implementation
features: [Temporal]
---*/
// Tests for arithmetic that start inside a repeated hour, and end in a skipped
// hour. We have TemporalHelpers.springForwardFallBackTimeZone which is
// sufficient to test this for Temporal.Duration.prototype.add, and
// Temporal.Duration.prototype.round, but it's impractical to replicate all the
// TZDB data for testing it with other methods such as subtract() where we need
// to calculate to the _next_ transition
var skippedHourDay = Temporal.ZonedDateTime.from("2019-03-10T00:00[America/Vancouver]");
var repeatedHourDay = Temporal.ZonedDateTime.from("2019-11-03T00:00[America/Vancouver]");
var inRepeatedHour = Temporal.ZonedDateTime.from("2019-11-03T01:00-07:00[America/Vancouver]");
// subtract()
var oneDay = new Temporal.Duration(0, 0, 0, 1);
assert.sameValue(`${ Temporal.Duration.from({
days: 127,
hours: 1
}).subtract(oneDay, { relativeTo: inRepeatedHour }) }`, "P126DT1H");
var hours24 = new Temporal.Duration(0, 0, 0, 0, 24);
assert.sameValue(`${ Temporal.Duration.from({
days: 127,
hours: 1
}).subtract(hours24, { relativeTo: inRepeatedHour }) }`, "P126D");
// total()
var totalDays = Temporal.Duration.from({
days: 126,
hours: 1
}).total({
unit: "days",
relativeTo: inRepeatedHour
});
assert(Math.abs(totalDays - (126 + 1 / 23)) < Number.EPSILON);
assert.sameValue(Temporal.Duration.from({
days: 126,
hours: 1
}).total({
unit: "hours",
relativeTo: inRepeatedHour
}), 3026);
// Tests for casting relativeTo to ZonedDateTime when possible:
// Without a TZDB, it's not possible to get a ZonedDateTime with DST from a
// string.
assert.sameValue(
`${ oneDay.add(hours24, { relativeTo: "2019-11-02T00:00[America/Vancouver]" }) }`,
"P1DT24H"
);
var hours25 = new Temporal.Duration(0, 0, 0, 0, 25);
assert.sameValue(`${ hours25.round({
largestUnit: "days",
relativeTo: "2019-11-03T00:00[America/Vancouver]"
}) }`, "P1D");
assert.sameValue(
`${ oneDay.subtract(hours24, { relativeTo: "2019-11-03T00:00[America/Vancouver]" }) }`,
"PT1H"
);
assert.sameValue(oneDay.total({
unit: "hours",
relativeTo: "2019-11-03T00:00[America/Vancouver]"
}), 25);

@ -0,0 +1,98 @@
// Copyright (C) 2018 Bloomberg LP. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal-zoneddatetime-objects
description: String parsing cases that require a TZDB in the implementation
features: [Temporal]
---*/
// parses with an IANA zone but no offset (with disambiguation)
var zdt = Temporal.ZonedDateTime.from("2020-03-08T02:30[America/Los_Angeles]", { disambiguation: "earlier" });
assert.sameValue(zdt.toString(), "2020-03-08T01:30:00-08:00[America/Los_Angeles]");
// "Z" means preserve the exact time in the given IANA time zone
var zdt = Temporal.ZonedDateTime.from("2020-03-08T09:00:00Z[America/Los_Angeles]");
assert.sameValue(zdt.toString(), "2020-03-08T01:00:00-08:00[America/Los_Angeles]");
// Offset options
// { offset: 'prefer' } if offset matches time zone (first 1:30 when DST ends)
var zdt = Temporal.ZonedDateTime.from("2020-11-01T01:30-07:00[America/Los_Angeles]", { offset: "prefer" });
assert.sameValue(zdt.toString(), "2020-11-01T01:30:00-07:00[America/Los_Angeles]");
// { offset: 'prefer' } if offset matches time zone (second 1:30 when DST ends)
var zdt = Temporal.ZonedDateTime.from("2020-11-01T01:30-08:00[America/Los_Angeles]", { offset: "prefer" });
assert.sameValue(zdt.toString(), "2020-11-01T01:30:00-08:00[America/Los_Angeles]");
// { offset: 'prefer' } if offset does not match time zone
var zdt = Temporal.ZonedDateTime.from("2020-11-01T04:00-07:00[America/Los_Angeles]", { offset: "prefer" });
assert.sameValue(zdt.toString(), "2020-11-01T04:00:00-08:00[America/Los_Angeles]");
// { offset: 'ignore' } uses time zone only
var zdt = Temporal.ZonedDateTime.from("2020-11-01T04:00-12:00[America/Los_Angeles]", { offset: "ignore" });
assert.sameValue(zdt.toString(), "2020-11-01T04:00:00-08:00[America/Los_Angeles]");
// { offset: 'use' } uses offset only
var zdt = Temporal.ZonedDateTime.from("2020-11-01T04:00-07:00[America/Los_Angeles]", { offset: "use" });
assert.sameValue(zdt.toString(), "2020-11-01T03:00:00-08:00[America/Los_Angeles]");
// Disambiguation options
// plain datetime with multiple instants - Fall DST in Brazil
var str = "2019-02-16T23:45[America/Sao_Paulo]";
assert.sameValue(`${ Temporal.ZonedDateTime.from(str) }`, "2019-02-16T23:45:00-02:00[America/Sao_Paulo]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(str, { disambiguation: "compatible" }) }`, "2019-02-16T23:45:00-02:00[America/Sao_Paulo]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(str, { disambiguation: "earlier" }) }`, "2019-02-16T23:45:00-02:00[America/Sao_Paulo]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(str, { disambiguation: "later" }) }`, "2019-02-16T23:45:00-03:00[America/Sao_Paulo]");
assert.throws(RangeError, () => Temporal.ZonedDateTime.from(str, { disambiguation: "reject" }));
// plain datetime with multiple instants - Spring DST in Los Angeles
var str = "2020-03-08T02:30[America/Los_Angeles]";
assert.sameValue(`${ Temporal.ZonedDateTime.from(str) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(str, { disambiguation: "compatible" }) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(str, { disambiguation: "earlier" }) }`, "2020-03-08T01:30:00-08:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(str, { disambiguation: "later" }) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
assert.throws(RangeError, () => Temporal.ZonedDateTime.from(str, { disambiguation: "reject" }));
// uses disambiguation if offset is ignored
var str = "2020-03-08T02:30[America/Los_Angeles]";
var offset = "ignore";
assert.sameValue(`${ Temporal.ZonedDateTime.from(str, { offset }) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(str, {
offset,
disambiguation: "compatible"
}) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(str, {
offset,
disambiguation: "earlier"
}) }`, "2020-03-08T01:30:00-08:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(str, {
offset,
disambiguation: "later"
}) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
assert.throws(RangeError, () => Temporal.ZonedDateTime.from(str, {
offset,
disambiguation: "reject"
}));
// uses disambiguation if offset is wrong and option is prefer
var str = "2020-03-08T02:30-23:59[America/Los_Angeles]";
var offset = "prefer";
assert.sameValue(`${ Temporal.ZonedDateTime.from(str, { offset }) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(str, {
offset,
disambiguation: "compatible"
}) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(str, {
offset,
disambiguation: "earlier"
}) }`, "2020-03-08T01:30:00-08:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(str, {
offset,
disambiguation: "later"
}) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
assert.throws(RangeError, () => Temporal.ZonedDateTime.from(str, {
offset,
disambiguation: "reject"
}));

@ -0,0 +1,26 @@
// Copyright (C) 2018 Bloomberg LP. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-temporal-zoneddatetime-objects
description: Corner cases of time zone offset shifts
features: [Temporal]
---*/
// hoursInDay works with non-hour DST change
var zdt1 = Temporal.ZonedDateTime.from("2020-10-04T12:00[Australia/Lord_Howe]");
assert.sameValue(zdt1.hoursInDay, 23.5);
var zdt2 = Temporal.ZonedDateTime.from("2020-04-05T12:00[Australia/Lord_Howe]");
assert.sameValue(zdt2.hoursInDay, 24.5);
// hoursInDay works with non-half-hour DST change
var zdt = Temporal.ZonedDateTime.from("1933-01-01T12:00[Asia/Singapore]");
assert(Math.abs(zdt.hoursInDay - 23.666666666666668) < Number.EPSILON);
// hoursInDay works when day starts at 1:00 due to DST start at midnight
var zdt = Temporal.ZonedDateTime.from("2015-10-18T12:00:00-02:00[America/Sao_Paulo]");
assert.sameValue(zdt.hoursInDay, 23);
// startOfDay works when day starts at 1:00 due to DST start at midnight
var zdt = Temporal.ZonedDateTime.from("2015-10-18T12:00:00-02:00[America/Sao_Paulo]");
assert.sameValue(`${ zdt.startOfDay().toPlainTime() }`, "01:00:00");

@ -4,6 +4,7 @@
/*---
esid: sec-temporal-duration-objects
description: Temporal.Duration.prototype.add() works as expected
includes: [temporalHelpers.js]
features: [Temporal]
---*/
@ -17,24 +18,25 @@ assert.sameValue(`${ oneDay.add(hours24, { relativeTo }) }`, "P2D");
// relativeTo does not affect days if ZonedDateTime, and duration encompasses no DST change
var relativeTo = Temporal.ZonedDateTime.from("2017-01-01T00:00[+04:30]");
assert.sameValue(`${ oneDay.add(hours24, { relativeTo }) }`, "P2D");
var skippedHourDay = Temporal.ZonedDateTime.from("2019-03-10T00:00[America/Vancouver]");
var repeatedHourDay = Temporal.ZonedDateTime.from("2019-11-03T00:00[America/Vancouver]");
var inRepeatedHour = Temporal.ZonedDateTime.from("2019-11-03T01:00-07:00[America/Vancouver]");
// relativeTo affects days if ZonedDateTime, and duration encompasses DST change
var timeZone = TemporalHelpers.springForwardFallBackTimeZone();
var skippedHourDay = Temporal.PlainDateTime.from("2000-04-02").toZonedDateTime(timeZone);
var repeatedHourDay = Temporal.PlainDateTime.from("2000-10-29").toZonedDateTime(timeZone);
var inRepeatedHour = new Temporal.ZonedDateTime(972806400_000_000_000n, timeZone);
var hours12 = new Temporal.Duration(0, 0, 0, 0, 12);
var hours25 = new Temporal.Duration(0, 0, 0, 0, 25);
// relativeTo affects days if ZonedDateTime, and duration encompasses DST change",
// start inside repeated hour, end after",
// start inside repeated hour, end after
assert.sameValue(`${ hours25.add(oneDay, { relativeTo: inRepeatedHour }) }`, "P2D");
assert.sameValue(`${ oneDay.add(hours25, { relativeTo: inRepeatedHour }) }`, "P2DT1H");
// start after repeated hour, end inside (negative)"
var relativeTo = Temporal.ZonedDateTime.from("2019-11-05T01:00[America/Vancouver]");
// start after repeated hour, end inside (negative)
var relativeTo = Temporal.PlainDateTime.from("2000-10-31T01:00").toZonedDateTime(timeZone);
assert.sameValue(`${ hours25.negated().add(oneDay.negated(), { relativeTo }) }`, "-P2DT1H");
assert.sameValue(`${ oneDay.negated().add(hours25.negated(), { relativeTo }) }`, "-P2D");
// start inside repeated hour, end in skipped hour",
// start inside repeated hour, end in skipped hour
assert.sameValue(`${ hours25.add(Temporal.Duration.from({
days: 125,
hours: 1
@ -44,44 +46,44 @@ assert.sameValue(`${ oneDay.add(Temporal.Duration.from({
hours: 1
}), { relativeTo: inRepeatedHour }) }`, "P126DT1H");
// start in normal hour, end in skipped hour",
var relativeTo = Temporal.ZonedDateTime.from("2019-03-08T02:30[America/Vancouver]");
// start in normal hour, end in skipped hour
var relativeTo = Temporal.PlainDateTime.from("2000-03-31T02:30").toZonedDateTime(timeZone);
assert.sameValue(`${ oneDay.add(hours25, { relativeTo }) }`, "P2DT1H");
assert.sameValue(`${ hours25.add(oneDay, { relativeTo }) }`, "P2D");
// start before skipped hour, end >1 day after",
// start before skipped hour, end >1 day after
assert.sameValue(`${ hours25.add(oneDay, { relativeTo: skippedHourDay }) }`, "P2DT2H");
assert.sameValue(`${ oneDay.add(hours25, { relativeTo: skippedHourDay }) }`, "P2DT1H");
// start after skipped hour, end >1 day before (negative)",
var relativeTo = Temporal.ZonedDateTime.from("2019-03-11T00:00[America/Vancouver]");
// start after skipped hour, end >1 day before (negative)
var relativeTo = Temporal.PlainDateTime.from("2000-04-03T00:00").toZonedDateTime(timeZone);
assert.sameValue(`${ hours25.negated().add(oneDay.negated(), { relativeTo }) }`, "-P2DT2H");
assert.sameValue(`${ oneDay.negated().add(hours25.negated(), { relativeTo }) }`, "-P2DT1H");
// start before skipped hour, end <1 day after",
// start before skipped hour, end <1 day after
assert.sameValue(`${ hours12.add(oneDay, { relativeTo: skippedHourDay }) }`, "P1DT13H");
assert.sameValue(`${ oneDay.add(hours12, { relativeTo: skippedHourDay }) }`, "P1DT12H");
// start after skipped hour, end <1 day before (negative)",
var relativeTo = Temporal.ZonedDateTime.from("2019-03-10T12:00[America/Vancouver]");
// start after skipped hour, end <1 day before (negative)
var relativeTo = Temporal.PlainDateTime.from("2000-04-02T12:00").toZonedDateTime(timeZone);
assert.sameValue(`${ hours12.negated().add(oneDay.negated(), { relativeTo }) }`, "-P1DT13H");
assert.sameValue(`${ oneDay.negated().add(hours12.negated(), { relativeTo }) }`, "-P1DT12H");
// start before repeated hour, end >1 day after",
// start before repeated hour, end >1 day after
assert.sameValue(`${ hours25.add(oneDay, { relativeTo: repeatedHourDay }) }`, "P2D");
assert.sameValue(`${ oneDay.add(hours25, { relativeTo: repeatedHourDay }) }`, "P2DT1H");
// start after repeated hour, end >1 day before (negative)",
var relativeTo = Temporal.ZonedDateTime.from("2019-11-04T00:00[America/Vancouver]");
// start after repeated hour, end >1 day before (negative)
var relativeTo = Temporal.PlainDateTime.from("2000-10-30T00:00").toZonedDateTime(timeZone);
assert.sameValue(`${ hours25.negated().add(oneDay.negated(), { relativeTo }) }`, "-P2D");
assert.sameValue(`${ oneDay.negated().add(hours25.negated(), { relativeTo }) }`, "-P2DT1H");
// start before repeated hour, end <1 day after",
// start before repeated hour, end <1 day after
assert.sameValue(`${ hours12.add(oneDay, { relativeTo: repeatedHourDay }) }`, "P1DT11H");
assert.sameValue(`${ oneDay.add(hours12, { relativeTo: repeatedHourDay }) }`, "P1DT12H");
// start after repeated hour, end <1 day before (negative)",
var relativeTo = Temporal.ZonedDateTime.from("2019-11-03T12:00[America/Vancouver]");
// start after repeated hour, end <1 day before (negative)
var relativeTo = Temporal.PlainDateTime.from("2000-10-29T12:00").toZonedDateTime(timeZone);
assert.sameValue(`${ hours12.negated().add(oneDay.negated(), { relativeTo }) }`, "-P1DT11H");
assert.sameValue(`${ oneDay.negated().add(hours12.negated(), { relativeTo }) }`, "-P1DT12H");
@ -91,13 +93,12 @@ assert.sameValue(`${ hours25.add(oneDay, { relativeTo }) }`, "P3DT1H");
assert.sameValue(`${ oneDay.add(hours25, { relativeTo }) }`, "P3DT1H");
// casts relativeTo to ZonedDateTime if possible
assert.sameValue(`${ oneDay.add(hours24, { relativeTo: "2019-11-02T00:00[America/Vancouver]" }) }`, "P1DT24H");
assert.sameValue(`${ oneDay.add(hours24, {
relativeTo: {
year: 2019,
month: 11,
day: 2,
timeZone: "America/Vancouver"
year: 2000,
month: 10,
day: 28,
timeZone
}
}) }`, "P1DT24H");

@ -4,6 +4,7 @@
/*---
esid: sec-temporal-duration-objects
description: Temporal.Duration.prototype.round() works as expected
includes: [temporalHelpers.js]
features: [Temporal]
---*/
@ -31,15 +32,16 @@ assert.sameValue(`${ hours25.round({
largestUnit: "days",
relativeTo
}) }`, "P1DT1H");
var skippedHourDay = Temporal.ZonedDateTime.from("2019-03-10T00:00[America/Vancouver]");
var repeatedHourDay = Temporal.ZonedDateTime.from("2019-11-03T00:00[America/Vancouver]");
var inRepeatedHour = Temporal.ZonedDateTime.from("2019-11-03T01:00-07:00[America/Vancouver]");
// relativeTo affects days if ZonedDateTime, and duration encompasses DST change
var timeZone = TemporalHelpers.springForwardFallBackTimeZone();
var skippedHourDay = Temporal.PlainDateTime.from("2000-04-02").toZonedDateTime(timeZone);
var repeatedHourDay = Temporal.PlainDateTime.from("2000-10-29").toZonedDateTime(timeZone);
var inRepeatedHour = new Temporal.ZonedDateTime(972806400_000_000_000n, timeZone);
var oneDay = new Temporal.Duration(0, 0, 0, 1);
var hours12 = new Temporal.Duration(0, 0, 0, 0, 12);
// relativeTo affects days if ZonedDateTime, and duration encompasses DST change"
// start inside repeated hour, end after",
// start inside repeated hour, end after
assert.sameValue(`${ hours25.round({
largestUnit: "days",
relativeTo: inRepeatedHour
@ -49,8 +51,8 @@ assert.sameValue(`${ oneDay.round({
relativeTo: inRepeatedHour
}) }`, "PT25H");
// start after repeated hour, end inside (negative)",
var relativeTo = Temporal.ZonedDateTime.from("2019-11-04T01:00[America/Vancouver]");
// start after repeated hour, end inside (negative)
var relativeTo = Temporal.PlainDateTime.from("2000-10-30T01:00").toZonedDateTime(timeZone);
assert.sameValue(`${ hours25.negated().round({
largestUnit: "days",
relativeTo
@ -60,7 +62,7 @@ assert.sameValue(`${ oneDay.negated().round({
relativeTo
}) }`, "-PT25H");
// start inside repeated hour, end in skipped hour",
// start inside repeated hour, end in skipped hour
assert.sameValue(`${ Temporal.Duration.from({
days: 126,
hours: 1
@ -76,8 +78,8 @@ assert.sameValue(`${ Temporal.Duration.from({
relativeTo: inRepeatedHour
}) }`, "PT3026H");
// start in normal hour, end in skipped hour",
var relativeTo = Temporal.ZonedDateTime.from("2019-03-09T02:30[America/Vancouver]");
// start in normal hour, end in skipped hour
var relativeTo = Temporal.PlainDateTime.from("2000-04-01T02:30").toZonedDateTime(timeZone);
assert.sameValue(`${ hours25.round({
largestUnit: "days",
relativeTo
@ -87,7 +89,7 @@ assert.sameValue(`${ oneDay.round({
relativeTo
}) }`, "PT24H");
// start before skipped hour, end >1 day after",
// start before skipped hour, end >1 day after
assert.sameValue(`${ hours25.round({
largestUnit: "days",
relativeTo: skippedHourDay
@ -97,8 +99,8 @@ assert.sameValue(`${ oneDay.round({
relativeTo: skippedHourDay
}) }`, "PT23H");
// start after skipped hour, end >1 day before (negative)",
var relativeTo = Temporal.ZonedDateTime.from("2019-03-11T00:00[America/Vancouver]");
// start after skipped hour, end >1 day before (negative)
var relativeTo = Temporal.PlainDateTime.from("2000-04-03T00:00").toZonedDateTime(timeZone);
assert.sameValue(`${ hours25.negated().round({
largestUnit: "days",
relativeTo
@ -108,20 +110,20 @@ assert.sameValue(`${ oneDay.negated().round({
relativeTo
}) }`, "-PT23H");
// start before skipped hour, end <1 day after",
// start before skipped hour, end <1 day after
assert.sameValue(`${ hours12.round({
largestUnit: "days",
relativeTo: skippedHourDay
}) }`, "PT12H");
// start after skipped hour, end <1 day before (negative)",
var relativeTo = Temporal.ZonedDateTime.from("2019-03-10T12:00[America/Vancouver]");
// start after skipped hour, end <1 day before (negative)
var relativeTo = Temporal.PlainDateTime.from("2000-04-02T12:00").toZonedDateTime(timeZone);
assert.sameValue(`${ hours12.negated().round({
largestUnit: "days",
relativeTo
}) }`, "-PT12H");
// start before repeated hour, end >1 day after",
// start before repeated hour, end >1 day after
assert.sameValue(`${ hours25.round({
largestUnit: "days",
relativeTo: repeatedHourDay
@ -131,8 +133,8 @@ assert.sameValue(`${ oneDay.round({
relativeTo: repeatedHourDay
}) }`, "PT25H");
// start after repeated hour, end >1 day before (negative)",
var relativeTo = Temporal.ZonedDateTime.from("2019-11-04T00:00[America/Vancouver]");
// start after repeated hour, end >1 day before (negative)
var relativeTo = Temporal.PlainDateTime.from("2000-10-30T00:00").toZonedDateTime(timeZone);
assert.sameValue(`${ hours25.negated().round({
largestUnit: "days",
relativeTo
@ -142,14 +144,14 @@ assert.sameValue(`${ oneDay.negated().round({
relativeTo
}) }`, "-PT25H");
// start before repeated hour, end <1 day after",
// start before repeated hour, end <1 day after
assert.sameValue(`${ hours12.round({
largestUnit: "days",
relativeTo: repeatedHourDay
}) }`, "PT12H");
// start after repeated hour, end <1 day before (negative)",
var relativeTo = Temporal.ZonedDateTime.from("2019-11-03T12:00[America/Vancouver]");
// start after repeated hour, end <1 day before (negative)
var relativeTo = Temporal.PlainDateTime.from("2000-10-29T12:00").toZonedDateTime(timeZone);
assert.sameValue(`${ hours12.negated().round({
largestUnit: "days",
relativeTo
@ -167,17 +169,13 @@ assert.sameValue(`${ Temporal.Duration.from({ hours: 48 }).round({
}) }`, "P3D");
// casts relativeTo to ZonedDateTime if possible
assert.sameValue(`${ hours25.round({
largestUnit: "days",
relativeTo: "2019-11-03T00:00[America/Vancouver]"
}) }`, "P1D");
assert.sameValue(`${ hours25.round({
largestUnit: "days",
relativeTo: {
year: 2019,
month: 11,
day: 3,
timeZone: "America/Vancouver"
year: 2000,
month: 10,
day: 29,
timeZone
}
}) }`, "P1D");

@ -4,6 +4,7 @@
/*---
esid: sec-temporal-duration-objects
description: Temporal.Duration.prototype.subtract() works as expected
includes: [temporalHelpers.js]
features: [Temporal]
---*/
@ -17,29 +18,21 @@ assert.sameValue(`${ oneDay.subtract(hours24, { relativeTo }) }`, "PT0S");
// relativeTo does not affect days if ZonedDateTime, and duration encompasses no DST change
var relativeTo = Temporal.ZonedDateTime.from("2017-01-01T00:00[+04:30]");
assert.sameValue(`${ oneDay.subtract(hours24, { relativeTo }) }`, "PT0S");
var skippedHourDay = Temporal.ZonedDateTime.from("2019-03-10T00:00[America/Vancouver]");
var repeatedHourDay = Temporal.ZonedDateTime.from("2019-11-03T00:00[America/Vancouver]");
var inRepeatedHour = Temporal.ZonedDateTime.from("2019-11-03T01:00-07:00[America/Vancouver]");
// relativeTo affects days if ZonedDateTime, and duration encompasses DST change
var timeZone = TemporalHelpers.springForwardFallBackTimeZone();
var skippedHourDay = Temporal.PlainDateTime.from("2000-04-02").toZonedDateTime(timeZone);
var repeatedHourDay = Temporal.PlainDateTime.from("2000-10-29").toZonedDateTime(timeZone);
var inRepeatedHour = new Temporal.ZonedDateTime(972806400_000_000_000n, timeZone);
var twoDays = new Temporal.Duration(0, 0, 0, 2);
var threeDays = new Temporal.Duration(0, 0, 0, 3);
// relativeTo affects days if ZonedDateTime, and duration encompasses DST change
// start inside repeated hour, end after"
// start inside repeated hour, end after
assert.sameValue(`${ hours24.subtract(oneDay, { relativeTo: inRepeatedHour }) }`, "-PT1H");
assert.sameValue(`${ oneDay.subtract(hours24, { relativeTo: inRepeatedHour }) }`, "PT1H");
// start inside repeated hour, end in skipped hour
assert.sameValue(`${ Temporal.Duration.from({
days: 127,
hours: 1
}).subtract(oneDay, { relativeTo: inRepeatedHour }) }`, "P126DT1H");
assert.sameValue(`${ Temporal.Duration.from({
days: 127,
hours: 1
}).subtract(hours24, { relativeTo: inRepeatedHour }) }`, "P126D");
// start in normal hour, end in skipped hour
var relativeTo = Temporal.ZonedDateTime.from("2019-03-09T02:30[America/Vancouver]");
var relativeTo = Temporal.PlainDateTime.from("2000-04-01T02:30").toZonedDateTime(timeZone);
assert.sameValue(`${ hours24.subtract(oneDay, { relativeTo }) }`, "PT1H");
assert.sameValue(`${ oneDay.subtract(hours24, { relativeTo }) }`, "PT0S");
@ -65,13 +58,12 @@ assert.sameValue(`${ twoDays.subtract(Temporal.Duration.from({ hours: 48 }), { r
assert.sameValue(`${ Temporal.Duration.from({ hours: 48 }).subtract(twoDays, { relativeTo }) }`, "P2D");
// casts relativeTo to ZonedDateTime if possible
assert.sameValue(`${ oneDay.subtract(hours24, { relativeTo: "2019-11-03T00:00[America/Vancouver]" }) }`, "PT1H");
assert.sameValue(`${ oneDay.subtract(hours24, {
relativeTo: {
year: 2019,
month: 11,
day: 3,
timeZone: "America/Vancouver"
year: 2000,
month: 10,
day: 29,
timeZone
}
}) }`, "PT1H");

@ -4,6 +4,7 @@
/*---
esid: sec-temporal-duration-objects
description: Temporal.Duration.prototype.total()
includes: [temporalHelpers.js]
features: [Temporal]
---*/
@ -256,15 +257,16 @@ assert.sameValue(oneDay.total({
unit: "hours",
relativeTo
}), 24);
var skippedHourDay = Temporal.ZonedDateTime.from("2019-03-10T00:00[America/Vancouver]");
var repeatedHourDay = Temporal.ZonedDateTime.from("2019-11-03T00:00[America/Vancouver]");
var inRepeatedHour = Temporal.ZonedDateTime.from("2019-11-03T01:00-07:00[America/Vancouver]");
// relativeTo affects days if ZonedDateTime, and duration encompasses DST change"
var timeZone = TemporalHelpers.springForwardFallBackTimeZone();
var skippedHourDay = Temporal.PlainDateTime.from("2000-04-02").toZonedDateTime(timeZone);
var repeatedHourDay = Temporal.PlainDateTime.from("2000-10-29").toZonedDateTime(timeZone);
var inRepeatedHour = new Temporal.ZonedDateTime(972806400_000_000_000n, timeZone);
var hours12 = new Temporal.Duration(0, 0, 0, 0, 12);
var hours25 = new Temporal.Duration(0, 0, 0, 0, 25);
//relativeTo affects days if ZonedDateTime, and duration encompasses DST change"
// start inside repeated hour, end after",
// start inside repeated hour, end after
assert.sameValue(hours25.total({
unit: "days",
relativeTo: inRepeatedHour
@ -274,8 +276,8 @@ assert.sameValue(oneDay.total({
relativeTo: inRepeatedHour
}), 25);
// start after repeated hour, end inside (negative)",
var relativeTo = Temporal.ZonedDateTime.from("2019-11-04T01:00[America/Vancouver]");
// start after repeated hour, end inside (negative)
var relativeTo = Temporal.PlainDateTime.from("2000-10-30T01:00").toZonedDateTime(timeZone);
assert.sameValue(hours25.negated().total({
unit: "days",
relativeTo
@ -285,25 +287,8 @@ assert.sameValue(oneDay.negated().total({
relativeTo
}), -25);
// start inside repeated hour, end in skipped hour",
var totalDays = Temporal.Duration.from({
days: 126,
hours: 1
}).total({
unit: "days",
relativeTo: inRepeatedHour
});
assert(Math.abs(totalDays - (126 + 1 / 23)) < Number.EPSILON);
assert.sameValue(Temporal.Duration.from({
days: 126,
hours: 1
}).total({
unit: "hours",
relativeTo: inRepeatedHour
}), 3026);
// start in normal hour, end in skipped hour",
var relativeTo = Temporal.ZonedDateTime.from("2019-03-09T02:30[America/Vancouver]");
// start in normal hour, end in skipped hour
var relativeTo = Temporal.PlainDateTime.from("2000-04-01T02:30").toZonedDateTime(timeZone);
var totalDays = hours25.total({
unit: "days",
relativeTo
@ -314,7 +299,7 @@ assert.sameValue(oneDay.total({
relativeTo
}), 24);
// start before skipped hour, end >1 day after",
// start before skipped hour, end >1 day after
var totalDays = hours25.total({
unit: "days",
relativeTo: skippedHourDay
@ -325,8 +310,8 @@ assert.sameValue(oneDay.total({
relativeTo: skippedHourDay
}), 23);
// start after skipped hour, end >1 day before (negative)",
var relativeTo = Temporal.ZonedDateTime.from("2019-03-11T00:00[America/Vancouver]");
// start after skipped hour, end >1 day before (negative)
var relativeTo = Temporal.PlainDateTime.from("2000-04-03T00:00").toZonedDateTime(timeZone);
var totalDays = hours25.negated().total({
unit: "days",
relativeTo
@ -337,22 +322,22 @@ assert.sameValue(oneDay.negated().total({
relativeTo
}), -23);
// start before skipped hour, end <1 day after",
// start before skipped hour, end <1 day after
var totalDays = hours12.total({
unit: "days",
relativeTo: skippedHourDay
});
assert(Math.abs(totalDays - 12 / 23) < Number.EPSILON);
// start after skipped hour, end <1 day before (negative)",
var relativeTo = Temporal.ZonedDateTime.from("2019-03-10T12:00[America/Vancouver]");
// start after skipped hour, end <1 day before (negative)
var relativeTo = Temporal.PlainDateTime.from("2000-04-02T12:00").toZonedDateTime(timeZone);
var totalDays = hours12.negated().total({
unit: "days",
relativeTo
});
assert(Math.abs(totalDays - -12 / 23) < Number.EPSILON);
// start before repeated hour, end >1 day after",
// start before repeated hour, end >1 day after
assert.sameValue(hours25.total({
unit: "days",
relativeTo: repeatedHourDay
@ -362,8 +347,8 @@ assert.sameValue(oneDay.total({
relativeTo: repeatedHourDay
}), 25);
// start after repeated hour, end >1 day before (negative)",
var relativeTo = Temporal.ZonedDateTime.from("2019-11-04T00:00[America/Vancouver]");
// start after repeated hour, end >1 day before (negative)
var relativeTo = Temporal.PlainDateTime.from("2000-10-30T00:00").toZonedDateTime(timeZone);
assert.sameValue(hours25.negated().total({
unit: "days",
relativeTo
@ -373,15 +358,15 @@ assert.sameValue(oneDay.negated().total({
relativeTo
}), -25);
// start before repeated hour, end <1 day after",
// start before repeated hour, end <1 day after
var totalDays = hours12.total({
unit: "days",
relativeTo: repeatedHourDay
});
assert(Math.abs(totalDays - 12 / 25) < Number.EPSILON);
// start after repeated hour, end <1 day before (negative)",
var relativeTo = Temporal.ZonedDateTime.from("2019-11-03T12:00[America/Vancouver]");
// start after repeated hour, end <1 day before (negative)
var relativeTo = Temporal.PlainDateTime.from("2000-10-29T12:00").toZonedDateTime(timeZone);
var totalDays = hours12.negated().total({
unit: "days",
relativeTo
@ -409,7 +394,7 @@ assert.sameValue(Temporal.Duration.from({ days: 3 }).total({
}), 48);
// totaling back up to days
var relativeTo = Temporal.ZonedDateTime.from("2019-11-02T00:00[America/Vancouver]");
var relativeTo = Temporal.PlainDateTime.from("2000-10-28T00:00").toZonedDateTime(timeZone);
assert.sameValue(Temporal.Duration.from({ hours: 48 }).total({ unit: "days" }), 2);
var totalDays = Temporal.Duration.from({ hours: 48 }).total({
unit: "days",
@ -418,17 +403,13 @@ var totalDays = Temporal.Duration.from({ hours: 48 }).total({
assert(Math.abs(totalDays - (1 + 24 / 25)) < Number.EPSILON);
// casts relativeTo to ZonedDateTime if possible
assert.sameValue(oneDay.total({
unit: "hours",
relativeTo: "2019-11-03T00:00[America/Vancouver]"
}), 25);
assert.sameValue(oneDay.total({
unit: "hours",
relativeTo: {
year: 2019,
month: 11,
day: 3,
timeZone: "America/Vancouver"
year: 2000,
month: 10,
day: 29,
timeZone
}
}), 25);

@ -4,23 +4,23 @@
/*---
esid: sec-temporal-timezone-objects
description: with DST change
includes: [temporalHelpers.js]
features: [Temporal]
---*/
// clock moving forward
var zone = new Temporal.TimeZone("Europe/Berlin");
var dtm = new Temporal.PlainDateTime(2019, 3, 31, 2, 45);
assert.sameValue(`${ zone.getInstantFor(dtm) }`, "2019-03-31T01:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "earlier" }) }`, "2019-03-31T00:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "later" }) }`, "2019-03-31T01:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "compatible" }) }`, "2019-03-31T01:45:00Z");
var zone = TemporalHelpers.springForwardFallBackTimeZone();
var dtm = new Temporal.PlainDateTime(2000, 4, 2, 2, 45);
assert.sameValue(`${ zone.getInstantFor(dtm) }`, "2000-04-02T10:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "earlier" }) }`, "2000-04-02T09:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "later" }) }`, "2000-04-02T10:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "compatible" }) }`, "2000-04-02T10:45:00Z");
assert.throws(RangeError, () => zone.getInstantFor(dtm, { disambiguation: "reject" }));
// clock moving backward
var zone = new Temporal.TimeZone("America/Sao_Paulo");
var dtm = new Temporal.PlainDateTime(2019, 2, 16, 23, 45);
assert.sameValue(`${ zone.getInstantFor(dtm) }`, "2019-02-17T01:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "earlier" }) }`, "2019-02-17T01:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "later" }) }`, "2019-02-17T02:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "compatible" }) }`, "2019-02-17T01:45:00Z");
var dtm = new Temporal.PlainDateTime(2000, 10, 29, 1, 45);
assert.sameValue(`${ zone.getInstantFor(dtm) }`, "2000-10-29T08:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "earlier" }) }`, "2000-10-29T08:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "later" }) }`, "2000-10-29T09:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "compatible" }) }`, "2000-10-29T08:45:00Z");
assert.throws(RangeError, () => zone.getInstantFor(dtm, { disambiguation: "reject" }));

@ -4,10 +4,11 @@
/*---
esid: sec-temporal-timezone-objects
description: getInstantFor disambiguation
includes: [temporalHelpers.js]
features: [Temporal]
---*/
var dtm = new Temporal.PlainDateTime(2019, 2, 16, 23, 45);
var dtm = new Temporal.PlainDateTime(2000, 10, 29, 1, 45);
// with constant offset
var zone = Temporal.TimeZone.from("+03:30");
@ -22,20 +23,19 @@ for (var disambiguation of [
}
// with daylight saving change - Fall
var zone = Temporal.TimeZone.from("America/Sao_Paulo");
assert.sameValue(`${ zone.getInstantFor(dtm) }`, "2019-02-17T01:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "earlier" }) }`, "2019-02-17T01:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "later" }) }`, "2019-02-17T02:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "compatible" }) }`, "2019-02-17T01:45:00Z");
var zone = TemporalHelpers.springForwardFallBackTimeZone();
assert.sameValue(`${ zone.getInstantFor(dtm) }`, "2000-10-29T08:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "earlier" }) }`, "2000-10-29T08:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "later" }) }`, "2000-10-29T09:45:00Z");
assert.sameValue(`${ zone.getInstantFor(dtm, { disambiguation: "compatible" }) }`, "2000-10-29T08:45:00Z");
assert.throws(RangeError, () => zone.getInstantFor(dtm, { disambiguation: "reject" }));
// with daylight saving change - Spring
var dtmLA = new Temporal.PlainDateTime(2020, 3, 8, 2, 30);
var zone = Temporal.TimeZone.from("America/Los_Angeles");
assert.sameValue(`${ zone.getInstantFor(dtmLA) }`, "2020-03-08T10:30:00Z");
assert.sameValue(`${ zone.getInstantFor(dtmLA, { disambiguation: "earlier" }) }`, "2020-03-08T09:30:00Z");
assert.sameValue(`${ zone.getInstantFor(dtmLA, { disambiguation: "later" }) }`, "2020-03-08T10:30:00Z");
assert.sameValue(`${ zone.getInstantFor(dtmLA, { disambiguation: "compatible" }) }`, "2020-03-08T10:30:00Z");
var dtmLA = new Temporal.PlainDateTime(2000, 4, 2, 2, 30);
assert.sameValue(`${ zone.getInstantFor(dtmLA) }`, "2000-04-02T10:30:00Z");
assert.sameValue(`${ zone.getInstantFor(dtmLA, { disambiguation: "earlier" }) }`, "2000-04-02T09:30:00Z");
assert.sameValue(`${ zone.getInstantFor(dtmLA, { disambiguation: "later" }) }`, "2000-04-02T10:30:00Z");
assert.sameValue(`${ zone.getInstantFor(dtmLA, { disambiguation: "compatible" }) }`, "2000-04-02T10:30:00Z");
assert.throws(RangeError, () => zone.getInstantFor(dtmLA, { disambiguation: "reject" }));
// throws on bad disambiguation

@ -4,7 +4,7 @@
/*---
esid: sec-temporal-timezone-objects
description: Temporal.TimeZone.prototype.getPossibleInstantsFor() works as expected
includes: [deepEqual.js]
includes: [deepEqual.js, temporalHelpers.js]
features: [Temporal]
---*/
@ -15,16 +15,15 @@ var dt = Temporal.PlainDateTime.from("2019-02-16T23:45");
assert.deepEqual(zone.getPossibleInstantsFor(dt).map(a => `${ a }`), ["2019-02-16T20:15:00Z"]);
// with clock moving forward
var zone = Temporal.TimeZone.from("Europe/Berlin");
var dt = Temporal.PlainDateTime.from("2019-03-31T02:45");
var zone = TemporalHelpers.springForwardFallBackTimeZone();
var dt = Temporal.PlainDateTime.from("2000-04-02T02:45");
assert.deepEqual(zone.getPossibleInstantsFor(dt), []);
// with clock moving backward
var zone = Temporal.TimeZone.from("America/Sao_Paulo");
var dt = Temporal.PlainDateTime.from("2019-02-16T23:45");
var dt = Temporal.PlainDateTime.from("2000-10-29T01:45");
assert.deepEqual(zone.getPossibleInstantsFor(dt).map(a => `${ a }`), [
"2019-02-17T01:45:00Z",
"2019-02-17T02:45:00Z"
"2000-10-29T08:45:00Z",
"2000-10-29T09:45:00Z"
]);
// casts argument

@ -4,12 +4,13 @@
/*---
esid: sec-temporal-zoneddatetime-objects
description: math around DST
includes: [temporalHelpers.js]
features: [Temporal]
---*/
var tz = new Temporal.TimeZone("America/Los_Angeles");
var hourBeforeDstStart = new Temporal.PlainDateTime(2020, 3, 8, 1).toZonedDateTime(tz);
var dayBeforeDstStart = new Temporal.PlainDateTime(2020, 3, 7, 2, 30).toZonedDateTime(tz);
var tz = TemporalHelpers.springForwardFallBackTimeZone();
var hourBeforeDstStart = new Temporal.PlainDateTime(2000, 4, 2, 1).toZonedDateTime(tz);
var dayBeforeDstStart = new Temporal.PlainDateTime(2000, 4, 1, 2, 30).toZonedDateTime(tz);
// add 1 hour to get to DST start
var added = hourBeforeDstStart.add({ hours: 1 });
@ -84,7 +85,7 @@ assert.sameValue(`${ undo }`, `${ end }`);
// 3:30 day before DST start -> 3:30 day of DST start
var start = dayBeforeDstStart.add({ hours: 1 });
var added = start.add({ days: 1 });
assert.sameValue(added.day, 8);
assert.sameValue(added.day, 2);
assert.sameValue(added.hour, 3);
assert.sameValue(added.minute, 30);
var diff = start.until(added, { largestUnit: "days" });
@ -94,7 +95,7 @@ assert.sameValue(`${ undo }`, `${ start }`);
// 2:30 day before DST start -> 3:30 day of DST start
var added = dayBeforeDstStart.add({ days: 1 });
assert.sameValue(added.day, 8);
assert.sameValue(added.day, 2);
assert.sameValue(added.hour, 3);
assert.sameValue(added.minute, 30);
var diff = dayBeforeDstStart.until(added, { largestUnit: "days" });
@ -105,7 +106,7 @@ assert.sameValue(`${ undo }`, `${ added }`);
// 1:30 day DST starts -> 4:30 day DST starts
var start = dayBeforeDstStart.add({ hours: 23 });
var added = start.add({ hours: 2 });
assert.sameValue(added.day, 8);
assert.sameValue(added.day, 2);
assert.sameValue(added.hour, 4);
assert.sameValue(added.minute, 30);
var diff = start.until(added, { largestUnit: "days" });
@ -116,7 +117,7 @@ assert.sameValue(`${ undo }`, `${ start }`);
// 2:00 day before DST starts -> 3:00 day DST starts
var start = hourBeforeDstStart.subtract({ days: 1 }).add({ hours: 1 });
var added = start.add({ days: 1 });
assert.sameValue(added.day, 8);
assert.sameValue(added.day, 2);
assert.sameValue(added.hour, 3);
assert.sameValue(added.minute, 0);
var diff = start.until(added, { largestUnit: "days" });
@ -127,7 +128,7 @@ assert.sameValue(`${ undo }`, `${ added }`);
// 1:00AM day DST starts -> (add 24 hours) -> 2:00AM day after DST starts
var start = hourBeforeDstStart;
var added = start.add({ hours: 24 });
assert.sameValue(added.day, 9);
assert.sameValue(added.day, 3);
assert.sameValue(added.hour, 2);
assert.sameValue(added.minute, 0);
var diff = start.until(added, { largestUnit: "days" });
@ -138,7 +139,7 @@ assert.sameValue(`${ undo }`, `${ start }`);
// 12:00AM day DST starts -> (add 24 hours) -> 1:00AM day after DST starts
var start = hourBeforeDstStart.subtract({ hours: 1 });
var added = start.add({ hours: 24 });
assert.sameValue(added.day, 9);
assert.sameValue(added.day, 3);
assert.sameValue(added.hour, 1);
assert.sameValue(added.minute, 0);
var diff = start.until(added, { largestUnit: "days" });
@ -147,16 +148,16 @@ var undo = added.subtract(diff);
assert.sameValue(`${ undo }`, `${ start }`);
// Difference can return day length > 24 hours
var start = Temporal.ZonedDateTime.from("2020-10-30T01:45-07:00[America/Los_Angeles]");
var end = Temporal.ZonedDateTime.from("2020-11-02T01:15-08:00[America/Los_Angeles]");
var start = Temporal.PlainDateTime.from("2000-10-27T01:45").toZonedDateTime(tz);
var end = Temporal.PlainDateTime.from("2000-10-30T01:15").toZonedDateTime(tz);
var diff = start.until(end, { largestUnit: "days" });
assert.sameValue(`${ diff }`, "P2DT24H30M");
var undo = start.add(diff);
assert.sameValue(`${ undo }`, `${ end }`);
// Difference rounding (nearest day) is DST-aware
var start = Temporal.ZonedDateTime.from("2020-03-10T02:30-07:00[America/Los_Angeles]");
var end = Temporal.ZonedDateTime.from("2020-03-07T14:15-08:00[America/Los_Angeles]");
var start = Temporal.PlainDateTime.from("2000-04-04T02:30").toZonedDateTime(tz);
var end = Temporal.PlainDateTime.from("2000-04-01T14:15").toZonedDateTime(tz);
var diff = start.until(end, {
smallestUnit: "days",
roundingMode: "halfExpand"
@ -164,8 +165,6 @@ var diff = start.until(end, {
assert.sameValue(`${ diff }`, "-P3D");
// Difference rounding (ceil day) is DST-aware
var start = Temporal.ZonedDateTime.from("2020-03-10T02:30-07:00[America/Los_Angeles]");
var end = Temporal.ZonedDateTime.from("2020-03-07T14:15-08:00[America/Los_Angeles]");
var diff = start.until(end, {
smallestUnit: "days",
roundingMode: "ceil"
@ -173,8 +172,6 @@ var diff = start.until(end, {
assert.sameValue(`${ diff }`, "-P2D");
// Difference rounding (trunc day) is DST-aware
var start = Temporal.ZonedDateTime.from("2020-03-10T02:30-07:00[America/Los_Angeles]");
var end = Temporal.ZonedDateTime.from("2020-03-07T14:15-08:00[America/Los_Angeles]");
var diff = start.until(end, {
smallestUnit: "days",
roundingMode: "trunc"
@ -182,8 +179,6 @@ var diff = start.until(end, {
assert.sameValue(`${ diff }`, "-P2D");
// Difference rounding (floor day) is DST-aware
var start = Temporal.ZonedDateTime.from("2020-03-10T02:30-07:00[America/Los_Angeles]");
var end = Temporal.ZonedDateTime.from("2020-03-07T14:15-08:00[America/Los_Angeles]");
var diff = start.until(end, {
smallestUnit: "days",
roundingMode: "floor"
@ -191,8 +186,6 @@ var diff = start.until(end, {
assert.sameValue(`${ diff }`, "-P3D");
// Difference rounding (nearest hour) is DST-aware
var start = Temporal.ZonedDateTime.from("2020-03-10T02:30-07:00[America/Los_Angeles]");
var end = Temporal.ZonedDateTime.from("2020-03-07T14:15-08:00[America/Los_Angeles]");
var diff = start.until(end, {
largestUnit: "days",
smallestUnit: "hours",
@ -201,8 +194,6 @@ var diff = start.until(end, {
assert.sameValue(`${ diff }`, "-P2DT12H");
// Difference rounding (ceil hour) is DST-aware
var start = Temporal.ZonedDateTime.from("2020-03-10T02:30-07:00[America/Los_Angeles]");
var end = Temporal.ZonedDateTime.from("2020-03-07T14:15-08:00[America/Los_Angeles]");
var diff = start.until(end, {
largestUnit: "days",
smallestUnit: "hours",
@ -211,8 +202,6 @@ var diff = start.until(end, {
assert.sameValue(`${ diff }`, "-P2DT12H");
// Difference rounding (trunc hour) is DST-aware
var start = Temporal.ZonedDateTime.from("2020-03-10T02:30-07:00[America/Los_Angeles]");
var end = Temporal.ZonedDateTime.from("2020-03-07T14:15-08:00[America/Los_Angeles]");
var diff = start.until(end, {
largestUnit: "days",
smallestUnit: "hours",
@ -221,8 +210,6 @@ var diff = start.until(end, {
assert.sameValue(`${ diff }`, "-P2DT12H");
// Difference rounding (floor hour) is DST-aware
var start = Temporal.ZonedDateTime.from("2020-03-10T02:30-07:00[America/Los_Angeles]");
var end = Temporal.ZonedDateTime.from("2020-03-07T14:15-08:00[America/Los_Angeles]");
var diff = start.until(end, {
largestUnit: "days",
smallestUnit: "hours",
@ -231,14 +218,14 @@ var diff = start.until(end, {
assert.sameValue(`${ diff }`, "-P2DT13H");
// Difference when date portion ends inside a DST-skipped period
var start = Temporal.ZonedDateTime.from("2020-03-07T02:30-08:00[America/Los_Angeles]");
var end = Temporal.ZonedDateTime.from("2020-03-08T03:15-07:00[America/Los_Angeles]");
var start = Temporal.PlainDateTime.from("2000-04-01T02:30").toZonedDateTime(tz);
var end = Temporal.PlainDateTime.from("2000-04-02T03:15").toZonedDateTime(tz);
var diff = start.until(end, { largestUnit: "days" });
assert.sameValue(`${ diff }`, "PT23H45M");
// Difference when date portion ends inside day skipped by Samoa's 24hr 2011 transition
var end = Temporal.ZonedDateTime.from("2011-12-31T05:00+14:00[Pacific/Apia]");
var start = Temporal.ZonedDateTime.from("2011-12-28T10:00-10:00[Pacific/Apia]");
var end = Temporal.PlainDateTime.from("2011-12-31T05:00").toZonedDateTime(timeZone);
var start = Temporal.PlainDateTime.from("2011-12-28T10:00").toZonedDateTime(timeZone);
var diff = start.until(end, { largestUnit: "days" });
assert.sameValue(`${ diff }`, "P1DT19H");

@ -4,12 +4,13 @@
/*---
esid: sec-temporal-zoneddatetime-objects
description: properties around DST
includes: [temporalHelpers.js]
features: [Temporal]
---*/
var tz = new Temporal.TimeZone("America/Los_Angeles");
var hourBeforeDstStart = new Temporal.PlainDateTime(2020, 3, 8, 1).toZonedDateTime(tz);
var dayBeforeDstStart = new Temporal.PlainDateTime(2020, 3, 7, 2, 30).toZonedDateTime(tz);
var tz = TemporalHelpers.springForwardFallBackTimeZone();
var hourBeforeDstStart = new Temporal.PlainDateTime(2000, 4, 2, 1).toZonedDateTime(tz);
var dayBeforeDstStart = new Temporal.PlainDateTime(2000, 4, 1, 2, 30).toZonedDateTime(tz);
// hoursInDay works with DST start
assert.sameValue(hourBeforeDstStart.hoursInDay, 23);
@ -18,31 +19,14 @@ assert.sameValue(hourBeforeDstStart.hoursInDay, 23);
assert.sameValue(dayBeforeDstStart.hoursInDay, 24);
// hoursInDay works with DST end
var dstEnd = Temporal.ZonedDateTime.from("2020-11-01T01:00-08:00[America/Los_Angeles]");
var dstEnd = Temporal.PlainDateTime.from("2000-10-29T01:00").toZonedDateTime(tz);
assert.sameValue(dstEnd.hoursInDay, 25);
// hoursInDay works with non-hour DST change
var zdt1 = Temporal.ZonedDateTime.from("2020-10-04T12:00[Australia/Lord_Howe]");
assert.sameValue(zdt1.hoursInDay, 23.5);
var zdt2 = Temporal.ZonedDateTime.from("2020-04-05T12:00[Australia/Lord_Howe]");
assert.sameValue(zdt2.hoursInDay, 24.5);
// hoursInDay works with non-half-hour DST change
var zdt = Temporal.ZonedDateTime.from("1933-01-01T12:00[Asia/Singapore]");
assert(Math.abs(zdt.hoursInDay - 23.666666666666668) < Number.EPSILON);
// hoursInDay works when day starts at 1:00 due to DST start at midnight
var zdt = Temporal.ZonedDateTime.from("2015-10-18T12:00:00-02:00[America/Sao_Paulo]");
assert.sameValue(zdt.hoursInDay, 23);
// startOfDay works
var start = dayBeforeDstStart.startOfDay();
assert.sameValue(`${ start.toPlainDate() }`, `${ dayBeforeDstStart.toPlainDate() }`);
assert.sameValue(`${ start.toPlainTime() }`, "00:00:00");
// startOfDay works when day starts at 1:00 due to DST start at midnight
var zdt = Temporal.ZonedDateTime.from("2015-10-18T12:00:00-02:00[America/Sao_Paulo]");
assert.sameValue(`${ zdt.startOfDay().toPlainTime() }`, "01: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]");

@ -4,6 +4,7 @@
/*---
esid: sec-temporal-zoneddatetime-objects
description: property bags
includes: [temporalHelpers.js]
features: [Temporal]
---*/
@ -119,11 +120,11 @@ var obj = {
assert.throws(RangeError, () => Temporal.ZonedDateTime.from(obj));
assert.throws(RangeError, () => Temporal.ZonedDateTime.from(obj, { offset: "reject" }));
var cali = Temporal.TimeZone.from("America/Los_Angeles");
var cali = TemporalHelpers.springForwardFallBackTimeZone();
var date = {
year: 2020,
month: 11,
day: 1,
year: 2000,
month: 10,
day: 29,
timeZone: cali
};
// { offset: 'prefer' } if offset matches time zone (first 1:30 when DST ends)
@ -133,7 +134,7 @@ var obj = {
minute: 30,
offset: "-07:00"
};
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { offset: "prefer" }) }`, "2020-11-01T01:30:00-07:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { offset: "prefer" }) }`, "2000-10-29T01:30:00-07:00[Custom/Spring_Fall]");
// { offset: 'prefer' } if offset matches time zone (second 1:30 when DST ends)
var obj = {
@ -142,7 +143,7 @@ var obj = {
minute: 30,
offset: "-08:00"
};
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { offset: "prefer" }) }`, "2020-11-01T01:30:00-08:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { offset: "prefer" }) }`, "2000-10-29T01:30:00-08:00[Custom/Spring_Fall]");
// { offset: 'prefer' } if offset does not match time zone"
var obj = {
@ -150,7 +151,7 @@ var obj = {
hour: 4,
offset: "-07:00"
};
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { offset: "prefer" }) }`, "2020-11-01T04:00:00-08:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { offset: "prefer" }) }`, "2000-10-29T04:00:00-08:00[Custom/Spring_Fall]");
// { offset: 'ignore' } uses time zone only
var obj = {
@ -158,7 +159,7 @@ var obj = {
hour: 4,
offset: "-12:00"
};
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { offset: "ignore" }) }`, "2020-11-01T04:00:00-08:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { offset: "ignore" }) }`, "2000-10-29T04:00:00-08:00[Custom/Spring_Fall]");
// { offset: 'use' } uses offset only
var obj = {
@ -166,93 +167,89 @@ var obj = {
hour: 4,
offset: "-07:00"
};
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { offset: "use" }) }`, "2020-11-01T03:00:00-08:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { offset: "use" }) }`, "2000-10-29T03:00:00-08:00[Custom/Spring_Fall]");
// Disambiguation options
// plain datetime with multiple instants - Fall DST in Brazil
var brazil = Temporal.TimeZone.from("America/Sao_Paulo");
// plain datetime with multiple instants - Fall DST
var obj = {
year: 2019,
month: 2,
day: 16,
hour: 23,
year: 2000,
month: 10,
day: 29,
hour: 1,
minute: 45,
timeZone: brazil
timeZone: cali
};
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj) }`, "2019-02-16T23:45:00-02:00[America/Sao_Paulo]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { disambiguation: "compatible" }) }`, "2019-02-16T23:45:00-02:00[America/Sao_Paulo]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { disambiguation: "earlier" }) }`, "2019-02-16T23:45:00-02:00[America/Sao_Paulo]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { disambiguation: "later" }) }`, "2019-02-16T23:45:00-03:00[America/Sao_Paulo]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj) }`, "2000-10-29T01:45:00-07:00[Custom/Spring_Fall]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { disambiguation: "compatible" }) }`, "2000-10-29T01:45:00-07:00[Custom/Spring_Fall]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { disambiguation: "earlier" }) }`, "2000-10-29T01:45:00-07:00[Custom/Spring_Fall]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { disambiguation: "later" }) }`, "2000-10-29T01:45:00-08:00[Custom/Spring_Fall]");
assert.throws(RangeError, () => Temporal.ZonedDateTime.from(obj, { disambiguation: "reject" }));
// plain datetime with multiple instants - Spring DST in Los Angeles
var cali = Temporal.TimeZone.from("America/Los_Angeles");
// plain datetime with multiple instants - Spring DST
var obj = {
year: 2020,
month: 3,
day: 8,
year: 2000,
month: 4,
day: 2,
hour: 2,
minute: 30,
timeZone: cali
};
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { disambiguation: "compatible" }) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { disambiguation: "earlier" }) }`, "2020-03-08T01:30:00-08:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { disambiguation: "later" }) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj) }`, "2000-04-02T03:30:00-07:00[Custom/Spring_Fall]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { disambiguation: "compatible" }) }`, "2000-04-02T03:30:00-07:00[Custom/Spring_Fall]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { disambiguation: "earlier" }) }`, "2000-04-02T01:30:00-08:00[Custom/Spring_Fall]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { disambiguation: "later" }) }`, "2000-04-02T03:30:00-07:00[Custom/Spring_Fall]");
assert.throws(RangeError, () => Temporal.ZonedDateTime.from(obj, { disambiguation: "reject" }));
// uses disambiguation if offset is ignored
var cali = Temporal.TimeZone.from("America/Los_Angeles");
var obj = {
year: 2020,
month: 3,
day: 8,
year: 2000,
month: 4,
day: 2,
hour: 2,
minute: 30,
timeZone: cali
};
var offset = "ignore";
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { offset }) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { offset }) }`, "2000-04-02T03:30:00-07:00[Custom/Spring_Fall]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, {
offset,
disambiguation: "compatible"
}) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
}) }`, "2000-04-02T03:30:00-07:00[Custom/Spring_Fall]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, {
offset,
disambiguation: "earlier"
}) }`, "2020-03-08T01:30:00-08:00[America/Los_Angeles]");
}) }`, "2000-04-02T01:30:00-08:00[Custom/Spring_Fall]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, {
offset,
disambiguation: "later"
}) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
}) }`, "2000-04-02T03:30:00-07:00[Custom/Spring_Fall]");
assert.throws(RangeError, () => Temporal.ZonedDateTime.from(obj, { disambiguation: "reject" }));
// uses disambiguation if offset is wrong and option is prefer
var cali = Temporal.TimeZone.from("America/Los_Angeles");
var obj = {
year: 2020,
month: 3,
day: 8,
year: 2000,
month: 4,
day: 2,
hour: 2,
minute: 30,
offset: "-23:59",
timeZone: cali
};
var offset = "prefer";
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { offset }) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, { offset }) }`, "2000-04-02T03:30:00-07:00[Custom/Spring_Fall]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, {
offset,
disambiguation: "compatible"
}) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
}) }`, "2000-04-02T03:30:00-07:00[Custom/Spring_Fall]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, {
offset,
disambiguation: "earlier"
}) }`, "2020-03-08T01:30:00-08:00[America/Los_Angeles]");
}) }`, "2000-04-02T01:30:00-08:00[Custom/Spring_Fall]");
assert.sameValue(`${ Temporal.ZonedDateTime.from(obj, {
offset,
disambiguation: "later"
}) }`, "2020-03-08T03:30:00-07:00[America/Los_Angeles]");
}) }`, "2000-04-02T03:30:00-07:00[Custom/Spring_Fall]");
assert.throws(RangeError, () => Temporal.ZonedDateTime.from(obj, {
offset,
disambiguation: "reject"

@ -4,6 +4,7 @@
/*---
esid: sec-temporal-zoneddatetime-objects
description: Temporal.ZonedDateTime.prototype.round()
includes: [temporalHelpers.js]
features: [Temporal]
---*/
@ -212,25 +213,27 @@ var bal = Temporal.ZonedDateTime.from("1976-11-18T23:59:59.999999999+01:00[+01:0
assert.sameValue(`${ bal.round({ smallestUnit }) }`, "1976-11-19T00:00:00+01:00[+01:00]");
});
var timeZone = TemporalHelpers.springForwardFallBackTimeZone();
// rounds correctly to a 25-hour day
var roundTo = { smallestUnit: "day" };
var roundMeDown = Temporal.ZonedDateTime.from("2020-11-01T12:29:59-08:00[America/Vancouver]");
assert.sameValue(`${ roundMeDown.round(roundTo) }`, "2020-11-01T00:00:00-07:00[America/Vancouver]");
var roundMeUp = Temporal.ZonedDateTime.from("2020-11-01T12:30:01-08:00[America/Vancouver]");
assert.sameValue(`${ roundMeUp.round(roundTo) }`, "2020-11-02T00:00:00-08:00[America/Vancouver]");
var roundMeDown = Temporal.PlainDateTime.from("2000-10-29T12:29:59").toZonedDateTime(timeZone);
assert.sameValue(`${ roundMeDown.round(roundTo) }`, "2000-10-29T00:00:00-07:00[Custom/Spring_Fall]");
var roundMeUp = Temporal.PlainDateTime.from("2000-10-29T12:30:01").toZonedDateTime(timeZone);
assert.sameValue(`${ roundMeUp.round(roundTo) }`, "2000-10-30T00:00:00-08:00[Custom/Spring_Fall]");
// rounds correctly to a 23-hour day
var roundTo = { smallestUnit: "day" };
var roundMeDown = Temporal.ZonedDateTime.from("2020-03-08T11:29:59-07:00[America/Vancouver]");
assert.sameValue(`${ roundMeDown.round(roundTo) }`, "2020-03-08T00:00:00-08:00[America/Vancouver]");
var roundMeUp = Temporal.ZonedDateTime.from("2020-03-08T11:30:01-07:00[America/Vancouver]");
assert.sameValue(`${ roundMeUp.round(roundTo) }`, "2020-03-09T00:00:00-07:00[America/Vancouver]");
var roundMeDown = Temporal.PlainDateTime.from("2000-04-02T11:29:59").toZonedDateTime(timeZone);
assert.sameValue(`${ roundMeDown.round(roundTo) }`, "2000-04-02T00:00:00-08:00[Custom/Spring_Fall]");
var roundMeUp = Temporal.PlainDateTime.from("2000-04-02T11:30:01").toZonedDateTime(timeZone);
assert.sameValue(`${ roundMeUp.round(roundTo) }`, "2000-04-03T00:00:00-07:00[Custom/Spring_Fall]");
// rounding up to a nonexistent wall-clock time
var almostSkipped = Temporal.ZonedDateTime.from("2018-11-03T23:59:59.999999999-03:00[America/Sao_Paulo]");
var almostSkipped = Temporal.PlainDateTime.from("2000-04-02T01:59:59.999999999").toZonedDateTime(timeZone);
var rounded = almostSkipped.round({
smallestUnit: "microsecond",
roundingMode: "halfExpand"
});
assert.sameValue(`${ rounded }`, "2018-11-04T01:00:00-02:00[America/Sao_Paulo]");
assert.sameValue(`${ rounded }`, "2000-04-02T03:00:00-07:00[Custom/Spring_Fall]");
assert.sameValue(rounded.epochNanoseconds - almostSkipped.epochNanoseconds, 1n);

@ -4,6 +4,7 @@
/*---
esid: sec-temporal-zoneddatetime-objects
description: Temporal.ZonedDateTime.prototype.toString()
includes: [temporalHelpers.js]
features: [Temporal]
---*/
@ -62,11 +63,12 @@ assert.sameValue(zdt.toString({
}), "1976-11-18T15:23:00");
// rounding up to a nonexistent wall-clock time
var zdt5 = Temporal.ZonedDateTime.from("2018-11-03T23:59:59.999999999-03:00[America/Sao_Paulo]");
var dst = TemporalHelpers.springForwardFallBackTimeZone();
var zdt5 = Temporal.PlainDateTime.from("2000-04-02T01:59:59.999999999").toZonedDateTime(dst);
var roundedString = zdt5.toString({
fractionalSecondDigits: 8,
roundingMode: "halfExpand"
});
assert.sameValue(roundedString, "2018-11-04T01:00:00.00000000-02:00[America/Sao_Paulo]");
var zdt6 = Temporal.ZonedDateTime.from(roundedString);
assert.sameValue(roundedString, "2000-04-02T03:00:00.00000000-07:00[Custom/Spring_Fall]");
var zdt6 = Temporal.Instant.from(roundedString);
assert.sameValue(zdt6.epochNanoseconds - zdt5.epochNanoseconds, 1n);

@ -4,6 +4,7 @@
/*---
esid: sec-temporal-zoneddatetime-objects
description: Temporal.ZonedDateTime.prototype.with()
includes: [temporalHelpers.js]
features: [Temporal]
---*/
@ -52,22 +53,23 @@ assert.sameValue(`${ zdt.with({
}) }`, "1976-05-18T15:23:15.123456789+00:00[UTC]");
// Overflow options
// constrain
// constrain
var overflow = "constrain";
assert.sameValue(`${ zdt.with({ month: 29 }, { overflow }) }`, "1976-12-18T15:23:30.123456789+00:00[UTC]");
assert.sameValue(`${ zdt.with({ day: 31 }, { overflow }) }`, "1976-11-30T15:23:30.123456789+00:00[UTC]");
assert.sameValue(`${ zdt.with({ hour: 29 }, { overflow }) }`, "1976-11-18T23:23:30.123456789+00:00[UTC]");
assert.sameValue(`${ zdt.with({ nanosecond: 9000 }, { overflow }) }`, "1976-11-18T15:23:30.123456999+00:00[UTC]");
// reject
// reject
var overflow = "reject";
assert.throws(RangeError, () => zdt.with({ month: 29 }, { overflow }));
assert.throws(RangeError, () => zdt.with({ day: 31 }, { overflow }));
assert.throws(RangeError, () => zdt.with({ hour: 29 }, { overflow }));
assert.throws(RangeError, () => zdt.with({ nanosecond: 9000 }, { overflow }));
var dstStartDay = Temporal.ZonedDateTime.from("2019-03-10T12:00:01-02:30[America/St_Johns]");
var dstEndDay = Temporal.ZonedDateTime.from("2019-11-03T12:00:01-03:30[America/St_Johns]");
var dst = TemporalHelpers.springForwardFallBackTimeZone();
var dstStartDay = Temporal.PlainDateTime.from("2000-04-02T12:00:01").toZonedDateTime(dst);
var dstEndDay = Temporal.PlainDateTime.from("2000-10-29T12:00:01").toZonedDateTime(dst);
var oneThirty = {
hour: 1,
minute: 30
@ -77,45 +79,45 @@ hour: 2,
minute: 30
};
// Disambiguation options
// Disambiguation options
var offset = "ignore";
// compatible, skipped wall time
// compatible, skipped wall time
assert.sameValue(`${ dstStartDay.with(twoThirty, {
offset,
disambiguation: "compatible"
}) }`, "2019-03-10T03:30:01-02:30[America/St_Johns]");
}) }`, "2000-04-02T03:30:01-07:00[Custom/Spring_Fall]");
// earlier, skipped wall time
// earlier, skipped wall time
assert.sameValue(`${ dstStartDay.with(twoThirty, {
offset,
disambiguation: "earlier"
}) }`, "2019-03-10T01:30:01-03:30[America/St_Johns]");
}) }`, "2000-04-02T01:30:01-08:00[Custom/Spring_Fall]");
// later, skipped wall time
// later, skipped wall time
assert.sameValue(`${ dstStartDay.with(twoThirty, {
offset,
disambiguation: "later"
}) }`, "2019-03-10T03:30:01-02:30[America/St_Johns]");
}) }`, "2000-04-02T03:30:01-07:00[Custom/Spring_Fall]");
// compatible, repeated wall time
// compatible, repeated wall time
assert.sameValue(`${ dstEndDay.with(oneThirty, {
offset,
disambiguation: "compatible"
}) }`, "2019-11-03T01:30:01-02:30[America/St_Johns]");
}) }`, "2000-10-29T01:30:01-07:00[Custom/Spring_Fall]");
// earlier, repeated wall time
// earlier, repeated wall time
assert.sameValue(`${ dstEndDay.with(oneThirty, {
offset,
disambiguation: "earlier"
}) }`, "2019-11-03T01:30:01-02:30[America/St_Johns]");
}) }`, "2000-10-29T01:30:01-07:00[Custom/Spring_Fall]");
// later, repeated wall time
// later, repeated wall time
assert.sameValue(`${ dstEndDay.with(oneThirty, {
offset,
disambiguation: "later"
}) }`, "2019-11-03T01:30:01-03:30[America/St_Johns]");
}) }`, "2000-10-29T01:30:01-08:00[Custom/Spring_Fall]");
// reject
// reject
assert.throws(RangeError, () => dstStartDay.with(twoThirty, {
offset,
disambiguation: "reject"
@ -125,7 +127,7 @@ assert.throws(RangeError, () => dstEndDay.with(oneThirty, {
disambiguation: "reject"
}));
// compatible is the default
// compatible is the default
assert.sameValue(`${ dstStartDay.with(twoThirty, { offset }) }`, `${ dstStartDay.with(twoThirty, {
offset,
disambiguation: "compatible"
@ -135,92 +137,92 @@ assert.sameValue(`${ dstEndDay.with(twoThirty, { offset }) }`, `${ dstEndDay.wit
disambiguation: "compatible"
}) }`);
// invalid disambiguation
// invalid disambiguation
[
"",
"EARLIER",
"balance"
].forEach(disambiguation => assert.throws(RangeError, () => zdt.with({ day: 5 }, { disambiguation })));
// Offset options
// Offset options
var bogus = {
...twoThirty,
offset: "+23:59"
};
// use, with bogus offset, changes to the exact time with the offset
// use, with bogus offset, changes to the exact time with the offset
var preserveExact = dstStartDay.with(bogus, { offset: "use" });
assert.sameValue(`${ preserveExact }`, "2019-03-08T23:01:01-03:30[America/St_Johns]");
assert.sameValue(preserveExact.epochNanoseconds, Temporal.Instant.from("2019-03-10T02:30:01+23:59").epochNanoseconds);
assert.sameValue(`${ preserveExact }`, "2000-03-31T18:31:01-08:00[Custom/Spring_Fall]");
assert.sameValue(preserveExact.epochNanoseconds, Temporal.Instant.from("2000-04-02T02:30:01+23:59").epochNanoseconds);
// ignore, with bogus offset, defers to disambiguation option
// ignore, with bogus offset, defers to disambiguation option
var offset = "ignore";
assert.sameValue(`${ dstStartDay.with(bogus, {
offset,
disambiguation: "earlier"
}) }`, "2019-03-10T01:30:01-03:30[America/St_Johns]");
}) }`, "2000-04-02T01:30:01-08:00[Custom/Spring_Fall]");
assert.sameValue(`${ dstStartDay.with(bogus, {
offset,
disambiguation: "later"
}) }`, "2019-03-10T03:30:01-02:30[America/St_Johns]");
}) }`, "2000-04-02T03:30:01-07:00[Custom/Spring_Fall]");
// prefer, with bogus offset, defers to disambiguation option
// prefer, with bogus offset, defers to disambiguation option
var offset = "prefer";
assert.sameValue(`${ dstStartDay.with(bogus, {
offset,
disambiguation: "earlier"
}) }`, "2019-03-10T01:30:01-03:30[America/St_Johns]");
}) }`, "2000-04-02T01:30:01-08:00[Custom/Spring_Fall]");
assert.sameValue(`${ dstStartDay.with(bogus, {
offset,
disambiguation: "later"
}) }`, "2019-03-10T03:30:01-02:30[America/St_Johns]");
}) }`, "2000-04-02T03:30:01-07:00[Custom/Spring_Fall]");
// reject, with bogus offset, throws
// reject, with bogus offset, throws
assert.throws(RangeError, () => dstStartDay.with({
...twoThirty,
offset: "+23:59"
}, { offset: "reject" }));
var doubleTime = Temporal.ZonedDateTime.from("2019-11-03T01:30:01-03:30[America/St_Johns]");
// use changes to the exact time with the offset
var preserveExact = doubleTime.with({ offset: "-02:30" }, { offset: "use" });
assert.sameValue(preserveExact.offset, "-02:30");
assert.sameValue(preserveExact.epochNanoseconds, Temporal.Instant.from("2019-11-03T01:30:01-02:30").epochNanoseconds);
var doubleTime = new Temporal.ZonedDateTime(972811801_000_000_000n, dst);
// use changes to the exact time with the offset
var preserveExact = doubleTime.with({ offset: "-07:00" }, { offset: "use" });
assert.sameValue(preserveExact.offset, "-07:00");
assert.sameValue(preserveExact.epochNanoseconds, Temporal.Instant.from("2000-10-29T01:30:01-07:00").epochNanoseconds);
// ignore defers to disambiguation option
// ignore defers to disambiguation option
var offset = "ignore";
assert.sameValue(doubleTime.with({ offset: "-02:30" }, {
assert.sameValue(doubleTime.with({ offset: "-07:00" }, {
offset,
disambiguation: "earlier"
}).offset, "-02:30");
assert.sameValue(doubleTime.with({ offset: "-02:30" }, {
}).offset, "-07:00");
assert.sameValue(doubleTime.with({ offset: "-07:00" }, {
offset,
disambiguation: "later"
}).offset, "-03:30");
}).offset, "-08:00");
// prefer adjusts offset of repeated clock time
assert.sameValue(doubleTime.with({ offset: "-02:30" }, { offset: "prefer" }).offset, "-02:30");
// prefer adjusts offset of repeated clock time
assert.sameValue(doubleTime.with({ offset: "-07:00" }, { offset: "prefer" }).offset, "-07:00");
// reject adjusts offset of repeated clock time
assert.sameValue(doubleTime.with({ offset: "-02:30" }, { offset: "reject" }).offset, "-02:30");
// reject adjusts offset of repeated clock time
assert.sameValue(doubleTime.with({ offset: "-07:00" }, { offset: "reject" }).offset, "-07:00");
// use does not cause the offset to change when adjusting repeated clock time
assert.sameValue(doubleTime.with({ minute: 31 }, { offset: "use" }).offset, "-03:30");
// use does not cause the offset to change when adjusting repeated clock time
assert.sameValue(doubleTime.with({ minute: 31 }, { offset: "use" }).offset, "-08:00");
// ignore may cause the offset to change when adjusting repeated clock time
assert.sameValue(doubleTime.with({ minute: 31 }, { offset: "ignore" }).offset, "-02:30");
// ignore may cause the offset to change when adjusting repeated clock time
assert.sameValue(doubleTime.with({ minute: 31 }, { offset: "ignore" }).offset, "-07:00");
// prefer does not cause the offset to change when adjusting repeated clock time
assert.sameValue(doubleTime.with({ minute: 31 }, { offset: "prefer" }).offset, "-03:30");
// prefer does not cause the offset to change when adjusting repeated clock time
assert.sameValue(doubleTime.with({ minute: 31 }, { offset: "prefer" }).offset, "-08:00");
// reject does not cause the offset to change when adjusting repeated clock time
assert.sameValue(doubleTime.with({ minute: 31 }, { offset: "reject" }).offset, "-03:30");
// reject does not cause the offset to change when adjusting repeated clock time
assert.sameValue(doubleTime.with({ minute: 31 }, { offset: "reject" }).offset, "-08:00");
// prefer is the default
// prefer is the default
assert.sameValue(`${ dstStartDay.with(twoThirty) }`, `${ dstStartDay.with(twoThirty, { offset: "prefer" }) }`);
assert.sameValue(`${ dstEndDay.with(twoThirty) }`, `${ dstEndDay.with(twoThirty, { offset: "prefer" }) }`);
assert.sameValue(`${ doubleTime.with({ minute: 31 }) }`, `${ doubleTime.with({ minute: 31 }, { offset: "prefer" }) }`);
// invalid offset
// invalid offset
[
"",
"PREFER",

@ -4,33 +4,39 @@
/*---
esid: sec-temporal-zoneddatetime-objects
description: .withPlainDate manipulation
includes: [temporalHelpers.js]
features: [Temporal]
---*/
var zdt = Temporal.ZonedDateTime.from("1995-12-07T03:24:30[America/Los_Angeles]");
var dst = TemporalHelpers.springForwardFallBackTimeZone();
var zdt = Temporal.PlainDateTime.from("1995-12-07T03:24:30").toZonedDateTime(dst);
// withPlainDate({ year: 2000, month: 6, day: 1 }) works
// and keeps wall time constant despite the UTC offset change
assert.sameValue(`${ zdt.withPlainDate({
year: 2000,
month: 6,
day: 1
}) }`, "2000-06-01T03:24:30-07:00[America/Los_Angeles]");
}) }`, "2000-06-01T03:24:30-07:00[Custom/Spring_Fall]");
// withPlainDate(plainDate) works
var date = Temporal.PlainDate.from("2020-01-23");
assert.sameValue(`${ zdt.withPlainDate(date) }`, "2020-01-23T03:24:30-08:00[America/Los_Angeles]");
assert.sameValue(`${ zdt.withPlainDate(date) }`, "2020-01-23T03:24:30-08:00[Custom/Spring_Fall]");
// withPlainDate('2018-09-15') works
assert.sameValue(`${ zdt.withPlainDate("2018-09-15") }`, "2018-09-15T03:24:30-07:00[America/Los_Angeles]");
assert.sameValue(`${ zdt.withPlainDate("2018-09-15") }`, "2018-09-15T03:24:30-08:00[Custom/Spring_Fall]");
// result contains a non-ISO calendar if present in the input
assert.sameValue(`${ zdt.withCalendar("japanese").withPlainDate("2008-09-06") }`, "2008-09-06T03:24:30-07:00[America/Los_Angeles][u-ca=japanese]");
var fakeJapanese = { toString() { return "japanese"; }};
assert.sameValue(`${ zdt.withCalendar(fakeJapanese).withPlainDate("2008-09-06") }`, "2008-09-06T03:24:30-08:00[Custom/Spring_Fall][u-ca=japanese]");
// calendar is unchanged if input has ISO calendar
assert.sameValue(`${ zdt.withPlainDate("2008-09-06[u-ca=japanese]") }`, "2008-09-06T03:24:30-07:00[America/Los_Angeles][u-ca=japanese]");
var date = new Temporal.PlainDate(2008, 9, 6, fakeJapanese);
assert.sameValue(`${ zdt.withPlainDate(date) }`, "2008-09-06T03:24:30-08:00[Custom/Spring_Fall][u-ca=japanese]");
// throws if both `this` and `other` have a non-ISO calendar
assert.throws(RangeError, () => zdt.withCalendar("gregory").withPlainDate("2008-09-06-07:00[America/Los_Angeles][u-ca=japanese]"));
var fakeGregorian = { toString() { return "gregory"; }};
assert.throws(RangeError, () => zdt.withCalendar(fakeGregorian).withPlainDate(date));
// object must contain at least one correctly-spelled property
assert.throws(TypeError, () => zdt.withPlainDate({}));
@ -42,4 +48,4 @@ assert.sameValue(`${ zdt.withPlainDate({
month: 6,
day: 1,
months: 123
}) }`, "2000-06-01T03:24:30-07:00[America/Los_Angeles]");
}) }`, "2000-06-01T03:24:30-07:00[Custom/Spring_Fall]");