From bad709c0e8d774e644e1affef4da54c328adfbc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bargull?= Date: Wed, 27 Sep 2023 17:56:15 +0200 Subject: [PATCH 1/5] Editorial: Move early returns to the top of UnbalanceDateDurationRelative --- spec/duration.html | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/spec/duration.html b/spec/duration.html index 6646e518ff..07959c76b4 100644 --- a/spec/duration.html +++ b/spec/duration.html @@ -1741,8 +1741,13 @@

1. Assert: If _plainRelativeTo_ is not *undefined*, _calendarRec_ is not *undefined*. 1. If _largestUnit_ is *"year"*, then 1. Return ! CreateDateDurationRecord(_years_, _months_, _weeks_, _days_). + 1. If _largestUnit_ is *"month"* and _years_ = 0, then + 1. Return ! CreateDateDurationRecord(0, _months_, _weeks_, _days_). + 1. If _largestUnit_ is *"week"* and _years_ = 0 and _months_ = 0, then + 1. Return ! CreateDateDurationRecord(0, 0, _weeks_, _days_). + 1. If _largestUnit_ is *"day"* and _years_ = 0 and _months_ = 0 and _weeks_ = 0, then + 1. Return ! CreateDateDurationRecord(0, 0, 0, _days_). 1. If _largestUnit_ is *"month"*, then - 1. If _years_ = 0, return ! CreateDateDurationRecord(0, _months_, _weeks_, _days_). 1. If _calendarRec_ is *undefined*, then 1. Throw a *RangeError* exception. 1. Assert: CalendarMethodsRecordHasLookedUp(_calendarRec_, ~date-add~) is *true*. @@ -1755,7 +1760,6 @@

1. Let _yearsInMonths_ be _untilResult_.[[Months]]. 1. Return ? CreateDateDurationRecord(0, _months_ + _yearsInMonths_, _weeks_, _days_). 1. If _largestUnit_ is *"week"*, then - 1. If _years_ = 0 and _months_ = 0, return ! CreateDateDurationRecord(0, 0, _weeks_, _days_). 1. If _calendarRec_ is *undefined*, then 1. Throw a *RangeError* exception. 1. Assert: CalendarMethodsRecordHasLookedUp(_calendarRec_, ~date-add~) is *true*. @@ -1764,7 +1768,6 @@

1. Let _yearsMonthsInDays_ be DaysUntil(_plainRelativeTo_, _later_). 1. Return ? CreateDateDurationRecord(0, 0, _weeks_, _days_ + _yearsMonthsInDays_). 1. NOTE: _largestUnit_ can be any time unit as well as *"day"*. - 1. If _years_ = 0, and _months_ = 0, and _weeks_ = 0, return ! CreateDateDurationRecord(0, 0, 0, _days_). 1. If _calendarRec_ is *undefined*, then 1. Throw a *RangeError* exception. 1. Assert: CalendarMethodsRecordHasLookedUp(_calendarRec_, ~date-add~) is *true*. From 8452ea5956c40dfb9f9263b70ff7214dfbb771a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bargull?= Date: Wed, 27 Sep 2023 17:58:26 +0200 Subject: [PATCH 2/5] Editorial: Algorithmic approach for early returns in UnbalanceDateDurationRelative --- spec/duration.html | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/spec/duration.html b/spec/duration.html index 07959c76b4..092827efe5 100644 --- a/spec/duration.html +++ b/spec/duration.html @@ -1739,15 +1739,12 @@

1. Assert: If _plainRelativeTo_ is not *undefined*, _calendarRec_ is not *undefined*. - 1. If _largestUnit_ is *"year"*, then + 1. Let _defaultLargestUnit_ be DefaultTemporalLargestUnit(_years_, _months_, _weeks_, _days_, 0, 0, 0, 0, 0). + 1. Let _effectiveLargestUnit_ be LargerOfTwoTemporalUnits(_largestUnit_, *"day"*). + 1. If _effectiveLargestUnit_ is LargerOfTwoTemporalUnits(_defaultLargestUnit_, _effectiveLargestUnit_), then 1. Return ! CreateDateDurationRecord(_years_, _months_, _weeks_, _days_). - 1. If _largestUnit_ is *"month"* and _years_ = 0, then - 1. Return ! CreateDateDurationRecord(0, _months_, _weeks_, _days_). - 1. If _largestUnit_ is *"week"* and _years_ = 0 and _months_ = 0, then - 1. Return ! CreateDateDurationRecord(0, 0, _weeks_, _days_). - 1. If _largestUnit_ is *"day"* and _years_ = 0 and _months_ = 0 and _weeks_ = 0, then - 1. Return ! CreateDateDurationRecord(0, 0, 0, _days_). - 1. If _largestUnit_ is *"month"*, then + 1. Assert: _effectiveLargestUnit_ is not *"year"*. + 1. If _effectiveLargestUnit_ is *"month"*, then 1. If _calendarRec_ is *undefined*, then 1. Throw a *RangeError* exception. 1. Assert: CalendarMethodsRecordHasLookedUp(_calendarRec_, ~date-add~) is *true*. @@ -1759,7 +1756,7 @@

