diff --git a/polyfill/lib/duration.mjs b/polyfill/lib/duration.mjs index 1b3a790646..916b52f995 100644 --- a/polyfill/lib/duration.mjs +++ b/polyfill/lib/duration.mjs @@ -1,7 +1,7 @@ /* global __debug__ */ import * as ES from './ecmascript.mjs'; -import { MakeIntrinsicClass } from './intrinsicclass.mjs'; +import { GetIntrinsic, MakeIntrinsicClass } from './intrinsicclass.mjs'; import { CalendarMethodRecord } from './methodrecord.mjs'; import { YEARS, @@ -17,6 +17,9 @@ import { CALENDAR, INSTANT, EPOCHNANOSECONDS, + ISO_YEAR, + ISO_MONTH, + ISO_DAY, CreateSlots, GetSlot, SetSlot @@ -305,11 +308,7 @@ export class Duration { let precalculatedPlainDateTime; const plainDateTimeOrRelativeToWillBeUsed = - !roundingGranularityIsNoop || - ES.IsCalendarUnit(largestUnit) || - largestUnit === 'day' || - calendarUnitsPresent || - days !== 0; + ES.IsCalendarUnit(largestUnit) || largestUnit === 'day' || calendarUnitsPresent || days !== 0; if (zonedRelativeTo && plainDateTimeOrRelativeToWillBeUsed) { // Convert a ZonedDateTime relativeTo to PlainDateTime and PlainDate only // if either is needed in one of the operations below, because the @@ -327,79 +326,85 @@ export class Duration { 'dateUntil' ]); - ({ years, months, weeks, days } = ES.UnbalanceDateDurationRelative( - years, - months, - weeks, - days, - largestUnit, - plainRelativeTo, - calendarRec - )); let norm = TimeDuration.normalize(hours, minutes, seconds, milliseconds, microseconds, nanoseconds); - ({ years, months, weeks, days, norm } = ES.RoundDuration( - years, - months, - weeks, - days, - norm, - roundingIncrement, - smallestUnit, - roundingMode, - plainRelativeTo, - calendarRec, - zonedRelativeTo, - timeZoneRec, - precalculatedPlainDateTime - )); + if (zonedRelativeTo) { - ({ years, months, weeks, days, norm } = ES.AdjustRoundedDurationDays( - years, - months, - weeks, - days, - norm, - roundingIncrement, - smallestUnit, - roundingMode, - zonedRelativeTo, - calendarRec, + const relativeEpochNs = GetSlot(zonedRelativeTo, EPOCHNANOSECONDS); + const targetEpochNs = ES.AddZonedDateTime( + GetSlot(zonedRelativeTo, INSTANT), timeZoneRec, - precalculatedPlainDateTime - )); - const intermediate = ES.MoveRelativeZonedDateTime( - zonedRelativeTo, calendarRec, - timeZoneRec, years, months, weeks, - 0, - precalculatedPlainDateTime - ); - ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.BalanceTimeDurationRelative( days, norm, - largestUnit, - intermediate, - timeZoneRec - )); + precalculatedPlainDateTime + ); + ({ years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = + ES.DifferenceZonedDateTimeWithRounding( + relativeEpochNs, + targetEpochNs, + plainRelativeTo, + calendarRec, + zonedRelativeTo, + timeZoneRec, + precalculatedPlainDateTime, + ObjectCreate(null), + largestUnit, + roundingIncrement, + smallestUnit, + roundingMode + )); + } else if (plainRelativeTo) { + let targetTime = ES.AddTime(0, 0, 0, 0, 0, 0, norm); + + // Delegate the date part addition to the calendar + const TemporalDuration = GetIntrinsic('%Temporal.Duration%'); + const dateDuration = new TemporalDuration(years, months, weeks, days + targetTime.deltaDays, 0, 0, 0, 0, 0, 0); + const targetDate = ES.AddDate(calendarRec, plainRelativeTo, dateDuration); + + ({ years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = + ES.DifferencePlainDateTimeWithRounding( + plainRelativeTo, + 0, + 0, + 0, + 0, + 0, + 0, + GetSlot(targetDate, ISO_YEAR), + GetSlot(targetDate, ISO_MONTH), + GetSlot(targetDate, ISO_DAY), + targetTime.hour, + targetTime.minute, + targetTime.second, + targetTime.millisecond, + targetTime.microsecond, + targetTime.nanosecond, + calendarRec, + largestUnit, + roundingIncrement, + smallestUnit, + roundingMode + )); } else { + // No reference date to calculate difference relative to + if (calendarUnitsPresent) { + throw new RangeError('a starting point is required for years, months, or weeks balancing'); + } + if (ES.IsCalendarUnit(largestUnit)) { + throw new RangeError(`a starting point is required for ${largestUnit}s balancing`); + } + if (ES.IsCalendarUnit(smallestUnit)) { + throw new RangeError(`a starting point is required for ${smallestUnit}s rounding`); + } + ({ days, norm } = ES.RoundDuration(0, 0, 0, days, norm, roundingIncrement, smallestUnit, roundingMode)); ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.BalanceTimeDuration( norm.add24HourDays(days), largestUnit )); } - ({ years, months, weeks, days } = ES.BalanceDateDurationRelative( - years, - months, - weeks, - days, - largestUnit, - smallestUnit, - plainRelativeTo, - calendarRec - )); return new Duration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds); } @@ -446,69 +451,80 @@ export class Duration { 'dateUntil' ]); - // Convert larger units down to days - ({ years, months, weeks, days } = ES.UnbalanceDateDurationRelative( - years, - months, - weeks, - days, - unit, - plainRelativeTo, - calendarRec - )); - let norm; - // If the unit we're totalling is smaller than `days`, convert days down to that unit. + let norm = TimeDuration.normalize(hours, minutes, seconds, milliseconds, microseconds, nanoseconds); if (zonedRelativeTo) { - const intermediate = ES.MoveRelativeZonedDateTime( - zonedRelativeTo, - calendarRec, + const relativeEpochNs = GetSlot(zonedRelativeTo, EPOCHNANOSECONDS); + const targetEpochNs = ES.AddZonedDateTime( + GetSlot(zonedRelativeTo, INSTANT), timeZoneRec, + calendarRec, years, months, weeks, - 0, + days, + norm, precalculatedPlainDateTime ); - norm = TimeDuration.normalize(hours, minutes, seconds, milliseconds, microseconds, nanoseconds); - - // Inline BalanceTimeDurationRelative, without the final balance step - const start = GetSlot(intermediate, INSTANT); - const startNs = GetSlot(intermediate, EPOCHNANOSECONDS); - let intermediateNs = startNs; - let startDt; - if (days !== 0) { - startDt = ES.GetPlainDateTimeFor(timeZoneRec, start, 'iso8601'); - intermediateNs = ES.AddDaysToZonedDateTime(start, startDt, timeZoneRec, 'iso8601', days).epochNs; - } - const endNs = ES.AddInstant(intermediateNs, norm); - norm = TimeDuration.fromEpochNsDiff(endNs, startNs); - if (ES.IsCalendarUnit(unit) || unit === 'day') { - if (!norm.isZero()) startDt ??= ES.GetPlainDateTimeFor(timeZoneRec, start, 'iso8601'); - ({ days, norm } = ES.NormalizedTimeDurationToDays(norm, intermediate, timeZoneRec, startDt)); - } else { - days = 0; - } - } else { - norm = TimeDuration.normalize(hours, minutes, seconds, milliseconds, microseconds, nanoseconds); - norm = norm.add24HourDays(days); - days = 0; + const { total } = ES.DifferenceZonedDateTimeWithRounding( + relativeEpochNs, + targetEpochNs, + plainRelativeTo, + calendarRec, + zonedRelativeTo, + timeZoneRec, + precalculatedPlainDateTime, + ObjectCreate(null), + unit, + 1, + unit, + 'trunc' + ); + return total; } - // Finally, truncate to the correct unit and calculate remainder - const { total } = ES.RoundDuration( - years, - months, - weeks, - days, - norm, - 1, - unit, - 'trunc', - plainRelativeTo, - calendarRec, - zonedRelativeTo, - timeZoneRec, - precalculatedPlainDateTime - ); + + if (plainRelativeTo) { + let targetTime = ES.AddTime(0, 0, 0, 0, 0, 0, norm); + + // Delegate the date part addition to the calendar + const TemporalDuration = GetIntrinsic('%Temporal.Duration%'); + const dateDuration = new TemporalDuration(years, months, weeks, days + targetTime.deltaDays, 0, 0, 0, 0, 0, 0); + const targetDate = ES.AddDate(calendarRec, plainRelativeTo, dateDuration); + + const { total } = ES.DifferencePlainDateTimeWithRounding( + plainRelativeTo, + 0, + 0, + 0, + 0, + 0, + 0, + GetSlot(targetDate, ISO_YEAR), + GetSlot(targetDate, ISO_MONTH), + GetSlot(targetDate, ISO_DAY), + targetTime.hour, + targetTime.minute, + targetTime.second, + targetTime.millisecond, + targetTime.microsecond, + targetTime.nanosecond, + calendarRec, + unit, + 1, + unit, + 'trunc' + ); + return total; + } + + // No reference date to calculate difference relative to + if (years !== 0 || months !== 0 || weeks !== 0) { + throw new RangeError('a starting point is required for years, months, or weeks total'); + } + if (ES.IsCalendarUnit(unit)) { + throw new RangeError(`a starting point is required for ${unit}s total`); + } + norm = norm.add24HourDays(days); + const { total } = ES.RoundDuration(0, 0, 0, 0, norm, 1, unit, 'trunc'); return total; } toString(options = undefined) { @@ -707,9 +723,11 @@ export class Duration { } if (calendarUnitsPresent) { - // plainRelativeTo may be undefined, and if so Unbalance will throw - ({ days: d1 } = ES.UnbalanceDateDurationRelative(y1, mon1, w1, d1, 'day', plainRelativeTo, calendarRec)); - ({ days: d2 } = ES.UnbalanceDateDurationRelative(y2, mon2, w2, d2, 'day', plainRelativeTo, calendarRec)); + if (!plainRelativeTo) { + throw new RangeError('A starting point is required for years, months, or weeks comparison'); + } + d1 = ES.UnbalanceDateDurationRelative(y1, mon1, w1, d1, plainRelativeTo, calendarRec); + d2 = ES.UnbalanceDateDurationRelative(y2, mon2, w2, d2, plainRelativeTo, calendarRec); } const norm1 = TimeDuration.normalize(h1, min1, s1, ms1, µs1, ns1).add24HourDays(d1); const norm2 = TimeDuration.normalize(h2, min2, s2, ms2, µs2, ns2).add24HourDays(d2); diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs index a7f4b52215..dae66614d2 100644 --- a/polyfill/lib/ecmascript.mjs +++ b/polyfill/lib/ecmascript.mjs @@ -3508,43 +3508,15 @@ export function BalanceTimeDurationRelative( return { days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds }; } -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`); +export function UnbalanceDateDurationRelative(years, months, weeks, days, plainRelativeTo, calendarRec) { + // calendarRec must have looked up dateAdd, unless calendar units 0 + if (years === 0 && months === 0 && weeks === 0) return days; - switch (effectiveLargestUnit) { - case 'year': - throw new Error('assert not reached'); - case 'month': { - // balance years down to months - const later = CalendarDateAdd(calendarRec, plainRelativeTo, new TemporalDuration(years)); - const untilOptions = ObjectCreate(null); - untilOptions.largestUnit = 'month'; - const untilResult = CalendarDateUntil(calendarRec, plainRelativeTo, later, untilOptions); - const yearsInMonths = GetSlot(untilResult, MONTHS); - return { years: 0, months: months + yearsInMonths, weeks, days }; - } - case 'week': { - // balance years and months down to days - const later = CalendarDateAdd(calendarRec, plainRelativeTo, new TemporalDuration(years, months)); - const yearsMonthsInDays = DaysUntil(plainRelativeTo, later); - return { years: 0, months: 0, weeks, days: days + yearsMonthsInDays }; - } - default: { - // largestUnit is "day", or any time unit - // balance years, months, and weeks down to days - const later = CalendarDateAdd(calendarRec, plainRelativeTo, new TemporalDuration(years, months, weeks)); - const yearsMonthsWeeksInDays = DaysUntil(plainRelativeTo, later); - return { years: 0, months: 0, weeks: 0, days: days + yearsMonthsWeeksInDays }; - } - } + // balance years, months, and weeks down to days + const TemporalDuration = GetIntrinsic('%Temporal.Duration%'); + const later = CalendarDateAdd(calendarRec, plainRelativeTo, new TemporalDuration(years, months, weeks)); + const yearsMonthsWeeksInDays = DaysUntil(plainRelativeTo, later); + return days + yearsMonthsWeeksInDays; } export function BalanceDateDurationRelative( @@ -3570,8 +3542,6 @@ export function BalanceDateDurationRelative( return { years, months, weeks, days }; } - if (!plainRelativeTo) throw new RangeError(`a starting point is required for ${largestUnit}s balancing`); - const untilOptions = ObjectCreate(null); untilOptions.largestUnit = largestUnit; @@ -3830,9 +3800,7 @@ export function DifferenceTime(h1, min1, s1, ms1, µs1, ns1, h2, min2, s2, ms2, export function DifferenceInstant(ns1, ns2, increment, smallestUnit, roundingMode) { const diff = TimeDuration.fromEpochNsDiff(ns2, ns1); - if (smallestUnit === 'nanosecond' && increment === 1) return diff; - - return RoundDuration(0, 0, 0, 0, diff, increment, smallestUnit, roundingMode).norm; + return RoundDuration(0, 0, 0, 0, diff, increment, smallestUnit, roundingMode); } export function DifferenceDate(calendarRec, plainDate1, plainDate2, options) { @@ -3893,7 +3861,12 @@ export function DifferenceISODateTime( const years = GetSlot(untilResult, YEARS); const months = GetSlot(untilResult, MONTHS); const weeks = GetSlot(untilResult, WEEKS); - const days = GetSlot(untilResult, DAYS); + let days = GetSlot(untilResult, DAYS); + if (largestUnit !== dateLargestUnit) { + // largestUnit < days, so add the days in to the normalized duration + timeDuration = timeDuration.add24HourDays(days); + days = 0; + } CombineDateAndNormalizedTimeDuration(years, months, weeks, days, timeDuration); return { years, months, weeks, days, norm: timeDuration }; } @@ -4027,6 +4000,213 @@ export function DifferenceZonedDateTime( return { years, months, weeks, days, norm }; } +export function DifferencePlainDateTimeWithRounding( + plainDate1, + h1, + min1, + s1, + ms1, + µs1, + ns1, + y2, + mon2, + d2, + h2, + min2, + s2, + ms2, + µs2, + ns2, + calendarRec, + largestUnit, + roundingIncrement, + smallestUnit, + roundingMode, + resolvedOptions +) { + const y1 = GetSlot(plainDate1, ISO_YEAR); + const mon1 = GetSlot(plainDate1, ISO_MONTH); + const d1 = GetSlot(plainDate1, ISO_DAY); + if (CompareISODateTime(y1, mon1, d1, h1, min1, s1, ms1, µs1, ns1, y2, mon2, d2, h2, min2, s2, ms2, µs2, ns2) == 0) { + return { + years: 0, + months: 0, + weeks: 0, + days: 0, + hours: 0, + minutes: 0, + seconds: 0, + milliseconds: 0, + microseconds: 0, + nanoseconds: 0, + total: 0 + }; + } + + let { years, months, weeks, days, norm } = DifferenceISODateTime( + y1, + mon1, + d1, + h1, + min1, + s1, + ms1, + µs1, + ns1, + y2, + mon2, + d2, + h2, + min2, + s2, + ms2, + µs2, + ns2, + calendarRec, + largestUnit, + resolvedOptions + ); + + const roundingIsNoop = smallestUnit === 'nanosecond' && roundingIncrement === 1; + if (roundingIsNoop) { + const normWithDays = norm.add24HourDays(days); + let hours, minutes, seconds, milliseconds, microseconds, nanoseconds; + ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration( + normWithDays, + largestUnit + )); + const total = norm.totalNs.toJSNumber(); + return { years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, total }; + } + + let total; + ({ years, months, weeks, days, norm, total } = RoundDuration( + years, + months, + weeks, + days, + norm, + roundingIncrement, + smallestUnit, + roundingMode, + plainDate1, + calendarRec + )); + const normWithDays = norm.add24HourDays(days); + let hours, minutes, seconds, milliseconds, microseconds, nanoseconds; + ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration( + normWithDays, + largestUnit + )); + ({ years, months, weeks, days } = BalanceDateDurationRelative( + years, + months, + weeks, + days, + largestUnit, + smallestUnit, + plainDate1, + calendarRec + )); + return { years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, total }; +} + +export function DifferenceZonedDateTimeWithRounding( + ns1, + ns2, + plainRelativeTo, + calendarRec, + zonedDateTime, + timeZoneRec, + precalculatedPlainDateTime, + resolvedOptions, + largestUnit, + roundingIncrement, + smallestUnit, + roundingMode +) { + if (!IsCalendarUnit(largestUnit) && largestUnit !== 'day') { + // The user is only asking for a time difference, so return difference of instants. + const { norm, total } = DifferenceInstant(ns1, ns2, roundingIncrement, smallestUnit, largestUnit, roundingMode); + const { hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration(norm, largestUnit); + return { + years: 0, + months: 0, + weeks: 0, + days: 0, + hours, + minutes, + seconds, + milliseconds, + microseconds, + nanoseconds, + total + }; + } + + let { years, months, weeks, days, norm } = DifferenceZonedDateTime( + ns1, + ns2, + timeZoneRec, + calendarRec, + largestUnit, + resolvedOptions, + precalculatedPlainDateTime + ); + + const roundingIsNoop = smallestUnit === 'nanosecond' && roundingIncrement === 1; + if (roundingIsNoop) { + const { hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration(norm, 'hour'); + const total = norm.totalNs.toJSNumber(); + return { years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, total }; + } + + let total; + ({ years, months, weeks, days, norm, total } = RoundDuration( + years, + months, + weeks, + days, + norm, + roundingIncrement, + smallestUnit, + roundingMode, + plainRelativeTo, + calendarRec, + zonedDateTime, + timeZoneRec, + precalculatedPlainDateTime + )); + ({ years, months, weeks, days, norm } = AdjustRoundedDurationDays( + years, + months, + weeks, + days, + norm, + roundingIncrement, + smallestUnit, + roundingMode, + zonedDateTime, + calendarRec, + timeZoneRec, + precalculatedPlainDateTime + )); + ({ years, months, weeks, days } = BalanceDateDurationRelative( + years, + months, + weeks, + days, + largestUnit, + smallestUnit, + plainRelativeTo, + calendarRec + )); + CombineDateAndNormalizedTimeDuration(years, months, weeks, days, norm); + const { hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration(norm, 'hour'); + + return { years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, total }; +} + export function GetDifferenceSettings(op, options, group, disallowed, fallbackSmallest, smallestLargestDefaultUnit) { const ALLOWED_UNITS = TEMPORAL_UNITS.reduce((allowed, unitInfo) => { const p = unitInfo[0]; @@ -4081,7 +4261,7 @@ export function DifferenceTemporalInstant(operation, instant, other, options) { const onens = GetSlot(instant, EPOCHNANOSECONDS); const twons = GetSlot(other, EPOCHNANOSECONDS); - const norm = DifferenceInstant( + const { norm } = DifferenceInstant( onens, twons, settings.roundingIncrement, @@ -4191,68 +4371,33 @@ export function DifferenceTemporalPlainDateTime(operation, plainDateTime, other, return new Duration(); } + const plainDate1 = TemporalDateTimeToDate(plainDateTime); const calendarRec = new CalendarMethodRecord(calendar, ['dateAdd', 'dateUntil']); - - let { years, months, weeks, days, norm } = DifferenceISODateTime( - GetSlot(plainDateTime, ISO_YEAR), - GetSlot(plainDateTime, ISO_MONTH), - GetSlot(plainDateTime, ISO_DAY), - GetSlot(plainDateTime, ISO_HOUR), - GetSlot(plainDateTime, ISO_MINUTE), - GetSlot(plainDateTime, ISO_SECOND), - GetSlot(plainDateTime, ISO_MILLISECOND), - GetSlot(plainDateTime, ISO_MICROSECOND), - GetSlot(plainDateTime, ISO_NANOSECOND), - GetSlot(other, ISO_YEAR), - GetSlot(other, ISO_MONTH), - GetSlot(other, ISO_DAY), - GetSlot(other, ISO_HOUR), - GetSlot(other, ISO_MINUTE), - GetSlot(other, ISO_SECOND), - GetSlot(other, ISO_MILLISECOND), - GetSlot(other, ISO_MICROSECOND), - GetSlot(other, ISO_NANOSECOND), - calendarRec, - settings.largestUnit, - resolvedOptions - ); - - let hours, minutes, seconds, milliseconds, microseconds, nanoseconds; - const roundingIsNoop = settings.smallestUnit === 'nanosecond' && settings.roundingIncrement === 1; - if (!roundingIsNoop) { - const relativeTo = TemporalDateTimeToDate(plainDateTime); - ({ years, months, weeks, days, norm } = RoundDuration( - years, - months, - weeks, - days, - norm, + const { years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = + DifferencePlainDateTimeWithRounding( + plainDate1, + GetSlot(plainDateTime, ISO_HOUR), + GetSlot(plainDateTime, ISO_MINUTE), + GetSlot(plainDateTime, ISO_SECOND), + GetSlot(plainDateTime, ISO_MILLISECOND), + GetSlot(plainDateTime, ISO_MICROSECOND), + GetSlot(plainDateTime, ISO_NANOSECOND), + GetSlot(other, ISO_YEAR), + GetSlot(other, ISO_MONTH), + GetSlot(other, ISO_DAY), + GetSlot(other, ISO_HOUR), + GetSlot(other, ISO_MINUTE), + GetSlot(other, ISO_SECOND), + GetSlot(other, ISO_MILLISECOND), + GetSlot(other, ISO_MICROSECOND), + GetSlot(other, ISO_NANOSECOND), + calendarRec, + settings.largestUnit, settings.roundingIncrement, settings.smallestUnit, settings.roundingMode, - relativeTo, - calendarRec - )); - ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration( - norm.add24HourDays(days), - settings.largestUnit - )); - ({ years, months, weeks, days } = BalanceDateDurationRelative( - years, - months, - weeks, - days, - settings.largestUnit, - settings.smallestUnit, - relativeTo, - calendarRec - )); - } else { - ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration( - norm.add24HourDays(days), - settings.largestUnit - )); - } + resolvedOptions + ); return new Duration( sign * years, @@ -4409,7 +4554,13 @@ export function DifferenceTemporalZonedDateTime(operation, zonedDateTime, other, months = 0; weeks = 0; days = 0; - const norm = DifferenceInstant(ns1, ns2, settings.roundingIncrement, settings.smallestUnit, settings.roundingMode); + const { norm } = DifferenceInstant( + ns1, + ns2, + settings.roundingIncrement, + settings.smallestUnit, + settings.roundingMode + ); ({ hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration( norm, settings.largestUnit @@ -4438,65 +4589,21 @@ export function DifferenceTemporalZonedDateTime(operation, zonedDateTime, other, ); const plainRelativeTo = TemporalDateTimeToDate(precalculatedPlainDateTime); - let norm; - ({ years, months, weeks, days, norm } = DifferenceZonedDateTime( - ns1, - ns2, - timeZoneRec, - calendarRec, - settings.largestUnit, - resolvedOptions, - precalculatedPlainDateTime - )); - - const roundingIsNoop = settings.smallestUnit === 'nanosecond' && settings.roundingIncrement === 1; - if (!roundingIsNoop) { - ({ years, months, weeks, days, norm } = RoundDuration( - years, - months, - weeks, - days, - norm, - settings.roundingIncrement, - settings.smallestUnit, - settings.roundingMode, + ({ years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = + DifferenceZonedDateTimeWithRounding( + ns1, + ns2, plainRelativeTo, calendarRec, zonedDateTime, timeZoneRec, - precalculatedPlainDateTime - )); - let deltaDays; - ({ days: deltaDays, norm } = NormalizedTimeDurationToDays(norm, zonedDateTime, timeZoneRec)); - days += deltaDays; - ({ years, months, weeks, days, norm } = AdjustRoundedDurationDays( - years, - months, - weeks, - days, - norm, - settings.roundingIncrement, - settings.smallestUnit, - settings.roundingMode, - zonedDateTime, - calendarRec, - timeZoneRec, - precalculatedPlainDateTime - )); - // BalanceTimeDuration already performed in AdjustRoundedDurationDays - ({ years, months, weeks, days } = BalanceDateDurationRelative( - years, - months, - weeks, - days, + precalculatedPlainDateTime, + resolvedOptions, settings.largestUnit, + settings.roundingIncrement, settings.smallestUnit, - plainRelativeTo, - calendarRec + settings.roundingMode )); - CombineDateAndNormalizedTimeDuration(years, months, weeks, days, norm); - } - ({ hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration(norm, 'hour')); } return new Duration( diff --git a/spec/duration.html b/spec/duration.html index b4f56a6c72..fd62cb84bc 100644 --- a/spec/duration.html +++ b/spec/duration.html @@ -114,10 +114,9 @@

Temporal.Duration.compare ( _one_, _two_ [ , _options_ ] )

1. If _after1_ < _after2_, return *-1*𝔽. 1. Return *+0*𝔽. 1. If _calendarUnitsPresent_ is *true*, then - 1. Let _unbalanceResult1_ be ? UnbalanceDateDurationRelative(_one_.[[Years]], _one_.[[Months]], _one_.[[Weeks]], _one_.[[Days]], *"day"*, _plainRelativeTo_, _calendarRec_). - 1. Let _unbalanceResult2_ be ? UnbalanceDateDurationRelative(_two_.[[Years]], _two_.[[Months]], _two_.[[Weeks]], _two_.[[Days]], *"day"*, _plainRelativeTo_, _calendarRec_). - 1. Let _days1_ be _unbalanceResult1_.[[Days]]. - 1. Let _days2_ be _unbalanceResult2_.[[Days]]. + 1. If _plainRelativeTo_ is *undefined*, throw a *RangeError* exception. + 1. Let _days1_ be ? UnbalanceDateDurationRelative(_one_.[[Years]], _one_.[[Months]], _one_.[[Weeks]], _one_.[[Days]], _plainRelativeTo_, _calendarRec_). + 1. Let _days2_ be ? UnbalanceDateDurationRelative(_two_.[[Years]], _two_.[[Months]], _two_.[[Weeks]], _two_.[[Days]], _plainRelativeTo_, _calendarRec_). 1. Else, 1. Let _days1_ be _one_.[[Days]]. 1. Let _days2_ be _two_.[[Days]]. @@ -461,26 +460,34 @@

Temporal.Duration.prototype.round ( _roundTo_ )

1. NOTE: The above conditions mean that the operation will have no effect: the smallest unit and rounding increment will leave the total duration unchanged, and it can be determined without calling a calendar or time zone method that no balancing will take place. 1. Return ! CreateTemporalDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]]). 1. Let _precalculatedPlainDateTime_ be *undefined*. - 1. If _roundingGranularityIsNoop_ is *false*, or IsCalendarUnit(_largestUnit_) is *true*, or _largestUnit_ is *"day"*, or _calendarUnitsPresent_ is *true*, or _duration_.[[Days]] ≠ 0, let _plainDateTimeOrRelativeToWillBeUsed_ be *true*; else let _plainDateTimeOrRelativeToWillBeUsed_ be *false*. + 1. If IsCalendarUnit(_largestUnit_) is *true*, or _largestUnit_ is *"day"*, or _calendarUnitsPresent_ is *true*, or _duration_.[[Days]] ≠ 0, let _plainDateTimeOrRelativeToWillBeUsed_ be *true*; else let _plainDateTimeOrRelativeToWillBeUsed_ be *false*. 1. If _zonedRelativeTo_ is not *undefined* and _plainDateTimeOrRelativeToWillBeUsed_ is *true*, then 1. NOTE: The above conditions mean that the corresponding `Temporal.PlainDateTime` or `Temporal.PlainDate` for _zonedRelativeTo_ will be used in one of the operations below. 1. Let _instant_ be ! CreateTemporalInstant(_zonedRelativeTo_.[[Nanoseconds]]). 1. Set _precalculatedPlainDateTime_ to ? GetPlainDateTimeFor(_timeZoneRec_, _instant_, _zonedRelativeTo_.[[Calendar]]). 1. Set _plainRelativeTo_ to ! CreateTemporalDate(_precalculatedPlainDateTime_.[[ISOYear]], _precalculatedPlainDateTime_.[[ISOMonth]], _precalculatedPlainDateTime_.[[ISODay]], _zonedRelativeTo_.[[Calendar]]). 1. Let _calendarRec_ be ? CreateCalendarMethodsRecordFromRelativeTo(_plainRelativeTo_, _zonedRelativeTo_, « ~date-add~, ~date-until~ »). - 1. Let _unbalanceResult_ be ? UnbalanceDateDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _largestUnit_, _plainRelativeTo_, _calendarRec_). 1. Let _norm_ be NormalizeTimeDuration(_duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]]). - 1. Let _roundRecord_ be ? RoundDuration(_unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], _unbalanceResult_.[[Days]], _norm_, _roundingIncrement_, _smallestUnit_, _roundingMode_, _plainRelativeTo_, _calendarRec_, _zonedRelativeTo_, _timeZoneRec_, _precalculatedPlainDateTime_). - 1. Let _roundResult_ be _roundRecord_.[[NormalizedDuration]]. + 1. Let _emptyOptions_ be OrdinaryObjectCreate(*null*). 1. If _zonedRelativeTo_ is not *undefined*, then - 1. Set _roundResult_ to ? AdjustRoundedDurationDays(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _roundResult_.[[Days]], _roundResult_.[[NormalizedTime]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _zonedRelativeTo_, _calendarRec_, _timeZoneRec_, _precalculatedPlainDateTime_). - 1. Let _intermediate_ be ? MoveRelativeZonedDateTime(_zonedRelativeTo_, _calendarRec_, _timeZoneRec_, _roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], 0, _precalculatedPlainDateTime_). - 1. Let _balanceResult_ be ? BalanceTimeDurationRelative(_roundResult_.[[Days]], _roundResult_.[[NormalizedTime]], _largestUnit_, _intermediate_, _timeZoneRec_, _precalculatedPlainDateTime_). + 1. Let _relativeEpochNs_ be _zonedRelativeTo_.[[Nanoseconds]]. + 1. Let _relativeInstant_ be ! CreateTemporalInstant(_relativeEpochNs_). + 1. Let _targetEpochNs_ be ? AddZonedDateTime(_relativeInstant_, _timeZoneRec_, _calendarRec_, _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _norm_, _precalculatedPlainDateTime_). + 1. Let _roundRecord_ be ? DifferenceZonedDateTimeWithRounding(_relativeEpochNs_, _targetEpochNs_, _plainRelativeTo_, _calendarRec_, _zonedRelativeTo_, _timeZoneRec_, _precalculatedPlainDateTime_, _emptyOptions_, _largestUnit_, _roundingIncrement_, _smallestUnit_, _roundingMode_). + 1. Let _roundResult_ be _roundRecord_.[[DurationRecord]]. + 1. Else if _plainRelativeTo_ is not *undefined*, then + 1. Let _targetTime_ be AddTime(0, 0, 0, 0, 0, 0, _norm_). + 1. Let _dateDuration_ be ? CreateTemporalDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]] + _targetTime_.[[Days]], 0, 0, 0, 0, 0, 0). + 1. Let _targetDate_ be ? AddDate(_calendarRec_, _plainRelativeTo_, _dateDuration_). + 1. Let _roundRecord_ be ? DifferencePlainDateTimeWithRounding(_plainRelativeTo_, 0, 0, 0, 0, 0, 0, _targetDate_.[[ISOYear]], _targetDate_.[[ISOMonth]], _targetDate_.[[ISODay]], _targetTime_.[[Hours]], _targetTime_.[[Minutes]], _targetTime_.[[Seconds]], _targetTime_.[[Milliseconds]], _targetTime_.[[Microseconds]], _targetTime_.[[Nanoseconds]], _calendarRec_, _largestUnit_, _roundingIncrement_, _smallestUnit_, _roundingMode_, _emptyOptions_). + 1. Let _roundResult_ be _roundRecord_.[[DurationRecord]]. 1. Else, - 1. Let _normWithDays_ be ? Add24HourDaysToNormalizedTimeDuration(_roundResult_.[[NormalizedTime]], _roundResult_.[[Days]]). + 1. If _calendarUnitsPresent_ is *true*, or IsCalendarUnit(_largestUnit_) is *true*, or IsCalendarUnit(_smallestUnit_) is *true*, throw a *RangeError* exception. + 1. Let _roundRecord_ be ? RoundDuration(0, 0, 0, _duration_.[[Days]], _norm_, _roundingIncrement_, _smallestUnit_, _roundingMode_). + 1. Let _normWithDays_ be ? Add24HourDaysToNormalizedTimeDuration(_roundRecord_.[[NormalizedDuration]].[[Days]], _roundRecord_.[[NormalizedDuration]].[[NormalizedTime]]). 1. Let _balanceResult_ be BalanceTimeDuration(_normWithDays_, _largestUnit_). - 1. Let _result_ be ? BalanceDateDurationRelative(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _balanceResult_.[[Days]], _largestUnit_, _smallestUnit_, _plainRelativeTo_, _calendarRec_). - 1. Return ? CreateTemporalDuration(_result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _result_.[[Days]], _balanceResult_.[[Hours]], _balanceResult_.[[Minutes]], _balanceResult_.[[Seconds]], _balanceResult_.[[Milliseconds]], _balanceResult_.[[Microseconds]], _balanceResult_.[[Nanoseconds]]). + 1. Let _roundResult_ be CreateDurationRecord(0, 0, 0, _balanceResult_.[[Days]], _balanceResult_.[[Hours]], _balanceResult_.[[Minutes]], _balanceResult_.[[Seconds]], _balanceResult_.[[Milliseconds]], _balanceResult_.[[Microseconds]], _balanceResult_.[[Nanoseconds]]). + 1. Return ? CreateTemporalDuration(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _roundResult_.[[Days]], _roundResult_.[[Hours]], _roundResult_.[[Minutes]], _roundResult_.[[Seconds]], _roundResult_.[[Milliseconds]], _roundResult_.[[Microseconds]], _roundResult_.[[Nanoseconds]]). @@ -513,34 +520,22 @@

