Temporal: Fast-path AddDaysToZonedDateTime in AddZonedDateTime

This commit is contained in:
Philip Chimento 2023-03-08 17:34:23 -08:00 committed by Philip Chimento
parent 8040379076
commit b5a5b283a3
7 changed files with 46 additions and 57 deletions

View File

@ -266,21 +266,6 @@ const expectedOpsForZonedRelativeTo = expected.concat([
"call options.relativeTo.timeZone.getOffsetNanosecondsFor",
]);
const expectedOpsForZonedCalendarCompare = [
"get options.relativeTo.timeZone.getOffsetNanosecondsFor",
"call options.relativeTo.timeZone.getOffsetNanosecondsFor",
// AddZonedDateTime on first argument
"get options.relativeTo.calendar.dateAdd",
"call options.relativeTo.calendar.dateAdd",
"get options.relativeTo.timeZone.getPossibleInstantsFor",
"call options.relativeTo.timeZone.getPossibleInstantsFor",
// AddZonedDateTime on second argument
"get options.relativeTo.calendar.dateAdd",
"call options.relativeTo.calendar.dateAdd",
"get options.relativeTo.timeZone.getPossibleInstantsFor",
"call options.relativeTo.timeZone.getPossibleInstantsFor",
];
const zonedRelativeTo = TemporalHelpers.propertyBagObserver(actual, {
year: 2001,
month: 5,
@ -305,7 +290,16 @@ Temporal.Duration.compare(
);
assert.compareArray(
actual,
expectedOpsForZonedRelativeTo.concat(expectedOpsForZonedCalendarCompare),
expectedOpsForZonedRelativeTo.concat([
"get options.relativeTo.timeZone.getOffsetNanosecondsFor",
"call options.relativeTo.timeZone.getOffsetNanosecondsFor",
// AddDaysToZonedDateTime on first argument
"get options.relativeTo.timeZone.getPossibleInstantsFor",
"call options.relativeTo.timeZone.getPossibleInstantsFor",
// AddDaysToZonedDateTime on second argument
"get options.relativeTo.timeZone.getPossibleInstantsFor",
"call options.relativeTo.timeZone.getPossibleInstantsFor",
]),
"order of operations with ZonedDateTime relativeTo and no calendar units except days"
);
actual.splice(0); // clear
@ -331,7 +325,20 @@ Temporal.Duration.compare(
);
assert.compareArray(
actual,
expectedOpsForZonedRelativeTo.concat(expectedOpsForZonedCalendarCompare),
expectedOpsForZonedRelativeTo.concat([
"get options.relativeTo.timeZone.getOffsetNanosecondsFor",
"call options.relativeTo.timeZone.getOffsetNanosecondsFor",
// AddZonedDateTime on first argument
"get options.relativeTo.calendar.dateAdd",
"call options.relativeTo.calendar.dateAdd",
"get options.relativeTo.timeZone.getPossibleInstantsFor",
"call options.relativeTo.timeZone.getPossibleInstantsFor",
// AddZonedDateTime on second argument
"get options.relativeTo.calendar.dateAdd",
"call options.relativeTo.calendar.dateAdd",
"get options.relativeTo.timeZone.getPossibleInstantsFor",
"call options.relativeTo.timeZone.getPossibleInstantsFor",
]),
"order of operations with ZonedDateTime relativeTo and calendar units"
);
actual.splice(0); // clear

View File

@ -40,11 +40,12 @@ features: [Temporal]
var one = Temporal.Duration.from({
days: Number.MAX_SAFE_INTEGER,
weeks: 3,
years: 1,
});
var two = Temporal.Duration.from({
days: Number.MAX_SAFE_INTEGER + 3,
weeks: 0,
years: 1,
});
var cal = new class extends Temporal.Calendar {

View File

@ -18,15 +18,14 @@ const relativeTo = new Temporal.ZonedDateTime(0n, timeZone, calendar);
// The calls come from these paths:
// Duration.round() ->
// RoundDuration ->
// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd()
// BalanceDuration ->
// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd()
// MoveRelativeZonedDateTime -> AddZonedDateTime -> calendar.dateAdd()
// MoveRelativeDate -> calendar.dateAdd()
// BalanceDurationRelative ->
// MoveRelativeDate -> calendar.dateAdd() (2x)
// calendar.dateAdd()
const instance1 = new Temporal.Duration(1, 1, 1, 1, 1);
instance1.round({ smallestUnit: "days", relativeTo });
instance1.round({ smallestUnit: "weeks", relativeTo });
assert.sameValue(calendar.dateAddCallCount, 5, "rounding with calendar smallestUnit");
// Rounding with a non-default largestUnit to cover the path in
@ -40,7 +39,7 @@ assert.sameValue(calendar.dateAddCallCount, 5, "rounding with calendar smallestU
// MoveRelativeDate -> calendar.dateAdd() (5x)
// BalanceDurationRelative
// MoveRelativeDate -> calendar.dateAdd()
// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd()
// MoveRelativeZonedDateTime -> AddZonedDateTime -> calendar.dateAdd()
calendar.dateAddCallCount = 0;
@ -48,18 +47,17 @@ const instance2 = new Temporal.Duration(0, 1, 1, 1);
instance2.round({ largestUnit: "weeks", smallestUnit: "weeks", relativeTo });
assert.sameValue(calendar.dateAddCallCount, 8, "rounding with non-default largestUnit and calendar smallestUnit");
// Rounding with smallestUnit a non-calendar unit, and having the resulting time
// difference be longer than a calendar day, covering the paths that go through
// AdjustRoundedDurationDays.
// Rounding with smallestUnit days only.
// The calls come from these paths:
// Duration.round() ->
// AdjustRoundedDurationDays -> AddDuration ->
// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd()
// BalanceDuration ->
// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd()
// RoundDuration ->
// MoveRelativeZonedDateTime -> AddZonedDateTime -> calendar.dateAdd()
// BalanceDurationRelative ->
// MoveRelativeDate -> calendar.dateAdd() (2x)
// calendar.dateAdd()
calendar.dateAddCallCount = 0;
const instance3 = new Temporal.Duration(0, 0, 0, 0, 23, 59, 59, 999, 999, 999);
instance3.round({ largestUnit: "days", smallestUnit: "hours", roundingMode: "ceil", relativeTo });
assert.sameValue(calendar.dateAddCallCount, 2, "rounding with time difference exceeding calendar day");
const instance3 = new Temporal.Duration(1, 1, 1, 1, 1);
instance3.round({ smallestUnit: "days", relativeTo });
assert.sameValue(calendar.dateAddCallCount, 4, "rounding with days smallestUnit");

View File

@ -21,12 +21,10 @@ const relativeTo = new Temporal.ZonedDateTime(0n, timeZone, calendar);
// UnbalanceDurationRelative -> MoveRelativeDate -> calendar.dateAdd() (3x)
// BalanceDuration ->
// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd()
// RoundDuration ->
// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd()
const instance1 = new Temporal.Duration(1, 1, 1, 1, 1);
instance1.total({ unit: "days", relativeTo });
assert.sameValue(calendar.dateAddCallCount, 5, "converting larger calendar units down");
assert.sameValue(calendar.dateAddCallCount, 3, "converting larger calendar units down");
// Total of a calendar unit where smaller calendar units have to be converted
// up, to cover the path that goes through MoveRelativeZonedDateTime
@ -36,11 +34,10 @@ assert.sameValue(calendar.dateAddCallCount, 5, "converting larger calendar units
// BalanceDuration ->
// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd()
// RoundDuration ->
// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd()
// MoveRelativeDate -> calendar.dateAdd()
calendar.dateAddCallCount = 0;
const instance2 = new Temporal.Duration(0, 0, 1, 1);
instance2.total({ unit: "weeks", relativeTo });
assert.sameValue(calendar.dateAddCallCount, 4, "converting smaller calendar units up");
assert.sameValue(calendar.dateAddCallCount, 3, "converting smaller calendar units up");

View File

@ -277,12 +277,10 @@ const expectedOpsForYearRoundingZoned = expectedOpsForZonedRelativeTo.concat([
"call options.relativeTo.timeZone.getPossibleInstantsFor",
], [
// code path through RoundDuration that rounds to the nearest year:
// MoveRelativeZonedDateTime → AddZonedDateTime
"get options.relativeTo.timeZone.getOffsetNanosecondsFor", // 5. GetPlainDateTimeFor
// MoveRelativeZonedDateTime → AddDaysToZonedDateTime
"get options.relativeTo.timeZone.getOffsetNanosecondsFor",
"call options.relativeTo.timeZone.getOffsetNanosecondsFor",
"get options.relativeTo.calendar.dateAdd", // 8.
"call options.relativeTo.calendar.dateAdd",
"get options.relativeTo.timeZone.getPossibleInstantsFor", // 10. GetInstantFor
"get options.relativeTo.timeZone.getPossibleInstantsFor",
"call options.relativeTo.timeZone.getPossibleInstantsFor",
"get options.relativeTo.calendar.dateAdd", // 9.b
"call options.relativeTo.calendar.dateAdd", // 9.c

View File

@ -44,10 +44,10 @@ assert.sameValue(calendar.dateAddCallCount, 3, "rounding difference with calenda
// test in until() only happens in one direction.)
// The calls come from this path:
// ZonedDateTime.since() -> AdjustRoundedDurationDays -> AddZonedDateTime ->
// BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (3x)
// BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() (2x)
calendar.dateAddCallCount = 0;
const later2 = new Temporal.ZonedDateTime(86_399_999_999_999n, timeZone, calendar);
later2.since(earlier, { largestUnit: "days", smallestUnit: "hours", roundingMode: "ceil" });
assert.sameValue(calendar.dateAddCallCount, 3, "rounding difference with non-calendar smallestUnit and time difference longer than a calendar day");
assert.sameValue(calendar.dateAddCallCount, 2, "rounding difference with non-calendar smallestUnit and time difference longer than a calendar day");

View File

@ -36,15 +36,3 @@ calendar.dateAddCallCount = 0;
earlier.until(later1, { smallestUnit: "weeks" });
assert.sameValue(calendar.dateAddCallCount, 3, "rounding difference with calendar smallestUnit");
// Difference with rounding, with smallestUnit a non-calendar unit, and having
// the resulting time difference be longer than a calendar day, covering the
// paths that go through AdjustRoundedDurationDays.
// The call comes from this path:
// ZonedDateTime.until() -> AdjustRoundedDurationDays -> AddZonedDateTime ->
// BuiltinTimeZoneGetInstantFor -> calendar.dateAdd()
calendar.dateAddCallCount = 0;
const later2 = new Temporal.ZonedDateTime(86_399_999_999_999n, timeZone, calendar);
earlier.until(later2, { largestUnit: "days", smallestUnit: "hours", roundingMode: "ceil" });
assert.sameValue(calendar.dateAddCallCount, 1, "rounding difference with non-calendar smallestUnit and time difference longer than a calendar day");