1. Let _untilResult_ be ? CalendarDateUntil(_calendarRec_, _plainRelativeTo_, _later_, _untilOptions_). 1. Let _yearsInMonths_ be _untilResult_.[[Months]]. 1. Return ? CreateDateDurationRecord(0, _months_ + _yearsInMonths_, _weeks_, _days_). - 1. If _largestUnit_ is *"week"*, then + 1. If _effectiveLargestUnit_ is *"week"*, then 1. If _calendarRec_ is *undefined*, then 1. Throw a *RangeError* exception. 1. Assert: CalendarMethodsRecordHasLookedUp(_calendarRec_, ~date-add~) is *true*. From 0e70ca42e7f5f1c883894d2564fb69b7812b5976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bargull?= Date: Wed, 27 Sep 2023 17:59:35 +0200 Subject: [PATCH 3/5] Editorial: Throw early in UnbalanceDateDurationRelative --- spec/duration.html | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/spec/duration.html b/spec/duration.html index 092827efe5..9a15cfbc08 100644 --- a/spec/duration.html +++ b/spec/duration.html @@ -1744,10 +1744,10 @@

1. If _effectiveLargestUnit_ is LargerOfTwoTemporalUnits(_defaultLargestUnit_, _effectiveLargestUnit_), then 1. Return ! CreateDateDurationRecord(_years_, _months_, _weeks_, _days_). 1. Assert: _effectiveLargestUnit_ is not *"year"*. + 1. If _calendarRec_ is *undefined*, then + 1. Throw a *RangeError* exception. + 1. Assert: CalendarMethodsRecordHasLookedUp(_calendarRec_, ~date-add~) is *true*. 1. If _effectiveLargestUnit_ is *"month"*, then - 1. If _calendarRec_ is *undefined*, then - 1. Throw a *RangeError* exception. - 1. Assert: CalendarMethodsRecordHasLookedUp(_calendarRec_, ~date-add~) is *true*. 1. Assert: CalendarMethodsRecordHasLookedUp(_calendarRec_, ~date-until~) is *true*. 1. Let _yearsDuration_ be ! CreateTemporalDuration(_years_, 0, 0, 0, 0, 0, 0, 0, 0, 0). 1. Let _later_ be ? CalendarDateAdd(_calendarRec_, _plainRelativeTo_, _yearsDuration_). @@ -1757,17 +1757,11 @@

1. Let _yearsInMonths_ be _untilResult_.[[Months]]. 1. Return ? CreateDateDurationRecord(0, _months_ + _yearsInMonths_, _weeks_, _days_). 1. If _effectiveLargestUnit_ is *"week"*, then - 1. If _calendarRec_ is *undefined*, then - 1. Throw a *RangeError* exception. - 1. Assert: CalendarMethodsRecordHasLookedUp(_calendarRec_, ~date-add~) is *true*. 1. Let _yearsMonthsDuration_ be ! CreateTemporalDuration(_years_, _months_, 0, 0, 0, 0, 0, 0, 0, 0). 1. Let _later_ be ? CalendarDateAdd(_calendarRec_, _plainRelativeTo_, _yearsMonthsDuration_). 1. Let _yearsMonthsInDays_ be DaysUntil(_plainRelativeTo_, _later_). 1. Return ? CreateDateDurationRecord(0, 0, _weeks_, _days_ + _yearsMonthsInDays_). 1. NOTE: _largestUnit_ can be any time unit as well as *"day"*. - 1. If _calendarRec_ is *undefined*, then - 1. Throw a *RangeError* exception. - 1. Assert: CalendarMethodsRecordHasLookedUp(_calendarRec_, ~date-add~) is *true*. 1. Let _yearsMonthsWeeksDuration_ be ! CreateTemporalDuration(_years_, _months_, _weeks_, 0, 0, 0, 0, 0, 0, 0). 1. Let _later_ be ? CalendarDateAdd(_calendarRec_, _plainRelativeTo_, _yearsMonthsWeeksDuration_). 1. Let _yearsMonthsWeeksInDays_ be DaysUntil(_plainRelativeTo_, _later_). From ddc0c1aeaac08c6af0e0e23dba58e804189a26d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Bargull?= Date: Wed, 27 Sep 2023 18:25:22 +0200 Subject: [PATCH 4/5] Editorial: Last CreateDateDurationRecords are infallible in UnbalanceDateDurationRelative The `DaysUntil` calls can at most modify `days` by 200,000,000, so the CreateDateDurationRecord calls are infallible. --- spec/duration.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/duration.html b/spec/duration.html index 9a15cfbc08..281514bffb 100644 --- a/spec/duration.html +++ b/spec/duration.html @@ -1760,12 +1760,12 @@