Temporal.Duration.prototype.total ( _totalOf_ )

1. Set _precalculatedPlainDateTime_ to ? GetPlainDateTimeFor(_timeZoneRec_, _instant_, _zonedRelativeTo_.[[Calendar]]). 1. Set _plainRelativeTo_ to ! CreateTemporalDate(_precalculatedPlainDateTime_.[[ISOYear]], _precalculatedPlainDateTime_.[[ISOMonth]], _precalculatedPlainDateTime_.[[ISODay]], _zonedRelativeTo_.[[Calendar]]). 1. Let _calendarRec_ be ? CreateCalendarMethodsRecordFromRelativeTo(_plainRelativeTo_, _zonedRelativeTo_, « ~date-add~, ~date-until~ »). - 1. Let _unbalanceResult_ be ? UnbalanceDateDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _unit_, _plainRelativeTo_, _calendarRec_). - 1. Let _days_ be _unbalanceResult_.[[Days]]. + 1. Let _norm_ be NormalizeTimeDuration(_duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]]). + 1. Let _emptyOptions_ be OrdinaryObjectCreate(*null*). 1. If _zonedRelativeTo_ is not *undefined*, then - 1. Let _intermediate_ be ? MoveRelativeZonedDateTime(_zonedRelativeTo_, _calendarRec_, _timeZoneRec_, _unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], 0, _precalculatedPlainDateTime_). - 1. Let _norm_ be NormalizeTimeDuration(_duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]]). - 1. Let _startNs_ be _intermediate_.[[Nanoseconds]]. - 1. Let _startInstant_ be ! CreateTemporalInstant(_startNs_). - 1. Let _startDateTime_ be *undefined*. - 1. If _days_ ≠ 0, then - 1. Set _startDateTime_ to ? GetPlainDateTimeFor(_timeZoneRec_, _startInstant_, *"iso8601"*). - 1. Let _addResult_ be ? AddDaysToZonedDateTime(_startInstant_, _startDateTime_, _timeZoneRec_, *"iso8601"*, _days_). - 1. Let _intermediateNs_ be _addResult_.[[EpochNanoseconds]]. - 1. Else, - 1. Let _intermediateNs_ be _startNs_. - 1. Let _endNs_ be ? AddInstant(_intermediateNs_, _norm_). - 1. Set _norm_ to NormalizedTimeDurationFromEpochNanosecondsDifference(_endNs_, _startNs_). - 1. If IsCalendarUnit(_unit_) is *true* or _unit_ is *"day"*, then - 1. If NormalizedTimeDurationIsZero(_norm_) is *false* and _startDateTime_ is *undefined*, set _startDateTime_ to ? GetPlainDateTimeFor(_timeZoneRec_, _startInstant_, *"iso8601"*). - 1. Let _result_ be ? NormalizedTimeDurationToDays(_norm_, _intermediate_, _timeZoneRec_, _startDateTime_). - 1. Set _norm_ to _result_.[[Remainder]]. - 1. Set _days_ to _result_.[[Days]]. - 1. Else, - 1. Set _days_ to 0. + 1. Let _relativeEpochNs_ be _zonedRelativeTo_.[[Nanoseconds]]. + 1. Let _relativeInstant_ be ! CreateTemporalInstant(_relativeEpochNs_). + 1. Let _targetEpochNs_ be ? AddZonedDateTime(_relativeInstant_, _timeZoneRec_, _calendarRec_, _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _norm_, _precalculatedPlainDateTime_). + 1. Let _roundRecord_ be ? DifferenceZonedDateTimeWithRounding(_relativeEpochNs_, _targetEpochNs_, _plainRelativeTo_, _calendarRec_, _zonedRelativeTo_, _timeZoneRec_, _precalculatedPlainDateTime_, _emptyOptions_, _unit_, 1, _unit_, *"trunc"*). + 1. Else if _plainRelativeTo_ is not *undefined*, then + 1. Let _targetTime_ be AddTime(0, 0, 0, 0, 0, 0, _norm_). + 1. Let _dateDuration_ be ? CreateTemporalDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]] + _targetTime_.[[Days]], 0, 0, 0, 0, 0, 0). + 1. Let _targetDate_ be ? AddDate(_calendarRec_, _plainRelativeTo_, _dateDuration_). + 1. Let _roundRecord_ be ? DifferencePlainDateTimeWithRounding(_plainRelativeTo_, 0, 0, 0, 0, 0, 0, _targetDate_.[[ISOYear]], _targetDate_.[[ISOMonth]], _targetDate_.[[ISODay]], _targetTime_.[[Hours]], _targetTime_.[[Minutes]], _targetTime_.[[Seconds]], _targetTime_.[[Milliseconds]], _targetTime_.[[Microseconds]], _targetTime_.[[Nanoseconds]], _calendarRec_, _unit_, 1, _unit_, *"trunc"*, _emptyOptions_). 1. Else, - 1. Let _norm_ be NormalizeTimeDuration(_duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]]). - 1. Set _norm_ to ? Add24HourDaysToNormalizedTimeDuration(_norm_, _days_). - 1. Set _days_ to 0. - 1. Let _roundRecord_ be ? RoundDuration(_unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], _days_, _norm_, 1, _unit_, *"trunc"*, _plainRelativeTo_, _calendarRec_, _zonedRelativeTo_, _timeZoneRec_, _precalculatedPlainDateTime_). + 1. If _duration_.[[Years]] ≠ 0, or _duration_.[[Months]] ≠ 0, or _duration_.[[Weeks]] ≠ 0, or IsCalendarUnit(_unit_) is *true*, throw a *RangeError* exception. + 1. Let _normWithDays_ be ? Add24HourDaysToNormalizedTimeDuration(_duration_.[[Days]], _norm_). + 1. Let _roundRecord_ be ? RoundDuration(0, 0, 0, 0, _normWithDays_, 1, _unit_, *"trunc"*). 1. Return 𝔽(_roundRecord_.[[Total]]). @@ -1727,40 +1722,17 @@

