Skip to content

Commit

Permalink
Temporal: Adjust tests for Duration rounding fix
Browse files Browse the repository at this point in the history
A MoveRelativeZonedDateTime step was missing, causing incorrect results.
See tc39/proposal-temporal#2742
  • Loading branch information
ptomato authored and Ms2ger committed May 14, 2024
1 parent 9b4c657 commit 6c6c72b
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const relativeTo = new Temporal.ZonedDateTime(0n, timeZone, calendar);

const instance1 = new Temporal.Duration(1, 1, 1, 1, 1);
instance1.round({ smallestUnit: "weeks", relativeTo });
assert.sameValue(calendar.dateAddCallCount, 3, "rounding with calendar smallestUnit");
assert.sameValue(calendar.dateAddCallCount, 4, "rounding with calendar smallestUnit");

// Rounding with a non-default largestUnit to cover the path in
// UnbalanceDurationRelative where larger units are converted into smaller
Expand All @@ -41,7 +41,7 @@ calendar.dateAddCallCount = 0;

const instance2 = new Temporal.Duration(0, 1, 1, 1);
instance2.round({ largestUnit: "weeks", smallestUnit: "weeks", relativeTo });
assert.sameValue(calendar.dateAddCallCount, 5, "rounding with non-default largestUnit and calendar smallestUnit");
assert.sameValue(calendar.dateAddCallCount, 6, "rounding with non-default largestUnit and calendar smallestUnit");

// Rounding with smallestUnit days only.
// The calls come from these paths:
Expand All @@ -54,4 +54,4 @@ calendar.dateAddCallCount = 0;

const instance3 = new Temporal.Duration(1, 1, 1, 1, 1);
instance3.round({ smallestUnit: "days", relativeTo });
assert.sameValue(calendar.dateAddCallCount, 2, "rounding with days smallestUnit");
assert.sameValue(calendar.dateAddCallCount, 3, "rounding with days smallestUnit");
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// 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.duration.prototype.round
description: >
Balancing the resulting duration takes the time zone's UTC offset shifts
into account
includes: [temporalHelpers.js]
features: [Temporal]
---*/

const timeZone = TemporalHelpers.springForwardFallBackTimeZone();

