diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs index 2fdde44e85..b42e25c834 100644 --- a/polyfill/lib/ecmascript.mjs +++ b/polyfill/lib/ecmascript.mjs @@ -5088,15 +5088,9 @@ export function RoundDuration( relativeTo = undefined ) { const TemporalDuration = GetIntrinsic('%Temporal.Duration%'); - let calendar, zdtRelative; - if (relativeTo) { - if (IsTemporalZonedDateTime(relativeTo)) { - zdtRelative = relativeTo; - relativeTo = ToTemporalDate(relativeTo); - } else if (!IsTemporalDate(relativeTo)) { - throw new TypeError('starting point must be PlainDate or ZonedDateTime'); - } - calendar = GetSlot(relativeTo, CALENDAR); + + if ((unit === 'year' || unit === 'month' || unit === 'week') && !relativeTo) { + throw new RangeError(`A starting point is required for ${unit}s rounding`); } // First convert time units up to days, if rounding to days or higher units. @@ -5105,8 +5099,8 @@ export function RoundDuration( if (unit === 'year' || unit === 'month' || unit === 'week' || unit === 'day') { nanoseconds = TotalDurationNanoseconds(0, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, 0); let intermediate; - if (zdtRelative) { - intermediate = MoveRelativeZonedDateTime(zdtRelative, years, months, weeks, days); + if (IsTemporalZonedDateTime(relativeTo)) { + intermediate = MoveRelativeZonedDateTime(relativeTo, years, months, weeks, days); } let deltaDays; ({ days: deltaDays, nanoseconds, dayLengthNs } = NanosecondsToDays(nanoseconds, intermediate)); @@ -5117,7 +5111,8 @@ export function RoundDuration( let total; switch (unit) { case 'year': { - if (!calendar) throw new RangeError('A starting point is required for years rounding'); + relativeTo = ToTemporalDate(relativeTo); + const calendar = GetSlot(relativeTo, CALENDAR); // convert months and weeks to days by calculating difference( // relativeTo + years, relativeTo + { years, months, weeks }) @@ -5161,7 +5156,8 @@ export function RoundDuration( break; } case 'month': { - if (!calendar) throw new RangeError('A starting point is required for months rounding'); + relativeTo = ToTemporalDate(relativeTo); + const calendar = GetSlot(relativeTo, CALENDAR); // convert weeks to days by calculating difference(relativeTo + // { years, months }, relativeTo + { years, months, weeks }) @@ -5196,7 +5192,9 @@ export function RoundDuration( break; } case 'week': { - if (!calendar) throw new RangeError('A starting point is required for weeks rounding'); + relativeTo = ToTemporalDate(relativeTo); + const calendar = GetSlot(relativeTo, CALENDAR); + // Weeks may be different lengths of days depending on the calendar, // convert days to weeks in a loop as described above under 'years'. const sign = MathSign(days); diff --git a/spec/duration.html b/spec/duration.html index ecc0fee81c..9930b0b2cf 100644 --- a/spec/duration.html +++ b/spec/duration.html @@ -1663,21 +1663,11 @@

1. If _relativeTo_ is not present, set _relativeTo_ to *undefined*. 1. If _unit_ is *"year"*, *"month"*, or *"week"*, and _relativeTo_ is *undefined*, then 1. Throw a *RangeError* exception. - 1. Let _zonedRelativeTo_ be *undefined*. - 1. If _relativeTo_ is not *undefined*, then - 1. If _relativeTo_ has an [[InitializedTemporalZonedDateTime]] internal slot, then - 1. Set _zonedRelativeTo_ to _relativeTo_. - 1. Set _relativeTo_ to ? ToTemporalDate(_relativeTo_). - 1. Else, - 1. Assert: _relativeTo_ has an [[InitializedTemporalDate]] internal slot. - 1. Let _calendar_ be _relativeTo_.[[Calendar]]. - 1. Else, - 1. NOTE: _calendar_ will not be used below. 1. If _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then 1. Let _nanoseconds_ be ! TotalDurationNanoseconds(0, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_, 0). 1. Let _intermediate_ be *undefined*. - 1. If _zonedRelativeTo_ is not *undefined*, then - 1. Let _intermediate_ be ? MoveRelativeZonedDateTime(_zonedRelativeTo_, _years_, _months_, _weeks_, _days_). + 1. If _relativeTo_ is an Object with an [[InitializedTemporalZonedDateTime]] internal slot, then + 1. Let _intermediate_ be ? MoveRelativeZonedDateTime(_relativeTo_, _years_, _months_, _weeks_, _days_). 1. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _intermediate_). 1. Set _days_ to _days_ + _result_.[[Days]] + _result_.[[Nanoseconds]] / _result_.[[DayLength]]. 1. Set _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, and _nanoseconds_ to 0. @@ -1685,6 +1675,8 @@

1. Let _fractionalSeconds_ be _nanoseconds_ × 10-9 + _microseconds_ × 10-6 + _milliseconds_ × 10-3 + _seconds_. 1. Let _remainder_ be *undefined*. 1. If _unit_ is *"year"*, then + 1. Set _relativeTo_ to ? ToTemporalDate(_relativeTo_). + 1. Let _calendar_ be _relativeTo_.[[Calendar]]. 1. Let _yearsDuration_ be ! CreateTemporalDuration(_years_, 0, 0, 0, 0, 0, 0, 0, 0, 0). 1. If _calendar_ is an Object, then 1. Let _dateAdd_ be ? GetMethod(_calendar_, *"dateAdd"*). @@ -1717,6 +1709,8 @@

1. Set _remainder_ to _fractionalYears_ - _years_. 1. Set _months_, _weeks_, and _days_ to 0. 1. Else if _unit_ is *"month"*, then + 1. Set _relativeTo_ to ? ToTemporalDate(_relativeTo_). + 1. Let _calendar_ be _relativeTo_.[[Calendar]]. 1. Let _yearsMonths_ be ! CreateTemporalDuration(_years_, _months_, 0, 0, 0, 0, 0, 0, 0, 0). 1. If _calendar_ is an Object, then 1. Let _dateAdd_ be ? GetMethod(_calendar_, *"dateAdd"*). @@ -1744,6 +1738,8 @@

1. Set _remainder_ to _fractionalMonths_ - _months_. 1. Set _weeks_ and _days_ to 0. 1. Else if _unit_ is *"week"*, then + 1. Set _relativeTo_ to ? ToTemporalDate(_relativeTo_). + 1. Let _calendar_ be _relativeTo_.[[Calendar]]. 1. If _days_ < 0, let _sign_ be -1; else, let _sign_ be 1. 1. Let _oneWeek_ be ! CreateTemporalDuration(0, 0, _sign_, 0, 0, 0, 0, 0, 0, 0). 1. If _calendar_ is an Object, then