_months_: an integer, _weeks_: an integer, _days_: an integer, - _largestUnit_: a String, - _plainRelativeTo_: *undefined* or a Temporal.PlainDate, - _calendarRec_: *undefined* or a Calendar Methods Record, - ) + _plainRelativeTo_: a Temporal.PlainDate, + _calendarRec_: a Calendar Methods Record, + ): either a normal completion containing an integer or a throw completion

description
-
It converts the calendar units of a duration into a form where no unit is larger than _largestUnit_, and returns the result as a Date Duration Record.
+
It converts the calendar units of a duration into a number of days, and returns the result.
- 1. Assert: If _plainRelativeTo_ is not *undefined*, _calendarRec_ is not *undefined*. - 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. Assert: _effectiveLargestUnit_ is not *"year"*. - 1. If _calendarRec_ is *undefined*, then - 1. Throw a *RangeError* exception. + 1. If _years_ = 0 and _months_ = 0 and _weeks_ = 0, return _days_. 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_). - 1. Let _untilOptions_ be OrdinaryObjectCreate(*null*). - 1. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"month"*). - 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 _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. 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_). @@ -1777,8 +1749,8 @@

_days_: an integer, _largestUnit_: a String, _smallestUnit_: a String, - _plainRelativeTo_: *undefined* or a Temporal.PlainDate, - _calendarRec_: *undefined* or a Calendar Methods Record, + _plainRelativeTo_: a Temporal.PlainDate, + _calendarRec_: a Calendar Methods Record, ): either a normal completion containing a Date Duration Record or a throw completion

