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_).