Skip to content

Commit

Permalink
Temporal: Remove loops in RoundDuration
Browse files Browse the repository at this point in the history
  • Loading branch information
ptomato committed Nov 16, 2023
1 parent e43e20a commit bcb4091
Show file tree
Hide file tree
Showing 15 changed files with 155 additions and 164 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,15 @@ assert.sameValue(calendar.dateAddCallCount, 3, "rounding with calendar smallestU
// The calls come from these paths:
// Duration.round() ->
// UnbalanceDurationRelative -> MoveRelativeDate -> calendar.dateAdd()
// RoundDuration ->
// MoveRelativeDate -> calendar.dateAdd() (5x)
// RoundDuration -> MoveRelativeDate -> calendar.dateAdd() (2x)
// BalanceDateDurationRelative -> calendar.dateAdd()
// MoveRelativeZonedDateTime -> AddZonedDateTime -> calendar.dateAdd()

calendar.dateAddCallCount = 0;

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");
assert.sameValue(calendar.dateAddCallCount, 5, "rounding with non-default largestUnit and calendar smallestUnit");

// Rounding with smallestUnit days only.
// The calls come from these paths:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular(
}, {
years: ["year"],
months: ["month"],
weeks: ["week"],
weeks: ["week", "week"],
days: []
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ info: |
const instance = new Temporal.Duration(0, 0, 0, /* days = */ 500_000_000);
const relativeTo = new Temporal.PlainDate(2000, 1, 1);
assert.throws(RangeError, () => instance.round({relativeTo, smallestUnit: "years"}));
assert.throws(RangeError, () => instance.round({relativeTo, smallestUnit: "months"}));
assert.throws(RangeError, () => instance.round({relativeTo, smallestUnit: "weeks"}));

const negInstance = new Temporal.Duration(0, 0, 0, /* days = */ -500_000_000);
assert.throws(RangeError, () => negInstance.round({relativeTo, smallestUnit: "years"}));
assert.throws(RangeError, () => negInstance.round({relativeTo, smallestUnit: "months"}));
assert.throws(RangeError, () => negInstance.round({relativeTo, smallestUnit: "weeks"}));
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,11 @@ actual.splice(0); // clear

// code path through RoundDuration that rounds to the nearest year:
const expectedOpsForYearRounding = expectedOpsForPlainRelativeTo.concat([
"call options.relativeTo.calendar.dateAdd", // 7.e
"call options.relativeTo.calendar.dateAdd", // 7.g
"call options.relativeTo.calendar.dateUntil", // 7.o
"call options.relativeTo.calendar.dateAdd", // 7.s MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 7.y MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 12.d
"call options.relativeTo.calendar.dateAdd", // 12.f
"call options.relativeTo.calendar.dateUntil", // 12.n
"call options.relativeTo.calendar.dateAdd", // 12.r MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 12.x MoveRelativeDate
// BalanceDateDurationRelative
"call options.relativeTo.calendar.dateAdd", // 9.c
"call options.relativeTo.calendar.dateUntil", // 9.d
Expand All @@ -153,10 +153,11 @@ const expectedOpsForMonthRounding = expectedOpsForPlainRelativeTo.concat([
"call options.relativeTo.calendar.dateAdd", // 3.f
"call options.relativeTo.calendar.dateUntil", // 3.i
// RoundDuration
"call options.relativeTo.calendar.dateAdd", // 10.c
"call options.relativeTo.calendar.dateAdd", // 10.e
"call options.relativeTo.calendar.dateAdd", // 10.k MoveRelativeDate
], Array(2).fill("call options.relativeTo.calendar.dateAdd"), [ // 2× 10.n.iii MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 13.c
"call options.relativeTo.calendar.dateAdd", // 13.e
"call options.relativeTo.calendar.dateUntil", // 13.m
"call options.relativeTo.calendar.dateAdd", // 13.q MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 13.w MoveRelativeDate
// BalanceDateDurationRelative
"call options.relativeTo.calendar.dateAdd", // 10.d
"call options.relativeTo.calendar.dateUntil", // 10.e
Expand All @@ -171,8 +172,9 @@ const expectedOpsForWeekRounding = expectedOpsForPlainRelativeTo.concat([
// UnbalanceDateDurationRelative
"call options.relativeTo.calendar.dateAdd", // 4.e
// RoundDuration
"call options.relativeTo.calendar.dateAdd", // 11.d MoveRelativeDate
], Array(58).fill("call options.relativeTo.calendar.dateAdd"), [ // 58× 11.g.iii MoveRelativeDate (52 + 4 + 2)
"call options.relativeTo.calendar.dateUntil", // 14.f
"call options.relativeTo.calendar.dateAdd", // 14.j MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 14.p MoveRelativeDate
// BalanceDateDurationRelative
"call options.relativeTo.calendar.dateAdd", // 16
"call options.relativeTo.calendar.dateUntil", // 17
Expand Down Expand Up @@ -204,9 +206,9 @@ actual.splice(0); // clear
// code path through Duration.prototype.round balancing from months up to years:
const expectedOpsForMonthToYearBalancing = expectedOpsForPlainRelativeTo.concat([
// RoundDuration
"call options.relativeTo.calendar.dateAdd", // 10.c
"call options.relativeTo.calendar.dateAdd", // 10.e
"call options.relativeTo.calendar.dateAdd", // 10.k MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 13.c
"call options.relativeTo.calendar.dateAdd", // 13.e
"call options.relativeTo.calendar.dateAdd", // 13.w MoveRelativeDate
// BalanceDateDurationRelative
"call options.relativeTo.calendar.dateAdd", // 9.c
"call options.relativeTo.calendar.dateUntil", // 9.d
Expand Down Expand Up @@ -387,11 +389,11 @@ const expectedOpsForYearRoundingZoned = expectedOpsForZonedRelativeTo.concat([
"call options.relativeTo.timeZone.getPossibleInstantsFor",
// NanosecondsToDays → AddDaysToZonedDateTime
"call options.relativeTo.timeZone.getPossibleInstantsFor",
"call options.relativeTo.calendar.dateAdd", // 7.e
"call options.relativeTo.calendar.dateAdd", // 7.g
"call options.relativeTo.calendar.dateUntil", // 7.o
"call options.relativeTo.calendar.dateAdd", // 7.s MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 7.y MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 12.d
"call options.relativeTo.calendar.dateAdd", // 12.f
"call options.relativeTo.calendar.dateUntil", // 12.n
"call options.relativeTo.calendar.dateAdd", // 12.r MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 12.x MoveRelativeDate
// BalanceDateDurationRelative
"call options.relativeTo.calendar.dateAdd", // 9.c
"call options.relativeTo.calendar.dateUntil", // 9.d
Expand All @@ -417,7 +419,7 @@ const expectedOpsForUnbalanceRoundBalance = expectedOpsForZonedRelativeTo.concat
"call options.relativeTo.calendar.dateAdd",
"call options.relativeTo.timeZone.getPossibleInstantsFor", // 13. GetInstantFor
// RoundDuration
"call options.relativeTo.calendar.dateAdd", // 8.g MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 14.p MoveRelativeDate
// BalanceDateDurationRelative
"call options.relativeTo.calendar.dateAdd", // 10.d
"call options.relativeTo.calendar.dateUntil", // 10.e
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ includes: [compareArray.js, temporalHelpers.js]
features: [Temporal]
---*/

// Check the paths that go through NanosecondsToDays: only one call with
// largestUnit: "year" in RoundDuration when the unit is "year". The others all
// Check the paths that go through NanosecondsToDays: only one call in
// RoundDuration when the unit is a calendar unit. The others all
// have largestUnit: "day" so the difference is taken in ISO calendar space.

const duration = new Temporal.Duration(0, 1, 1, 1, 1, 1, 1, 1, 1, 1);
Expand All @@ -50,32 +50,10 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular(
const relativeTo = new Temporal.ZonedDateTime(0n, "UTC", calendar);
duration.total({ unit, relativeTo });
},
{
years: ["year"],
months: [],
weeks: [],
days: [],
hours: [],
minutes: [],
seconds: [],
milliseconds: [],
microseconds: [],
nanoseconds: []
}
);

// Check the path that converts years to months in UnbalanceDurationRelative.

TemporalHelpers.checkCalendarDateUntilLargestUnitSingular(
(calendar, unit) => {
const duration = new Temporal.Duration(5, 1);
const relativeTo = new Temporal.PlainDateTime(2000, 5, 2, 0, 0, 0, 0, 0, 0, calendar);
duration.total({ unit, relativeTo });
},
{
years: ["year"],
months: ["month"],
weeks: [],
weeks: ["week"],
days: [],
hours: [],
minutes: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ info: |
const instance = new Temporal.Duration(0, 0, 0, /* days = */ 500_000_000);
const relativeTo = new Temporal.PlainDate(2000, 1, 1);
assert.throws(RangeError, () => instance.total({relativeTo, unit: "years"}));
assert.throws(RangeError, () => instance.total({relativeTo, unit: "months"}));
assert.throws(RangeError, () => instance.total({relativeTo, unit: "weeks"}));

const negInstance = new Temporal.Duration(0, 0, 0, /* days = */ -500_000_000);
assert.throws(RangeError, () => negInstance.total({relativeTo, unit: "years"}));
assert.throws(RangeError, () => negInstance.total({relativeTo, unit: "months"}));
assert.throws(RangeError, () => negInstance.total({relativeTo, unit: "weeks"}));
Original file line number Diff line number Diff line change
Expand Up @@ -105,22 +105,22 @@ actual.splice(0); // clear

// code path through RoundDuration that rounds to the nearest year with minimal calendar calls:
const expectedOpsForMinimalYearRounding = expectedOpsForPlainRelativeTo.concat([
// 7.e and 7.g not called because years, months, weeks are 0
"call options.relativeTo.calendar.dateUntil", // 7.o
// 7.s not called because years, months, weeks are 0
"call options.relativeTo.calendar.dateAdd", // 7.y MoveRelativeDate
// 12.d and 12.f not called because years, months, weeks are 0
"call options.relativeTo.calendar.dateUntil", // 12.n
// 12.r not called because years, months, weeks are 0
"call options.relativeTo.calendar.dateAdd", // 12.x MoveRelativeDate
]);
instance.total(createOptionsObserver({ unit: "years", relativeTo: plainRelativeTo }));
assert.compareArray(actual, expectedOpsForMinimalYearRounding, "order of operations with years = 0 and unit = years");
actual.splice(0); // clear

// code path through RoundDuration that rounds to the nearest year:
const expectedOpsForYearRounding = expectedOpsForPlainRelativeTo.concat([
"call options.relativeTo.calendar.dateAdd", // 7.d
"call options.relativeTo.calendar.dateAdd", // 7.f
"call options.relativeTo.calendar.dateUntil", // 7.n
"call options.relativeTo.calendar.dateAdd", // 7.s
"call options.relativeTo.calendar.dateAdd", // 7.x MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 12.d
"call options.relativeTo.calendar.dateAdd", // 12.f
"call options.relativeTo.calendar.dateUntil", // 12.n
"call options.relativeTo.calendar.dateAdd", // 12.r MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 12.x MoveRelativeDate
]);
const instanceYears = new Temporal.Duration(1, 12, 0, 0, /* hours = */ 2400);
instanceYears.total(createOptionsObserver({ unit: "years", relativeTo: plainRelativeTo }));
Expand All @@ -133,10 +133,12 @@ const expectedOpsForMonthRounding = expectedOpsForPlainRelativeTo.concat([
"call options.relativeTo.calendar.dateAdd", // 3.f
"call options.relativeTo.calendar.dateUntil", // 3.i
// RoundDuration
"call options.relativeTo.calendar.dateAdd", // 10.c
"call options.relativeTo.calendar.dateAdd", // 10.e
"call options.relativeTo.calendar.dateAdd", // 10.k MoveRelativeDate
], Array(2).fill("call options.relativeTo.calendar.dateAdd")); // 2× 10.n.iii MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 13.c
"call options.relativeTo.calendar.dateAdd", // 13.e
"call options.relativeTo.calendar.dateUntil", // 13.m
"call options.relativeTo.calendar.dateAdd", // 13.q MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 13.w MoveRelativeDate
]);
const instance2 = new Temporal.Duration(1, 0, 0, 62);
instance2.total(createOptionsObserver({ unit: "months", relativeTo: plainRelativeTo }));
assert.compareArray(actual, expectedOpsForMonthRounding, "order of operations with unit = months");
Expand All @@ -147,8 +149,10 @@ const expectedOpsForWeekRounding = expectedOpsForPlainRelativeTo.concat([
// UnbalanceDateDurationRelative
"call options.relativeTo.calendar.dateAdd", // 4.e
// RoundDuration
"call options.relativeTo.calendar.dateAdd", // 11.d MoveRelativeDate
], Array(58).fill("call options.relativeTo.calendar.dateAdd")); // 58× 11.g.iii MoveRelativeDate (52 + 4 + 2)
"call options.relativeTo.calendar.dateUntil", // 14.f
"call options.relativeTo.calendar.dateAdd", // 14.j MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 14.p MoveRelativeDate
]);
const instance3 = new Temporal.Duration(1, 1, 0, 15);
instance3.total(createOptionsObserver({ unit: "weeks", relativeTo: plainRelativeTo }));
assert.compareArray(actual, expectedOpsForWeekRounding, "order of operations with unit = weeks");
Expand Down Expand Up @@ -282,10 +286,10 @@ const expectedOpsForMinimalYearRoundingZoned = expectedOpsForZonedRelativeTo.con
// code path through RoundDuration that rounds to the nearest year:
// MoveRelativeZonedDateTime → AddDaysToZonedDateTime
"call options.relativeTo.timeZone.getPossibleInstantsFor",
// 7.e and 7.g not called because years, months, weeks are 0
"call options.relativeTo.calendar.dateUntil", // 7.o
// 7.s not called because years, months, weeks are 0
"call options.relativeTo.calendar.dateAdd", // 7.y MoveRelativeDate
// 12.d and 12.f not called because years, months, weeks are 0
"call options.relativeTo.calendar.dateUntil", // 12.n
// 12.r not called because years, months, weeks are 0
"call options.relativeTo.calendar.dateAdd", // 12.x MoveRelativeDate
]);
instance.total(createOptionsObserver({ unit: "years", relativeTo: zonedRelativeTo }));
assert.compareArray(
Expand Down Expand Up @@ -316,11 +320,11 @@ const expectedOpsForYearRoundingZoned = expectedOpsForZonedRelativeTo.concat([
"call options.relativeTo.calendar.dateAdd",
"call options.relativeTo.timeZone.getPossibleInstantsFor",
// RoundDuration
"call options.relativeTo.calendar.dateAdd", // 7.e
"call options.relativeTo.calendar.dateAdd", // 7.g
"call options.relativeTo.calendar.dateUntil", // 7.o
"call options.relativeTo.calendar.dateAdd", // 7.s MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 7.y MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 12.d
"call options.relativeTo.calendar.dateAdd", // 12.f
"call options.relativeTo.calendar.dateUntil", // 12.n
"call options.relativeTo.calendar.dateAdd", // 12.r MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 12.x MoveRelativeDate
]);
instanceYears.total(createOptionsObserver({ unit: "years", relativeTo: zonedRelativeTo }));
assert.compareArray(
Expand All @@ -345,9 +349,10 @@ const expectedOpsForUnbalanceRound = expectedOpsForZonedRelativeTo.concat([
"call options.relativeTo.calendar.dateAdd",
"call options.relativeTo.timeZone.getPossibleInstantsFor", // 13. GetInstantFor
// RoundDuration
"call options.relativeTo.calendar.dateAdd", // 7.f
"call options.relativeTo.calendar.dateAdd", // 7.h
"call options.relativeTo.calendar.dateAdd", // 7.n MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 13.c
"call options.relativeTo.calendar.dateAdd", // 13.e
"call options.relativeTo.calendar.dateUntil", // 13.m
"call options.relativeTo.calendar.dateAdd", // 13.w MoveRelativeDate
]);
new Temporal.Duration(0, 1, 1).total(createOptionsObserver({ unit: "months", relativeTo: zonedRelativeTo }));
assert.compareArray(
Expand Down Expand Up @@ -375,8 +380,9 @@ const expectedOpsForBalanceRound = expectedOpsForZonedRelativeTo.concat([
// RoundDuration → MoveRelativeZonedDateTime → AddZonedDateTime
"call options.relativeTo.timeZone.getPossibleInstantsFor", // 10. GetInstantFor
// RoundDuration
"call options.relativeTo.calendar.dateAdd", // 10.f
"call options.relativeTo.calendar.dateAdd", // 10.i.iii
"call options.relativeTo.calendar.dateUntil", // 14.f
"call options.relativeTo.calendar.dateAdd", // 14.j MoveRelativeDate
"call options.relativeTo.calendar.dateAdd", // 14.p MoveRelativeDate
]);
new Temporal.Duration(0, 0, 0, 1, 240).total(createOptionsObserver({ unit: "weeks", relativeTo: zonedRelativeTo }));
assert.compareArray(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,11 @@ const expectedOpsForYearRounding = expected.concat([
// CalendarDateUntil
"call this.calendar.dateUntil",
// RoundDuration
"call this.calendar.dateAdd", // 7.e
"call this.calendar.dateAdd", // 7.g
"call this.calendar.dateUntil", // 7.o
"call this.calendar.dateAdd", // 7.y MoveRelativeDate
// (7.s not called because other units can't add up to >1 year at this point)
"call this.calendar.dateAdd", // 12.d
"call this.calendar.dateAdd", // 12.f
"call this.calendar.dateUntil", // 12.n
"call this.calendar.dateAdd", // 12.x MoveRelativeDate
// (12.r not called because other units can't add up to >1 year at this point)
// BalanceDateDurationRelative
"call this.calendar.dateAdd", // 9.c
"call this.calendar.dateUntil" // 9.d
Expand All @@ -161,10 +161,10 @@ const expectedOpsForYearRoundingSameMonth = expected.concat([
// CalendarDateUntil
"call this.calendar.dateUntil",
// RoundDuration
"call this.calendar.dateAdd", // 7.e
"call this.calendar.dateAdd", // 7.g
"call this.calendar.dateAdd", // 7.y MoveRelativeDate
// (7.o not called because months and weeks == 0)
"call this.calendar.dateAdd", // 12.d
"call this.calendar.dateAdd", // 12.f
"call this.calendar.dateAdd", // 12.x MoveRelativeDate
// (12.n not called because months and weeks == 0)
// BalanceDateDurationRelative
"call this.calendar.dateAdd", // 9.c
"call this.calendar.dateUntil" // 9.d
Expand All @@ -181,10 +181,9 @@ const expectedOpsForMonthRounding = expected.concat([
// CalendarDateUntil
"call this.calendar.dateUntil",
// RoundDuration
"call this.calendar.dateAdd", // 10.c
"call this.calendar.dateAdd", // 10.e
"call this.calendar.dateAdd", // 10.k MoveRelativeDate
// (10.n.iii MoveRelativeDate not called because weeks == 0)
"call this.calendar.dateAdd", // 13.c
"call this.calendar.dateAdd", // 13.e
"call this.calendar.dateAdd", // 13.w MoveRelativeDate
// BalanceDateDurationRelative
"call this.calendar.dateAdd", // 10.d
"call this.calendar.dateUntil" // 10.e
Expand All @@ -201,8 +200,8 @@ const expectedOpsForWeekRounding = expected.concat([
// CalendarDateUntil
"call this.calendar.dateUntil",
// RoundDuration
"call this.calendar.dateAdd", // 11.d MoveRelativeDate
// (11.g.iii MoveRelativeDate not called because days already balanced)
"call this.calendar.dateUntil", // 14.f
"call this.calendar.dateAdd", // 14.p MoveRelativeDate
// BalanceDateDurationRelative
"call this.calendar.dateAdd", // 16
"call this.calendar.dateUntil" // 17
Expand Down
Loading

0 comments on commit bcb4091

Please sign in to comment.