@@ -1786,13 +1758,10 @@

It converts the calendar units of a duration into a form where lower units are converted into higher units as much as possible, up to _largestUnit_ and not lower than _smallestUnit_, and returns the result as a Date Duration Record.

- 1. Assert: If _plainRelativeTo_ is not *undefined*, _calendarRec_ is not *undefined*. 1. Let _allZero_ be *false*. 1. If _years_ = 0, and _months_ = 0, and _weeks_ = 0, and _days_ = 0, set _allZero_ to *true*. 1. If _largestUnit_ is not one of *"year"*, *"month"*, or *"week"*, or _allZero_ is *true*, then 1. Return ! CreateDateDurationRecord(_years_, _months_, _weeks_, _days_). - 1. If _plainRelativeTo_ 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 _untilOptions_ be OrdinaryObjectCreate(*null*). diff --git a/spec/instant.html b/spec/instant.html index 1a56503b7f..8c9690b365 100644 --- a/spec/instant.html +++ b/spec/instant.html @@ -590,7 +590,7 @@

_roundingIncrement_: a positive integer, _smallestUnit_: a String, _roundingMode_: a String from the "Identifier" column of , - ): a Normalized Time Duration Record + ): a Record with fields [[NormalizedTimeDuration]] (a Normalized Time Duration Record) and [[Total]] (a mathematical value)