// Based on a test case by Adam Shaw
{
const duration = new Temporal.Duration(1, 0, 0, 0, 24);
const relativeTo = new Temporal.ZonedDateTime(
941184000_000_000_000n /* = 1999-10-29T08Z */,
timeZone); /* = 1999-10-29T00-08 in local time */

const result = duration.round({ largestUnit: "years", relativeTo });
TemporalHelpers.assertDuration(result, 1, 0, 0, 0, 24, 0, 0, 0, 0, 0,
"24 hours does not balance to 1 day in 25-hour day");
}
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,9 @@ const expectedOpsForYearRoundingZoned = expectedOpsForZonedRelativeTo.concat([
"call options.relativeTo.calendar.dateUntil", // 12.n
"call options.relativeTo.calendar.dateAdd", // 12.r MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 12.x MoveRelativeDate
// MoveRelativeZonedDateTime → AddZonedDateTime
"call options.relativeTo.calendar.dateAdd",
"call options.relativeTo.timeZone.getPossibleInstantsFor",
// BalanceDateDurationRelative
"call options.relativeTo.calendar.dateAdd", // 9.c
"call options.relativeTo.calendar.dateUntil", // 9.d
Expand All @@ -420,6 +423,9 @@ const expectedOpsForUnbalanceRoundBalance = expectedOpsForZonedRelativeTo.concat
"call options.relativeTo.timeZone.getPossibleInstantsFor", // 13. GetInstantFor
// RoundDuration
"call options.relativeTo.calendar.dateAdd", // 14.p MoveRelativeDate
// MoveRelativeZonedDateTime → AddZonedDateTime
"call options.relativeTo.calendar.dateAdd",
"call options.relativeTo.timeZone.getPossibleInstantsFor",
// BalanceDateDurationRelative
"call options.relativeTo.calendar.dateAdd", // 10.d
"call options.relativeTo.calendar.dateUntil", // 10.e
Expand All @@ -445,6 +451,9 @@ const expectedOpsForWeeksSpecialCase = expectedOpsForZonedRelativeTo.concat([
"call options.relativeTo.timeZone.getPossibleInstantsFor", // 13. GetInstantFor
// RoundDuration
"call options.relativeTo.calendar.dateAdd", // 14.p MoveRelativeDate
// MoveRelativeZonedDateTime → AddZonedDateTime
"call options.relativeTo.calendar.dateAdd",
"call options.relativeTo.timeZone.getPossibleInstantsFor",
]);
new Temporal.Duration(0, 1, 1).round(createOptionsObserver({ largestUnit: "months", smallestUnit: "weeks", relativeTo: zonedRelativeTo }));
assert.compareArray(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,4 @@ const relativeTo = { year: 2000, month: 5, day: 2, timeZone, calendar: nonBuilti
const instance = new Temporal.Duration(1, 0, 0, 0, 24);
instance.round({ largestUnit: "years", relativeTo });

assert.sameValue(timeZone.calls, 6, "getPossibleInstantsFor should have been called 6 times");
assert.sameValue(timeZone.calls, 8, "getPossibleInstantsFor should have been called 8 times");
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const expected = [
"2000-01-01T00:00:00", // called once on the input relativeTo object
"2001-02-09T00:00:00", // called once on relativeTo plus years, months, weeks, days from the receiver
"2001-02-10T00:00:00", // called once on the previous value plus the calendar days difference between that and the time part of the duration
"2001-02-01T00:00:00", // called once in the balancing step on intermediate relativeTo
];

TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// 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.duration.prototype.total
description: >
Balancing the resulting duration takes the time zone's UTC offset shifts
into account
includes: [temporalHelpers.js]
features: [Temporal]
---*/

// Based on a test case by Adam Shaw

const duration = new Temporal.Duration(1, 0, 0, 0, 24);
const timeZone = TemporalHelpers.springForwardFallBackTimeZone();
const relativeTo = new Temporal.ZonedDateTime(
941184000_000_000_000n /* = 1999-10-29T08Z */,
timeZone); /* = 1999-10-29T00-08 in local time */

const result = duration.total({ unit: "days", relativeTo });
assert.sameValue(result, 366.96, "24 hours does not balance to 1 day in 25-hour day");
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// 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.since
description: >
Balancing the resulting duration takes the time zone's UTC offset shifts
into account
includes: [temporalHelpers.js]
features: [Temporal]
---*/

const timeZone = TemporalHelpers.springForwardFallBackTimeZone();

// Based on a test case by Adam Shaw
{
const start = new Temporal.ZonedDateTime(
941184000_000_000_000n /* = 1999-10-29T08Z */,
timeZone); /* = 1999-10-29T00-08 in local time */
const end = new Temporal.ZonedDateTime(
972889200_000_000_000n /* = 2000-10-30T07Z */,
timeZone); /* = 2000-10-29T23-08 in local time */

const duration = start.since(end, { largestUnit: "years" });
TemporalHelpers.assertDuration(duration, -1, 0, 0, 0, -24, 0, 0, 0, 0, 0,
"24 hours does not balance to 1 day in 25-hour day");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// 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.until
description: >
Balancing the resulting duration takes the time zone's UTC offset shifts
into account
includes: [temporalHelpers.js]
features: [Temporal]
---*/

const timeZone = TemporalHelpers.springForwardFallBackTimeZone();

// Based on a test case by Adam Shaw
{
const start = new Temporal.ZonedDateTime(
941184000_000_000_000n /* = 1999-10-29T08Z */,
timeZone); /* = 1999-10-29T00-08 in local time */
const end = new Temporal.ZonedDateTime(
972889200_000_000_000n /* = 2000-10-30T07Z */,
timeZone); /* = 2000-10-29T23-08 in local time */

const duration = start.until(end, { largestUnit: "years" });
TemporalHelpers.assertDuration(duration, 1, 0, 0, 0, 24, 0, 0, 0, 0, 0,
"24 hours does not balance to 1 day in 25-hour day");
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ const instance = new Temporal.Duration(1, 0, 0, 0, 24);

let relativeTo = "2019-11-01T00:00[America/Vancouver]";
const result4 = instance.round({ largestUnit: "years", relativeTo });
TemporalHelpers.assertDuration(result4, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, "date-time + IANA annotation is a zoned relativeTo");
TemporalHelpers.assertDuration(result4, 1, 0, 0, 0, 24, 0, 0, 0, 0, 0, "date-time + IANA annotation is a zoned relativeTo");

relativeTo = "2019-11-01T00:00Z[America/Vancouver]";
const result5 = instance.round({ largestUnit: "years", relativeTo });
TemporalHelpers.assertDuration(result5, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, "date-time + Z + IANA annotation is a zoned relativeTo");
TemporalHelpers.assertDuration(result5, 1, 0, 0, 0, 24, 0, 0, 0, 0, 0, "date-time + Z + IANA annotation is a zoned relativeTo");

relativeTo = "2019-11-01T00:00-07:00[America/Vancouver]";
const result6 = instance.round({ largestUnit: "years", relativeTo });
TemporalHelpers.assertDuration(result6, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, "date-time + offset + IANA annotation is a zoned relativeTo");
TemporalHelpers.assertDuration(result6, 1, 0, 0, 0, 24, 0, 0, 0, 0, 0, "date-time + offset + IANA annotation is a zoned relativeTo");

relativeTo = "2019-11-01T00:00+04:15[America/Vancouver]";
assert.throws(RangeError, () => instance.round({ largestUnit: "years", relativeTo }), "date-time + offset + IANA annotation throws if wall time and exact time mismatch");

0 comments on commit 6c6c72b

Please sign in to comment.