1. Let _yearsMonthsDuration_ be ! CreateTemporalDuration(_years_, _months_, 0, 0, 0, 0, 0, 0, 0, 0). 1. Let _later_ be ? CalendarDateAdd(_calendarRec_, _plainRelativeTo_, _yearsMonthsDuration_). 1. Let _yearsMonthsInDays_ be DaysUntil(_plainRelativeTo_, _later_). - 1. Return ? CreateDateDurationRecord(0, 0, _weeks_, _days_ + _yearsMonthsInDays_). + 1. Return ! CreateDateDurationRecord(0, 0, _weeks_, _days_ + _yearsMonthsInDays_). 1. NOTE: _largestUnit_ can be any time unit as well as *"day"*. 1. Let _yearsMonthsWeeksDuration_ be ! CreateTemporalDuration(_years_, _months_, _weeks_, 0, 0, 0, 0, 0, 0, 0). 1. Let _later_ be ? CalendarDateAdd(_calendarRec_, _plainRelativeTo_, _yearsMonthsWeeksDuration_). 1. Let _yearsMonthsWeeksInDays_ be DaysUntil(_plainRelativeTo_, _later_). - 1. Return ? CreateDateDurationRecord(0, 0, 0, _days_ + _yearsMonthsWeeksInDays_). + 1. Return ! CreateDateDurationRecord(0, 0, 0, _days_ + _yearsMonthsWeeksInDays_). From a5c5587b57ec1374664ad9bfb5507eca451c31b6 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Wed, 31 Jan 2024 10:46:54 -0800 Subject: [PATCH 5/5] Polyfill: Refactor UnbalanceDateDurationRelative to match spec changes This applies the spec changes in the previous commits to UnbalanceDateDurationRelative in the polyfill. --- polyfill/lib/ecmascript.mjs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs index 666fad6ca1..14f3355ba1 100644 --- a/polyfill/lib/ecmascript.mjs +++ b/polyfill/lib/ecmascript.mjs @@ -3445,14 +3445,18 @@ export function BalanceTimeDurationRelative( export function UnbalanceDateDurationRelative(years, months, weeks, days, largestUnit, plainRelativeTo, calendarRec) { // calendarRec must have looked up dateAdd and dateUntil const TemporalDuration = GetIntrinsic('%Temporal.Duration%'); + const defaultLargestUnit = DefaultTemporalLargestUnit(years, months, weeks, days, 0, 0, 0, 0, 0, 0); + const effectiveLargestUnit = LargerOfTwoTemporalUnits(largestUnit, 'day'); + if (LargerOfTwoTemporalUnits(defaultLargestUnit, effectiveLargestUnit) === effectiveLargestUnit) { + // no-op + return { years, months, weeks, days }; + } + if (!calendarRec) throw new RangeError(`a starting point is required for ${largestUnit}s balancing`); - switch (largestUnit) { + switch (effectiveLargestUnit) { case 'year': - // no-op - return { years, months, weeks, days }; + throw new Error('assert not reached'); case 'month': { - if (years === 0) return { years: 0, months, weeks, days }; - if (!calendarRec) throw new RangeError('a starting point is required for months balancing'); // balance years down to months const later = CalendarDateAdd(calendarRec, plainRelativeTo, new TemporalDuration(years)); const untilOptions = ObjectCreate(null); @@ -3462,8 +3466,6 @@ export function UnbalanceDateDurationRelative(years, months, weeks, days, larges return { years: 0, months: months + yearsInMonths, weeks, days }; } case 'week': { - if (years === 0 && months === 0) return { years: 0, months: 0, weeks, days }; - if (!calendarRec) throw new RangeError('a starting point is required for weeks balancing'); // balance years and months down to days const later = CalendarDateAdd(calendarRec, plainRelativeTo, new TemporalDuration(years, months)); const yearsMonthsInDays = DaysUntil(plainRelativeTo, later); @@ -3471,8 +3473,6 @@ export function UnbalanceDateDurationRelative(years, months, weeks, days, larges } default: { // largestUnit is "day", or any time unit - if (years === 0 && months === 0 && weeks === 0) return { years: 0, months: 0, weeks: 0, days }; - if (!calendarRec) throw new RangeError('a starting point is required for balancing calendar units'); // balance years, months, and weeks down to days const later = CalendarDateAdd(calendarRec, plainRelativeTo, new TemporalDuration(years, months, weeks)); const yearsMonthsWeeksInDays = DaysUntil(plainRelativeTo, later);