description
@@ -598,10 +598,8 @@

1. Let _difference_ be NormalizedTimeDurationFromEpochNanosecondsDifference(_ns2_, _ns1_). - 1. If _smallestUnit_ is *"nanosecond"* and _roundingIncrement_ is 1, then - 1. Return _difference_. 1. Let _roundRecord_ be ! RoundDuration(0, 0, 0, 0, _difference_, _roundingIncrement_, _smallestUnit_, _roundingMode_). - 1. Return _roundRecord_.[[NormalizedDuration]].[[NormalizedTime]]. + 1. Return the Record { [[NormalizedTimeDuration]]: _roundRecord_.[[NormalizedDuration]].[[NormalizedTime]], [[Total]]: _roundRecord_.[[Total]] }. @@ -671,7 +669,8 @@

1. Set _other_ to ? ToTemporalInstant(_other_). 1. Let _resolvedOptions_ be ? SnapshotOwnProperties(? GetOptionsObject(_options_), *null*). 1. Let _settings_ be ? GetDifferenceSettings(_operation_, _resolvedOptions_, ~time~, « », *"nanosecond"*, *"second"*). - 1. Let _norm_ be DifferenceInstant(_instant_.[[Nanoseconds]], _other_.[[Nanoseconds]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]]). + 1. Let _diffRecord_ be DifferenceInstant(_instant_.[[Nanoseconds]], _other_.[[Nanoseconds]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]]). + 1. Let _norm_ be _diffRecord_.[[NormalizedTimeDuration]]. 1. Let _result_ be BalanceTimeDuration(_norm_, _settings_.[[LargestUnit]]). 1. Return ! CreateTemporalDuration(0, 0, 0, 0, _sign_ × _result_.[[Hours]], _sign_ × _result_.[[Minutes]], _sign_ × _result_.[[Seconds]], _sign_ × _result_.[[Milliseconds]], _sign_ × _result_.[[Microseconds]], _sign_ × _result_.[[Nanoseconds]]). diff --git a/spec/plaindatetime.html b/spec/plaindatetime.html index 18711cfc17..9767f4db43 100644 --- a/spec/plaindatetime.html +++ b/spec/plaindatetime.html @@ -1348,7 +1348,67 @@

