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); diff --git a/spec/duration.html b/spec/duration.html index 6646e518ff..281514bffb 100644 --- a/spec/duration.html +++ b/spec/duration.html @@ -1739,13 +1739,15 @@

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"*, 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*. + 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. 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_). @@ -1754,24 +1756,16 @@

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 _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*. + 1. If _effectiveLargestUnit_ is *"week"*, then 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. 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*. 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_).