1. Let _untilOptions_ be ! SnapshotOwnProperties(_options_, *null*). 1. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, _dateLargestUnit_). 1. Let _dateDifference_ be ? DifferenceDate(_calendarRec_, _date1_, _date2_, _untilOptions_). - 1. Return ? CreateNormalizedDurationRecord(_dateDifference_.[[Years]], _dateDifference_.[[Months]], _dateDifference_.[[Weeks]], _dateDifference_.[[Days]], _timeDuration_). + 1. Let _days_ be _dateDifference_.[[Days]]. + 1. If _largestUnit_ is not _dateLargestUnit_, then + 1. Set _timeDuration_ to ? Add24HourDaysToNormalizedTimeDuration(_dateDifference_.[[Days]], _timeDuration_). + 1. Set _days_ to 0. + 1. Return ? CreateNormalizedDurationRecord(_dateDifference_.[[Years]], _dateDifference_.[[Months]], _dateDifference_.[[Weeks]], _days_, _timeDuration_). + + + + +

+ DifferencePlainDateTimeWithRounding ( + _plainDate1_: a Temporal.PlainDate, + _h1_: an integer in the inclusive interval from 0 to 23, + _min1_: an integer in the inclusive interval from 0 to 59, + _s1_: an integer in the inclusive interval from 0 to 59, + _ms1_: an integer in the inclusive interval from 0 to 999, + _mus1_: an integer in the inclusive interval from 0 to 999, + _ns1_: an integer in the inclusive interval from 0 to 999, + _y2_: an integer, + _mon2_: an integer, + _d2_: an integer, + _h2_: an integer in the inclusive interval from 0 to 23, + _min2_: an integer in the inclusive interval from 0 to 59, + _s2_: an integer in the inclusive interval from 0 to 59, + _ms2_: an integer in the inclusive interval from 0 to 999, + _mus2_: an integer in the inclusive interval from 0 to 999, + _ns2_: an integer in the inclusive interval from 0 to 999, + _calendarRec_: a Calendar Methods Record, + _largestUnit_: a String etc, + _roundingIncrement_: an integer, + _smallestUnit_: a String, + _roundingMode_: a String, + _resolvedOptions_: an Object with [[Prototype]] slot *null*, + ): either a normal completion containing a Record with fields [[DurationRecord]] (a Duration Record) and [[Total]] (a mathematical value), or a throw completion +

+
+
description
+
+
+ + 1. Assert: IsValidISODate(_y2_, _mon2_, _d2_) is *true*. + 1. Let _y1_ be _plainDate1_.[[ISOYear]]. + 1. Let _mon1_ be _plainDate1_.[[ISOMonth]]. + 1. Let _d1_ be _plainDate1_.[[ISODay]]. + 1. If CompareISODateTime(_y1_, _mon1_, _d1_, _h1_, _min1_, _s1_, _ms1_, _mus1_, _ns1_, _y2_, _mon2_, _d2_, _h2_, _min2_, _s2_, _ms2_, _mus2_, _ns2_) = 0, then + 1. Let _durationRecord_ be CreateDurationRecord(0, 0, 0, 0, 0, 0, 0, 0, 0, 0). + 1. Return the Record { [[DurationRecord]]: _durationRecord_, [[Total]]: 0 }. + 1. Let _diff_ be ? DifferenceISODateTime(_y1_, _mon1_, _d1_, _h1_, _min1_, _s1_, _ms1_, _mus1_, _ns1_, _y2_, _mon2_, _d2_, _h2_, _min2_, _s2_, _ms2_, _mus2_, _ns2_, _calendarRec_, _largestUnit_, _resolvedOptions_). + 1. If _smallestUnit_ is *"nanosecond"* and _roundingIncrement_ = 1, then + 1. Let _normWithDays_ be ? Add24HourDaysToNormalizedTimeDuration(_diff_.[[NormalizedTime]], _diff_.[[Days]]). + 1. Let _timeResult_ be BalanceTimeDuration(_normWithDays_, _largestUnit_). + 1. Let _total_ be NormalizedTimeDurationSeconds(_normWithDays_) × 109 + NormalizedTimeDurationSubseconds(_normWithDays_). + 1. Let _durationRecord_ be CreateDurationRecord(_diff_.[[Years]], _diff_.[[Months]], _diff_.[[Weeks]], _timeResult_.[[Days]], _timeResult_.[[Hours]], _timeResult_.[[Minutes]], _timeResult_.[[Seconds]], _timeResult_.[[Milliseconds]], _timeResult_.[[Microseconds]], _timeResult_.[[Nanoseconds]]). + 1. Return the Record { [[DurationRecord]]: _durationRecord_, [[Total]]: _total_ }. + 1. Let _roundRecord_ be ? RoundDuration(_diff_.[[Years]], _diff_.[[Months]], _diff_.[[Weeks]], _diff_.[[Days]], _diff_.[[NormalizedTime]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _plainDate1_, _calendarRec_). + 1. Let _roundResult_ be _roundRecord_.[[NormalizedDuration]]. + 1. Let _normWithDays_ be ? Add24HourDaysToNormalizedTimeDuration(_roundResult_.[[NormalizedTime]], _roundResult_.[[Days]]). + 1. Let _timeResult_ be BalanceTimeDuration(_normWithDays_, _largestUnit_). + 1. Let _balanceResult_ be ? BalanceDateDurationRelative(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _timeResult_.[[Days]], _largestUnit_, _smallestUnit_, _plainDate1_, _calendarRec_). + 1. Let _durationRecord_ be CreateDurationRecord(_balanceResult_.[[Years]], _balanceResult_.[[Months]], _balanceResult_.[[Weeks]], _balanceResult_.[[Days]], _timeResult_.[[Hours]], _timeResult_.[[Minutes]], _timeResult_.[[Seconds]], _timeResult_.[[Milliseconds]], _timeResult_.[[Microseconds]], _timeResult_.[[Nanoseconds]]). + 1. Return the Record { [[DurationRecord]]: _durationRecord_, [[Total]]: _roundRecord_.[[Total]] }.
@@ -1376,21 +1436,11 @@

1. Set _datePartsIdentical_ to *true*. 1. If _datePartsIdentical_ is *true*, and _dateTime_.[[ISOHour]] = _other_.[[ISOHour]], and _dateTime_.[[ISOMinute]] = _other_.[[ISOMinute]], and _dateTime_.[[ISOSecond]] = _other_.[[ISOSecond]], and _dateTime_.[[ISOMillisecond]] = _other_.[[ISOMillisecond]], and _dateTime_.[[ISOMicrosecond]] = _other_.[[ISOMicrosecond]], and _dateTime_.[[ISONanosecond]] = _other_.[[ISONanosecond]], then 1. Return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0). + 1. Let _plainDate_ be ! CreateTemporalDate(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[Calendar]]). 1. Let _calendarRec_ be ? CreateCalendarMethodsRecord(_dateTime_.[[Calendar]], « ~date-add~, ~date-until~ »). - 1. Let _result_ be ? DifferenceISODateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _other_.[[ISOYear]], _other_.[[ISOMonth]], _other_.[[ISODay]], _other_.[[ISOHour]], _other_.[[ISOMinute]], _other_.[[ISOSecond]], _other_.[[ISOMillisecond]], _other_.[[ISOMicrosecond]], _other_.[[ISONanosecond]], _calendarRec_, _settings_.[[LargestUnit]], _resolvedOptions_). - 1. If _settings_.[[SmallestUnit]] is *"nanosecond"* and _settings_.[[RoundingIncrement]] = 1, let _roundingGranularityIsNoop_ be *true*; else let _roundingGranularityIsNoop_ be *false*. - 1. If _roundingGranularityIsNoop_ is *false*, then - 1. Let _relativeTo_ be ! CreateTemporalDate(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[Calendar]]). - 1. Let _roundRecord_ be ? RoundDuration(_result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _result_.[[Days]], _result_.[[NormalizedTime]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]], _relativeTo_, _calendarRec_). - 1. Let _roundResult_ be _roundRecord_.[[NormalizedDuration]]. - 1. Let _normWithDays_ be ? Add24HourDaysToNormalizedTimeDuration(_roundResult_.[[NormalizedTime]], _roundResult_.[[Days]]). - 1. Let _timeResult_ be BalanceTimeDuration(_normWithDays_, _settings_.[[LargestUnit]]). - 1. Let _balanceResult_ be ? BalanceDateDurationRelative(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _timeResult_.[[Days]], _settings_.[[LargestUnit]], _settings_.[[SmallestUnit]], _relativeTo_, _calendarRec_). - 1. Else, - 1. Let _normWithDays_ be ? Add24HourDaysToNormalizedTimeDuration(_result_.[[NormalizedTime]], _result_.[[Days]]). - 1. Let _timeResult_ be BalanceTimeDuration(_normWithDays_, _settings_.[[LargestUnit]]). - 1. Let _balanceResult_ be ! CreateDateDurationRecord(_result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _timeResult_.[[Days]]). - 1. Return ? CreateTemporalDuration(_sign_ × _balanceResult_.[[Years]], _sign_ × _balanceResult_.[[Months]], _sign_ × _balanceResult_.[[Weeks]], _sign_ × _balanceResult_.[[Days]], _sign_ × _timeResult_.[[Hours]], _sign_ × _timeResult_.[[Minutes]], _sign_ × _timeResult_.[[Seconds]], _sign_ × _timeResult_.[[Milliseconds]], _sign_ × _timeResult_.[[Microseconds]], _sign_ × _timeResult_.[[Nanoseconds]]). + 1. Let _resultRecord_ be ? DifferencePlainDateTimeWithRounding(_plainDate_, _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _other_.[[ISOYear]], _other_.[[ISOMonth]], _other_.[[ISODay]], _other_.[[ISOHour]], _other_.[[ISOMinute]], _other_.[[ISOSecond]], _other_.[[ISOMillisecond]], _other_.[[ISOMicrosecond]], _other_.[[ISONanosecond]], _calendarRec_, _settings_.[[LargestUnit]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]], _resolvedOptions_). + 1. Let _result_ be _resultRecord_.[[DurationRecord]]. + 1. Return ? CreateTemporalDuration(_sign_ × _result_.[[Years]], _sign_ × _result_.[[Months]], _sign_ × _result_.[[Weeks]], _sign_ × _result_.[[Days]], _sign_ × _result_.[[Hours]], _sign_ × _result_.[[Minutes]], _sign_ × _result_.[[Seconds]], _sign_ × _result_.[[Milliseconds]], _sign_ × _result_.[[Microseconds]], _sign_ × _result_.[[Nanoseconds]]). diff --git a/spec/zoneddatetime.html b/spec/zoneddatetime.html index 53ef405013..972f410019 100644 --- a/spec/zoneddatetime.html +++ b/spec/zoneddatetime.html @@ -1541,6 +1541,52 @@

+ +

+ DifferenceZonedDateTimeWithRounding ( + _ns1_: a BigInt, + _ns2_: a BigInt, + _plainRelativeTo_: a Temporal.PlainDate, + _calendarRec_: a Calendar Methods Record, + _zonedDateTime_: a Temporal.ZonedDateTime, + _timeZoneRec_: a Time Zone Methods Record, + _precalculatedPlainDateTime_: a Temporal.PlainDateTime, + _resolvedOptions_: an Object with [[Prototype]] slot *null*, + _largestUnit_: a String, + _roundingIncrement_: an integer, + _smallestUnit_: a String, + _roundingMode_: a String, + ): either a normal completion containing a Record with fields [[DurationRecord]] (a Duration Record) and [[Total]] (a mathematical value), or a throw completion +

+
+
description
+
+
+ + 1. If IsCalendarUnit(_largestUnit_) is *false* and _largestUnit_ is not *"day"*, then + 1. Let _diffRecord_ be DifferenceInstant(_ns1_, _ns2_, _roundingIncrement_, _smallestUnit_, _roundingMode_). + 1. Let _norm_ be _diffRecord_.[[NormalizedTimeDuration]]. + 1. Let _result_ be BalanceTimeDuration(_norm_, _largestUnit_). + 1. Let _durationRecord_ be CreateDurationRecord(0, 0, 0, 0, _result_.[[Hours]], _result_.[[Minutes]], _result_.[[Seconds]], _result_.[[Milliseconds]], _result_.[[Microseconds]], _result_.[[Nanoseconds]]). + 1. Return the Record { [[DurationRecord]]: _durationRecord_, [[Total]]: _diffRecord_.[[Total]] }. + 1. Let _difference_ be ? DifferenceZonedDateTime(_ns1_, _ns2_, _timeZoneRec_, _calendarRec_, _largestUnit_, _resolvedOptions_, _precalculatedPlainDateTime_). + 1. If _smallestUnit_ is *"nanosecond"* and _roundingIncrement_ is 1, let _roundingGranularityIsNoop_ be *true*; else let _roundingGranularityIsNoop_ be *false*. + 1. If _roundingGranularityIsNoop_ is *true*, then + 1. Let _timeResult_ be BalanceTimeDuration(_difference_.[[NormalizedTime]], *"hour"*). + 1. Let _total_ be NormalizedTimeDurationSeconds(_difference_.[[NormalizedTime]]) × 109 + NormalizedTimeDurationSubseconds(_difference_.[[NormalizedTime]]). + 1. Let _durationRecord_ be CreateDurationRecord(_difference_.[[Years]], _difference_.[[Months]], _difference_.[[Weeks]], _difference_.[[Days]], _timeResult_.[[Hours]], _timeResult_.[[Minutes]], _timeResult_.[[Seconds]], _timeResult_.[[Milliseconds]], _timeResult_.[[Microseconds]], _timeResult_.[[Nanoseconds]]). + 1. Return the Record { [[DurationRecord]]: _durationRecord_, [[Total]]: _total_ }. + 1. Let _roundRecord_ be ? RoundDuration(_difference_.[[Years]], _difference_.[[Months]], _difference_.[[Weeks]], _difference_.[[Days]], _difference_.[[NormalizedTime]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _plainRelativeTo_, _calendarRec_, _zonedDateTime_, _timeZoneRec_, _precalculatedPlainDateTime_). + 1. Let _roundResult_ be _roundRecord_.[[NormalizedDuration]]. + 1. Let _adjustResult_ be ? AdjustRoundedDurationDays(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _roundResult_.[[Days]], _roundResult_.[[NormalizedTime]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _zonedDateTime_, _calendarRec_, _timeZoneRec_, _precalculatedPlainDateTime_). + 1. Let _balanceResult_ be ? BalanceDateDurationRelative(_adjustResult_.[[Years]], _adjustResult_.[[Months]], _adjustResult_.[[Weeks]], _adjustResult_.[[Days]], _largestUnit_, _smallestUnit_, _plainRelativeTo_, _calendarRec_). + 1. Set _result_ to ? CombineDateAndNormalizedTimeDuration(_balanceResult_, _adjustResult_.[[NormalizedTime]]). + 1. Let _timeResult_ be BalanceTimeDuration(_result_.[[NormalizedTime]], *"hour"*). + 1. Let _durationRecord_ be CreateDurationRecord(_result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _result_.[[Days]], _timeResult_.[[Hours]], _timeResult_.[[Minutes]], _timeResult_.[[Seconds]], _timeResult_.[[Milliseconds]], _timeResult_.[[Microseconds]], _timeResult_.[[Nanoseconds]]). + 1. Return the Record { [[DurationRecord]]: _durationRecord_, [[Total]]: _roundRecord_.[[Total]] }. + +
+

DifferenceTemporalZonedDateTime ( @@ -1562,7 +1608,8 @@

1. Let _resolvedOptions_ be ? SnapshotOwnProperties(? GetOptionsObject(_options_), *null*). 1. Let _settings_ be ? GetDifferenceSettings(_operation_, _resolvedOptions_, ~datetime~, « », *"nanosecond"*, *"hour"*). 1. If _settings_.[[LargestUnit]] is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then - 1. Let _norm_ be DifferenceInstant(_zonedDateTime_.[[Nanoseconds]], _other_.[[Nanoseconds]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]]). + 1. Let _diffRecord_ be DifferenceInstant(_zonedDateTime_.[[Nanoseconds]], _other_.[[Nanoseconds]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]]). + 1. Let _norm_ be _diffRecord_.[[NormalizedTimeDuration]]. 1. Let _result_ be BalanceTimeDuration(_norm_, _settings_.[[LargestUnit]]). 1. Return ! CreateTemporalDuration(0, 0, 0, 0, _sign_ × _result_.[[Hours]], _sign_ × _result_.[[Minutes]], _sign_ × _result_.[[Seconds]], _sign_ × _result_.[[Milliseconds]], _sign_ × _result_.[[Microseconds]], _sign_ × _result_.[[Nanoseconds]]). 1. NOTE: To calculate differences in two different time zones, _settings_.[[LargestUnit]] must be *"hour"* or smaller, because day lengths can vary between time zones due to DST and other UTC offset shifts. @@ -1575,18 +1622,9 @@

1. Let _instant_ be ! CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]). 1. Let _precalculatedPlainDateTime_ be ? GetPlainDateTimeFor(_timeZoneRec_, _instant_, _calendarRec_.[[Receiver]]). 1. Let _plainRelativeTo_ be ! CreateTemporalDate(_precalculatedPlainDateTime_.[[ISOYear]], _precalculatedPlainDateTime_.[[ISOMonth]], _precalculatedPlainDateTime_.[[ISODay]], _calendarRec_.[[Receiver]]). - 1. Let _result_ be ? DifferenceZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _other_.[[Nanoseconds]], _timeZoneRec_, _calendarRec_, _settings_.[[LargestUnit]], _resolvedOptions_, _precalculatedPlainDateTime_). - 1. If _settings_.[[SmallestUnit]] is *"nanosecond"* and _settings_.[[RoundingIncrement]] is 1, let _roundingGranularityIsNoop_ be *true*; else let _roundingGranularityIsNoop_ be *false*. - 1. If _roundingGranularityIsNoop_ is *false*, then - 1. Let _roundRecord_ be ? RoundDuration(_result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _result_.[[Days]], _result_.[[NormalizedTime]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]], _plainRelativeTo_, _calendarRec_, _zonedDateTime_, _timeZoneRec_, _precalculatedPlainDateTime_). - 1. Let _roundResult_ be _roundRecord_.[[NormalizedDuration]]. - 1. Let _daysResult_ be ! NormalizedTimeDurationToDays(_roundResult_.[[NormalizedTime]], _zonedDateTime_, _timeZoneRec_). - 1. Let _days_ be _roundResult_.[[Days]] + _daysResult_.[[Days]]. - 1. Let _adjustResult_ be ? AdjustRoundedDurationDays(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _days_, _daysResult_.[[NormalizedTime]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]], _zonedDateTime_, _calendarRec_, _timeZoneRec_, _precalculatedPlainDateTime_). - 1. Let _balanceResult_ be ? BalanceDateDurationRelative(_adjustResult_.[[Years]], _adjustResult_.[[Months]], _adjustResult_.[[Weeks]], _adjustResult_.[[Days]], _settings_.[[LargestUnit]], _settings_.[[SmallestUnit]], _plainRelativeTo_, _calendarRec_). - 1. Set _result_ to ? CombineDateAndNormalizedTimeDuration(_balanceResult_, _adjustResult_.[[NormalizedTime]]). - 1. Let _timeResult_ be BalanceTimeDuration(_result_.[[NormalizedTime]], *"hour"*). - 1. Return ! CreateTemporalDuration(_sign_ × _result_.[[Years]], _sign_ × _result_.[[Months]], _sign_ × _result_.[[Weeks]], _sign_ × _result_.[[Days]], _sign_ × _timeResult_.[[Hours]], _sign_ × _timeResult_.[[Minutes]], _sign_ × _timeResult_.[[Seconds]], _sign_ × _timeResult_.[[Milliseconds]], _sign_ × _timeResult_.[[Microseconds]], _sign_ × _timeResult_.[[Nanoseconds]]). + 1. Let _resultRecord_ be ? DifferenceZonedDateTimeWithRounding(_zonedDateTime_.[[Nanoseconds]], _other_.[[Nanoseconds]], _plainRelativeTo_, _calendarRec_, _zonedDateTime_, _timeZoneRec_, _precalculatedPlainDateTime_, _resolvedOptions_, _settings_.[[LargestUnit]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]]). + 1. Let _result_ be _resultRecord_.[[DurationRecord]]. + 1. Return ! CreateTemporalDuration(_sign_ × _result_.[[Years]], _sign_ × _result_.[[Months]], _sign_ × _result_.[[Weeks]], _sign_ × _result_.[[Days]], _sign_ × _result_.[[Hours]], _sign_ × _result_.[[Minutes]], _sign_ × _result_.[[Seconds]], _sign_ × _result_.[[Milliseconds]], _sign_ × _result_.[[Microseconds]], _sign_ × _result_.[[Nanoseconds]]).