From b4ffe4cb7c1cc04ae0aeef765ae9b5442397faa2 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Tue, 7 Mar 2023 14:31:47 -0800 Subject: [PATCH] Normative: Separate zoned and plain operations in RoundDuration This converts a ZonedDateTime relativeTo into a PlainDateTime relativeTo only when necessary, only after potentially throwing other errors, and only once. Previously, it could be converted up to a few separate times in each operation, such as UnbalanceDurationRelative, RoundDuration, and BalanceDurationRelative. Since the conversion is user-visible, we don't want to perform it when not necessary or perform it more times than necessary. Closes: #2247 Closes: #2529 --- polyfill/lib/duration.mjs | 90 +++++++++---- polyfill/lib/ecmascript.mjs | 256 +++++++++++++++++++++++------------- spec/duration.html | 202 +++++++++++++++------------- spec/zoneddatetime.html | 26 ++-- 4 files changed, 355 insertions(+), 219 deletions(-) diff --git a/polyfill/lib/duration.mjs b/polyfill/lib/duration.mjs index e8d9c5a352..5fd650a036 100644 --- a/polyfill/lib/duration.mjs +++ b/polyfill/lib/duration.mjs @@ -268,12 +268,15 @@ export class Duration { const maximum = maximumIncrements[smallestUnit]; if (maximum !== undefined) ES.ValidateTemporalRoundingIncrement(roundingIncrement, maximum, false); + let zonedRelativeTo = ES.IsTemporalZonedDateTime(relativeTo) ? relativeTo : undefined; + let plainRelativeTo = ES.IsTemporalDate(relativeTo) ? relativeTo : undefined; + const roundingGranularityIsNoop = smallestUnit === 'nanosecond' && roundingIncrement === 1; const balancingRequested = largestUnit !== existingLargestUnit; const calendarUnitsPresent = years !== 0 || months !== 0 || weeks !== 0; const timeUnitsOverflowWillOccur = minutes >= 60 || seconds >= 60 || milliseconds >= 1000 || microseconds >= 1000 || nanoseconds >= 1000; - const hoursToDaysConversionMayOccur = (days !== 0 && ES.IsTemporalZonedDateTime(relativeTo)) || hours >= 24; + const hoursToDaysConversionMayOccur = (days !== 0 && zonedRelativeTo) || hours >= 24; if ( roundingGranularityIsNoop && !balancingRequested && @@ -284,13 +287,27 @@ export class Duration { return new Duration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds); } + const plainRelativeToWillBeUsed = + smallestUnit === 'year' || + smallestUnit === 'month' || + smallestUnit === 'week' || + years !== 0 || + months !== 0 || + weeks !== 0 || + days !== 0; + if (zonedRelativeTo && plainRelativeToWillBeUsed) { + // Convert a ZonedDateTime relativeTo to PlainDate only if needed in one + // of the operations below, because the conversion is user visible + plainRelativeTo = ES.ToTemporalDate(zonedRelativeTo); + } + ({ years, months, weeks, days } = ES.UnbalanceDurationRelative( years, months, weeks, days, largestUnit, - relativeTo + plainRelativeTo )); ({ years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.RoundDuration( @@ -307,25 +324,28 @@ export class Duration { roundingIncrement, smallestUnit, roundingMode, - relativeTo - )); - ({ years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = - ES.AdjustRoundedDurationDays( - years, - months, - weeks, - days, - hours, - minutes, - seconds, - milliseconds, - microseconds, - nanoseconds, - roundingIncrement, - smallestUnit, - roundingMode, - relativeTo + plainRelativeTo, + zonedRelativeTo )); + if (zonedRelativeTo) { + ({ years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = + ES.AdjustRoundedDurationDays( + years, + months, + weeks, + days, + hours, + minutes, + seconds, + milliseconds, + microseconds, + nanoseconds, + roundingIncrement, + smallestUnit, + roundingMode, + zonedRelativeTo + )); + } ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.BalanceDuration( days, hours, @@ -335,9 +355,16 @@ export class Duration { microseconds, nanoseconds, largestUnit, - relativeTo + zonedRelativeTo + )); + ({ years, months, weeks, days } = ES.BalanceDurationRelative( + years, + months, + weeks, + days, + largestUnit, + plainRelativeTo )); - ({ years, months, weeks, days } = ES.BalanceDurationRelative(years, months, weeks, days, largestUnit, relativeTo)); return new Duration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds); } @@ -365,12 +392,22 @@ export class Duration { const relativeTo = ES.ToRelativeTemporalObject(totalOf); const unit = ES.GetTemporalUnit(totalOf, 'unit', 'datetime', ES.REQUIRED); + let zonedRelativeTo = ES.IsTemporalZonedDateTime(relativeTo) ? relativeTo : undefined; + let plainRelativeTo = ES.IsTemporalDate(relativeTo) ? relativeTo : undefined; + const plainRelativeToWillBeUsed = + unit === 'year' || unit === 'month' || unit === 'week' || years !== 0 || months !== 0 || weeks !== 0; + if (zonedRelativeTo !== undefined && plainRelativeToWillBeUsed) { + // Convert a ZonedDateTime relativeTo to PlainDate only if needed in one + // of the operations below, because the conversion is user visible + plainRelativeTo = ES.ToTemporalDate(zonedRelativeTo); + } + // Convert larger units down to days - ({ years, months, weeks, days } = ES.UnbalanceDurationRelative(years, months, weeks, days, unit, relativeTo)); + ({ years, months, weeks, days } = ES.UnbalanceDurationRelative(years, months, weeks, days, unit, plainRelativeTo)); // If the unit we're totalling is smaller than `days`, convert days down to that unit. let intermediate; - if (ES.IsTemporalZonedDateTime(relativeTo)) { - intermediate = ES.MoveRelativeZonedDateTime(relativeTo, years, months, weeks, 0); + if (zonedRelativeTo) { + intermediate = ES.MoveRelativeZonedDateTime(zonedRelativeTo, years, months, weeks, 0); } let balanceResult = ES.BalancePossiblyInfiniteDuration( days, @@ -404,7 +441,8 @@ export class Duration { 1, unit, 'trunc', - relativeTo + plainRelativeTo, + zonedRelativeTo ); return total; } diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs index b42e25c834..e9c8ea546b 100644 --- a/polyfill/lib/ecmascript.mjs +++ b/polyfill/lib/ecmascript.mjs @@ -3031,25 +3031,25 @@ export function TotalDurationNanoseconds( return bigInt(nanoseconds).add(microseconds.multiply(1000)); } -export function NanosecondsToDays(nanoseconds, relativeTo) { +export function NanosecondsToDays(nanoseconds, zonedRelativeTo) { const TemporalInstant = GetIntrinsic('%Temporal.Instant%'); const sign = MathSign(nanoseconds); nanoseconds = bigInt(nanoseconds); let dayLengthNs = 86400e9; if (sign === 0) return { days: 0, nanoseconds: bigInt.zero, dayLengthNs }; - if (!IsTemporalZonedDateTime(relativeTo)) { + if (!zonedRelativeTo) { let days; ({ quotient: days, remainder: nanoseconds } = nanoseconds.divmod(dayLengthNs)); days = days.toJSNumber(); return { days, nanoseconds, dayLengthNs }; } - const startNs = GetSlot(relativeTo, EPOCHNANOSECONDS); - const start = GetSlot(relativeTo, INSTANT); + const startNs = GetSlot(zonedRelativeTo, EPOCHNANOSECONDS); + const start = GetSlot(zonedRelativeTo, INSTANT); const endNs = startNs.add(nanoseconds); const end = new TemporalInstant(endNs); - const timeZone = GetSlot(relativeTo, TIME_ZONE); - const calendar = GetSlot(relativeTo, CALENDAR); + const timeZone = GetSlot(zonedRelativeTo, TIME_ZONE); + const calendar = GetSlot(zonedRelativeTo, CALENDAR); // Find the difference in days only. const dtStart = GetPlainDateTimeFor(timeZone, start, calendar); @@ -3136,7 +3136,7 @@ export function BalanceDuration( microseconds, nanoseconds, largestUnit, - relativeTo = undefined + zonedRelativeTo = undefined ) { let result = BalancePossiblyInfiniteDuration( days, @@ -3147,7 +3147,7 @@ export function BalanceDuration( microseconds, nanoseconds, largestUnit, - relativeTo + zonedRelativeTo ); if (result === 'positive overflow' || result === 'negative overflow') { throw new RangeError('Duration out of range'); @@ -3165,13 +3165,13 @@ export function BalancePossiblyInfiniteDuration( microseconds, nanoseconds, largestUnit, - relativeTo = undefined + zonedRelativeTo = undefined ) { - if (IsTemporalZonedDateTime(relativeTo)) { + if (zonedRelativeTo) { const endNs = AddZonedDateTime( - GetSlot(relativeTo, INSTANT), - GetSlot(relativeTo, TIME_ZONE), - GetSlot(relativeTo, CALENDAR), + GetSlot(zonedRelativeTo, INSTANT), + GetSlot(zonedRelativeTo, TIME_ZONE), + GetSlot(zonedRelativeTo, CALENDAR), 0, 0, 0, @@ -3183,13 +3183,13 @@ export function BalancePossiblyInfiniteDuration( microseconds, nanoseconds ); - const startNs = GetSlot(relativeTo, EPOCHNANOSECONDS); + const startNs = GetSlot(zonedRelativeTo, EPOCHNANOSECONDS); nanoseconds = endNs.subtract(startNs); } else { nanoseconds = TotalDurationNanoseconds(days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, 0); } if (largestUnit === 'year' || largestUnit === 'month' || largestUnit === 'week' || largestUnit === 'day') { - ({ days, nanoseconds } = NanosecondsToDays(nanoseconds, relativeTo)); + ({ days, nanoseconds } = NanosecondsToDays(nanoseconds, zonedRelativeTo)); } else { days = 0; } @@ -3259,16 +3259,12 @@ export function BalancePossiblyInfiniteDuration( return { days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds }; } -export function UnbalanceDurationRelative(years, months, weeks, days, largestUnit, relativeTo) { +export function UnbalanceDurationRelative(years, months, weeks, days, largestUnit, plainRelativeTo) { const TemporalDuration = GetIntrinsic('%Temporal.Duration%'); const sign = DurationSign(years, months, weeks, days, 0, 0, 0, 0, 0, 0); if (sign === 0) return { years, months, weeks, days }; - let calendar; - if (relativeTo) { - relativeTo = ToTemporalDate(relativeTo); - calendar = GetSlot(relativeTo, CALENDAR); - } + const calendar = plainRelativeTo ? GetSlot(plainRelativeTo, CALENDAR) : undefined; const oneYear = new TemporalDuration(sign); const oneMonth = new TemporalDuration(0, sign); @@ -3286,6 +3282,7 @@ export function UnbalanceDurationRelative(years, months, weeks, days, largestUni break; case 'month': { + if (years.isZero()) break; if (!calendar) throw new RangeError('a starting point is required for months balancing'); // balance years down to months let dateAdd, dateUntil; @@ -3294,12 +3291,12 @@ export function UnbalanceDurationRelative(years, months, weeks, days, largestUni dateUntil = GetMethod(calendar, 'dateUntil'); } while (!years.isZero()) { - const newRelativeTo = CalendarDateAdd(calendar, relativeTo, oneYear, undefined, dateAdd); + const newRelativeTo = CalendarDateAdd(calendar, plainRelativeTo, oneYear, undefined, dateAdd); const untilOptions = ObjectCreate(null); untilOptions.largestUnit = 'month'; - const untilResult = CalendarDateUntil(calendar, relativeTo, newRelativeTo, untilOptions, dateUntil); + const untilResult = CalendarDateUntil(calendar, plainRelativeTo, newRelativeTo, untilOptions, dateUntil); const oneYearMonths = GetSlot(untilResult, MONTHS); - relativeTo = newRelativeTo; + plainRelativeTo = newRelativeTo; months = months.add(oneYearMonths); years = years.subtract(sign); } @@ -3307,12 +3304,18 @@ export function UnbalanceDurationRelative(years, months, weeks, days, largestUni break; case 'week': { + if (years.isZero() && months.isZero()) break; if (!calendar) throw new RangeError('a starting point is required for weeks balancing'); const dateAdd = typeof calendar !== 'string' ? GetMethod(calendar, 'dateAdd') : undefined; // balance years down to days while (!years.isZero()) { let oneYearDays; - ({ relativeTo, days: oneYearDays } = MoveRelativeDate(calendar, relativeTo, oneYear, dateAdd)); + ({ relativeTo: plainRelativeTo, days: oneYearDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneYear, + dateAdd + )); days = days.add(oneYearDays); years = years.subtract(sign); } @@ -3320,7 +3323,12 @@ export function UnbalanceDurationRelative(years, months, weeks, days, largestUni // balance months down to days while (!months.isZero()) { let oneMonthDays; - ({ relativeTo, days: oneMonthDays } = MoveRelativeDate(calendar, relativeTo, oneMonth, dateAdd)); + ({ relativeTo: plainRelativeTo, days: oneMonthDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneMonth, + dateAdd + )); days = days.add(oneMonthDays); months = months.subtract(sign); } @@ -3334,7 +3342,12 @@ export function UnbalanceDurationRelative(years, months, weeks, days, largestUni // balance years down to days while (!years.isZero()) { let oneYearDays; - ({ relativeTo, days: oneYearDays } = MoveRelativeDate(calendar, relativeTo, oneYear, dateAdd)); + ({ relativeTo: plainRelativeTo, days: oneYearDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneYear, + dateAdd + )); days = days.add(oneYearDays); years = years.subtract(sign); } @@ -3342,7 +3355,12 @@ export function UnbalanceDurationRelative(years, months, weeks, days, largestUni // balance months down to days while (!months.isZero()) { let oneMonthDays; - ({ relativeTo, days: oneMonthDays } = MoveRelativeDate(calendar, relativeTo, oneMonth, dateAdd)); + ({ relativeTo: plainRelativeTo, days: oneMonthDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneMonth, + dateAdd + )); days = days.add(oneMonthDays); months = months.subtract(sign); } @@ -3350,7 +3368,12 @@ export function UnbalanceDurationRelative(years, months, weeks, days, largestUni // balance weeks down to days while (!weeks.isZero()) { let oneWeekDays; - ({ relativeTo, days: oneWeekDays } = MoveRelativeDate(calendar, relativeTo, oneWeek, dateAdd)); + ({ relativeTo: plainRelativeTo, days: oneWeekDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneWeek, + dateAdd + )); days = days.add(oneWeekDays); weeks = weeks.subtract(sign); } @@ -3366,17 +3389,16 @@ export function UnbalanceDurationRelative(years, months, weeks, days, largestUni }; } -export function BalanceDurationRelative(years, months, weeks, days, largestUnit, relativeTo) { +export function BalanceDurationRelative(years, months, weeks, days, largestUnit, plainRelativeTo) { const TemporalDuration = GetIntrinsic('%Temporal.Duration%'); const sign = DurationSign(years, months, weeks, days, 0, 0, 0, 0, 0, 0); - if (sign === 0) return { years, months, weeks, days }; - - let calendar; - if (relativeTo) { - relativeTo = ToTemporalDate(relativeTo); - calendar = GetSlot(relativeTo, CALENDAR); + if (sign === 0 || (largestUnit !== 'year' && largestUnit !== 'month' && largestUnit !== 'week')) { + return { years, months, weeks, days }; } + if (!plainRelativeTo) throw new RangeError(`a starting point is required for ${largestUnit}s balancing`); + const calendar = GetSlot(plainRelativeTo, CALENDAR); + const oneYear = new TemporalDuration(sign); const oneMonth = new TemporalDuration(0, sign); const oneWeek = new TemporalDuration(0, 0, sign); @@ -3389,72 +3411,109 @@ export function BalanceDurationRelative(years, months, weeks, days, largestUnit, switch (largestUnit) { case 'year': { - if (!calendar) throw new RangeError('a starting point is required for years balancing'); const dateAdd = typeof calendar !== 'string' ? GetMethod(calendar, 'dateAdd') : undefined; // balance days up to years let newRelativeTo, oneYearDays; - ({ relativeTo: newRelativeTo, days: oneYearDays } = MoveRelativeDate(calendar, relativeTo, oneYear, dateAdd)); + ({ relativeTo: newRelativeTo, days: oneYearDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneYear, + dateAdd + )); while (days.abs().geq(MathAbs(oneYearDays))) { days = days.subtract(oneYearDays); years = years.add(sign); - relativeTo = newRelativeTo; - ({ relativeTo: newRelativeTo, days: oneYearDays } = MoveRelativeDate(calendar, relativeTo, oneYear, dateAdd)); + plainRelativeTo = newRelativeTo; + ({ relativeTo: newRelativeTo, days: oneYearDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneYear, + dateAdd + )); } // balance days up to months let oneMonthDays; - ({ relativeTo: newRelativeTo, days: oneMonthDays } = MoveRelativeDate(calendar, relativeTo, oneMonth, dateAdd)); + ({ relativeTo: newRelativeTo, days: oneMonthDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneMonth, + dateAdd + )); while (days.abs().geq(MathAbs(oneMonthDays))) { days = days.subtract(oneMonthDays); months = months.add(sign); - relativeTo = newRelativeTo; - ({ relativeTo: newRelativeTo, days: oneMonthDays } = MoveRelativeDate(calendar, relativeTo, oneMonth, dateAdd)); + plainRelativeTo = newRelativeTo; + ({ relativeTo: newRelativeTo, days: oneMonthDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneMonth, + dateAdd + )); } // balance months up to years - newRelativeTo = CalendarDateAdd(calendar, relativeTo, oneYear, undefined, dateAdd); + newRelativeTo = CalendarDateAdd(calendar, plainRelativeTo, oneYear, undefined, dateAdd); const dateUntil = typeof calendar !== 'string' ? GetMethod(calendar, 'dateUntil') : undefined; const untilOptions = ObjectCreate(null); untilOptions.largestUnit = 'month'; - let untilResult = CalendarDateUntil(calendar, relativeTo, newRelativeTo, untilOptions, dateUntil); + let untilResult = CalendarDateUntil(calendar, plainRelativeTo, newRelativeTo, untilOptions, dateUntil); let oneYearMonths = GetSlot(untilResult, MONTHS); while (months.abs().geq(MathAbs(oneYearMonths))) { months = months.subtract(oneYearMonths); years = years.add(sign); - relativeTo = newRelativeTo; - newRelativeTo = CalendarDateAdd(calendar, relativeTo, oneYear, undefined, dateAdd); + plainRelativeTo = newRelativeTo; + newRelativeTo = CalendarDateAdd(calendar, plainRelativeTo, oneYear, undefined, dateAdd); const untilOptions = ObjectCreate(null); untilOptions.largestUnit = 'month'; - untilResult = CalendarDateUntil(calendar, relativeTo, newRelativeTo, untilOptions, dateUntil); + untilResult = CalendarDateUntil(calendar, plainRelativeTo, newRelativeTo, untilOptions, dateUntil); oneYearMonths = GetSlot(untilResult, MONTHS); } break; } case 'month': { - if (!calendar) throw new RangeError('a starting point is required for months balancing'); const dateAdd = typeof calendar !== 'string' ? GetMethod(calendar, 'dateAdd') : undefined; // balance days up to months let newRelativeTo, oneMonthDays; - ({ relativeTo: newRelativeTo, days: oneMonthDays } = MoveRelativeDate(calendar, relativeTo, oneMonth, dateAdd)); + ({ relativeTo: newRelativeTo, days: oneMonthDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneMonth, + dateAdd + )); while (days.abs().geq(MathAbs(oneMonthDays))) { days = days.subtract(oneMonthDays); months = months.add(sign); - relativeTo = newRelativeTo; - ({ relativeTo: newRelativeTo, days: oneMonthDays } = MoveRelativeDate(calendar, relativeTo, oneMonth, dateAdd)); + plainRelativeTo = newRelativeTo; + ({ relativeTo: newRelativeTo, days: oneMonthDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneMonth, + dateAdd + )); } break; } case 'week': { - if (!calendar) throw new RangeError('a starting point is required for weeks balancing'); const dateAdd = typeof calendar !== 'string' ? GetMethod(calendar, 'dateAdd') : undefined; // balance days up to weeks let newRelativeTo, oneWeekDays; - ({ relativeTo: newRelativeTo, days: oneWeekDays } = MoveRelativeDate(calendar, relativeTo, oneWeek, dateAdd)); + ({ relativeTo: newRelativeTo, days: oneWeekDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneWeek, + dateAdd + )); while (days.abs().geq(MathAbs(oneWeekDays))) { days = days.subtract(oneWeekDays); weeks = weeks.add(sign); - relativeTo = newRelativeTo; - ({ relativeTo: newRelativeTo, days: oneWeekDays } = MoveRelativeDate(calendar, relativeTo, oneWeek, dateAdd)); + plainRelativeTo = newRelativeTo; + ({ relativeTo: newRelativeTo, days: oneWeekDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneWeek, + dateAdd + )); } break; } @@ -4241,6 +4300,9 @@ export function DifferenceTemporalZonedDateTime(operation, zonedDateTime, other, DifferenceZonedDateTime(ns1, ns2, timeZone, calendar, settings.largestUnit, resolvedOptions)); if (settings.smallestUnit !== 'nanosecond' || settings.roundingIncrement !== 1) { + const plainRelativeToWillBeUsed = + settings.smallestUnit === 'year' || settings.smallestUnit === 'month' || settings.smallestUnit === 'week'; + const plainRelativeTo = plainRelativeToWillBeUsed ? ToTemporalDate(zonedDateTime) : undefined; ({ years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = RoundDuration( years, months, @@ -4255,6 +4317,7 @@ export function DifferenceTemporalZonedDateTime(operation, zonedDateTime, other, settings.roundingIncrement, settings.smallestUnit, settings.roundingMode, + plainRelativeTo, zonedDateTime )); ({ years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = @@ -4964,10 +5027,9 @@ export function AdjustRoundedDurationDays( increment, unit, roundingMode, - relativeTo + zonedRelativeTo ) { if ( - !IsTemporalZonedDateTime(relativeTo) || unit === 'year' || unit === 'month' || unit === 'week' || @@ -4997,10 +5059,10 @@ export function AdjustRoundedDurationDays( ); const direction = MathSign(timeRemainderNs.toJSNumber()); - const timeZone = GetSlot(relativeTo, TIME_ZONE); - const calendar = GetSlot(relativeTo, CALENDAR); + const timeZone = GetSlot(zonedRelativeTo, TIME_ZONE); + const calendar = GetSlot(zonedRelativeTo, CALENDAR); const dayStart = AddZonedDateTime( - GetSlot(relativeTo, INSTANT), + GetSlot(zonedRelativeTo, INSTANT), timeZone, calendar, years, @@ -5054,7 +5116,7 @@ export function AdjustRoundedDurationDays( 0, 0, 0, - relativeTo + zonedRelativeTo )); timeRemainderNs = RoundInstant(timeRemainderNs.subtract(dayLengthNs), increment, unit, roundingMode); ({ hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceDuration( @@ -5085,11 +5147,12 @@ export function RoundDuration( increment, unit, roundingMode, - relativeTo = undefined + plainRelativeTo = undefined, + zonedRelativeTo = undefined ) { const TemporalDuration = GetIntrinsic('%Temporal.Duration%'); - if ((unit === 'year' || unit === 'month' || unit === 'week') && !relativeTo) { + if ((unit === 'year' || unit === 'month' || unit === 'week') && !plainRelativeTo) { throw new RangeError(`A starting point is required for ${unit}s rounding`); } @@ -5099,8 +5162,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 (IsTemporalZonedDateTime(relativeTo)) { - intermediate = MoveRelativeZonedDateTime(relativeTo, years, months, weeks, days); + if (zonedRelativeTo) { + intermediate = MoveRelativeZonedDateTime(zonedRelativeTo, years, months, weeks, days); } let deltaDays; ({ days: deltaDays, nanoseconds, dayLengthNs } = NanosecondsToDays(nanoseconds, intermediate)); @@ -5111,33 +5174,32 @@ export function RoundDuration( let total; switch (unit) { case 'year': { - relativeTo = ToTemporalDate(relativeTo); - const calendar = GetSlot(relativeTo, CALENDAR); + const calendar = GetSlot(plainRelativeTo, CALENDAR); // convert months and weeks to days by calculating difference( // relativeTo + years, relativeTo + { years, months, weeks }) const yearsDuration = new TemporalDuration(years); const dateAdd = typeof calendar !== 'string' ? GetMethod(calendar, 'dateAdd') : undefined; - const yearsLater = CalendarDateAdd(calendar, relativeTo, yearsDuration, undefined, dateAdd); + const yearsLater = CalendarDateAdd(calendar, plainRelativeTo, yearsDuration, undefined, dateAdd); const yearsMonthsWeeks = new TemporalDuration(years, months, weeks); - const yearsMonthsWeeksLater = CalendarDateAdd(calendar, relativeTo, yearsMonthsWeeks, undefined, dateAdd); + const yearsMonthsWeeksLater = CalendarDateAdd(calendar, plainRelativeTo, yearsMonthsWeeks, undefined, dateAdd); const monthsWeeksInDays = DaysUntil(yearsLater, yearsMonthsWeeksLater); - relativeTo = yearsLater; + plainRelativeTo = yearsLater; days += monthsWeeksInDays; const wholeDays = new TemporalDuration(0, 0, 0, days); - const wholeDaysLater = CalendarDateAdd(calendar, relativeTo, wholeDays, undefined, dateAdd); + const wholeDaysLater = CalendarDateAdd(calendar, plainRelativeTo, wholeDays, undefined, dateAdd); const untilOptions = ObjectCreate(null); untilOptions.largestUnit = 'year'; - const yearsPassed = CalendarDateUntil(calendar, relativeTo, wholeDaysLater, untilOptions).years; + const yearsPassed = CalendarDateUntil(calendar, plainRelativeTo, wholeDaysLater, untilOptions).years; years += yearsPassed; - const oldRelativeTo = relativeTo; + const oldRelativeTo = plainRelativeTo; const yearsPassedDuration = new TemporalDuration(yearsPassed); - relativeTo = CalendarDateAdd(calendar, relativeTo, yearsPassedDuration, undefined, dateAdd); - const daysPassed = DaysUntil(oldRelativeTo, relativeTo); + plainRelativeTo = CalendarDateAdd(calendar, plainRelativeTo, yearsPassedDuration, undefined, dateAdd); + const daysPassed = DaysUntil(oldRelativeTo, plainRelativeTo); days -= daysPassed; const oneYear = new TemporalDuration(days < 0 ? -1 : 1); - let { days: oneYearDays } = MoveRelativeDate(calendar, relativeTo, oneYear, dateAdd); + let { days: oneYearDays } = MoveRelativeDate(calendar, plainRelativeTo, oneYear, dateAdd); // Note that `nanoseconds` below (here and in similar code for months, // weeks, and days further below) isn't actually nanoseconds for the @@ -5156,18 +5218,17 @@ export function RoundDuration( break; } case 'month': { - relativeTo = ToTemporalDate(relativeTo); - const calendar = GetSlot(relativeTo, CALENDAR); + const calendar = GetSlot(plainRelativeTo, CALENDAR); // convert weeks to days by calculating difference(relativeTo + // { years, months }, relativeTo + { years, months, weeks }) const yearsMonths = new TemporalDuration(years, months); const dateAdd = typeof calendar !== 'string' ? GetMethod(calendar, 'dateAdd') : undefined; - const yearsMonthsLater = CalendarDateAdd(calendar, relativeTo, yearsMonths, undefined, dateAdd); + const yearsMonthsLater = CalendarDateAdd(calendar, plainRelativeTo, yearsMonths, undefined, dateAdd); const yearsMonthsWeeks = new TemporalDuration(years, months, weeks); - const yearsMonthsWeeksLater = CalendarDateAdd(calendar, relativeTo, yearsMonthsWeeks, undefined, dateAdd); + const yearsMonthsWeeksLater = CalendarDateAdd(calendar, plainRelativeTo, yearsMonthsWeeks, undefined, dateAdd); const weeksInDays = DaysUntil(yearsMonthsLater, yearsMonthsWeeksLater); - relativeTo = yearsMonthsLater; + plainRelativeTo = yearsMonthsLater; days += weeksInDays; // Months may be different lengths of days depending on the calendar, @@ -5175,11 +5236,21 @@ export function RoundDuration( const sign = MathSign(days); const oneMonth = new TemporalDuration(0, days < 0 ? -1 : 1); let oneMonthDays; - ({ relativeTo, days: oneMonthDays } = MoveRelativeDate(calendar, relativeTo, oneMonth, dateAdd)); + ({ relativeTo: plainRelativeTo, days: oneMonthDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneMonth, + dateAdd + )); while (MathAbs(days) >= MathAbs(oneMonthDays)) { months += sign; days -= oneMonthDays; - ({ relativeTo, days: oneMonthDays } = MoveRelativeDate(calendar, relativeTo, oneMonth, dateAdd)); + ({ relativeTo: plainRelativeTo, days: oneMonthDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneMonth, + dateAdd + )); } oneMonthDays = MathAbs(oneMonthDays); const divisor = bigInt(oneMonthDays).multiply(dayLengthNs); @@ -5192,8 +5263,7 @@ export function RoundDuration( break; } case 'week': { - relativeTo = ToTemporalDate(relativeTo); - const calendar = GetSlot(relativeTo, CALENDAR); + const calendar = GetSlot(plainRelativeTo, CALENDAR); // Weeks may be different lengths of days depending on the calendar, // convert days to weeks in a loop as described above under 'years'. @@ -5201,11 +5271,21 @@ export function RoundDuration( const oneWeek = new TemporalDuration(0, 0, days < 0 ? -1 : 1); const dateAdd = typeof calendar !== 'string' ? GetMethod(calendar, 'dateAdd') : undefined; let oneWeekDays; - ({ relativeTo, days: oneWeekDays } = MoveRelativeDate(calendar, relativeTo, oneWeek, dateAdd)); + ({ relativeTo: plainRelativeTo, days: oneWeekDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneWeek, + dateAdd + )); while (MathAbs(days) >= MathAbs(oneWeekDays)) { weeks += sign; days -= oneWeekDays; - ({ relativeTo, days: oneWeekDays } = MoveRelativeDate(calendar, relativeTo, oneWeek, dateAdd)); + ({ relativeTo: plainRelativeTo, days: oneWeekDays } = MoveRelativeDate( + calendar, + plainRelativeTo, + oneWeek, + dateAdd + )); } oneWeekDays = MathAbs(oneWeekDays); const divisor = bigInt(oneWeekDays).multiply(dayLengthNs); diff --git a/spec/duration.html b/spec/duration.html index 8ff0368544..ea33001080 100644 --- a/spec/duration.html +++ b/spec/duration.html @@ -434,17 +434,25 @@

Temporal.Duration.prototype.round ( _roundTo_ )

1. If LargerOfTwoTemporalUnits(_largestUnit_, _smallestUnit_) is not _largestUnit_, throw a *RangeError* exception. 1. Let _maximum_ be ! MaximumTemporalDurationRoundingIncrement(_smallestUnit_). 1. If _maximum_ is not *undefined*, perform ? ValidateTemporalRoundingIncrement(_roundingIncrement_, _maximum_, *false*). + 1. Let _zonedRelativeTo_ be *undefined*. + 1. If _relativeTo_ is an Object with an [[InitializedTemporalZonedDateTime]] internal slot, set _zonedRelativeTo_ to _relativeTo_. + 1. Let _plainRelativeTo_ be *undefined*. + 1. If _relativeTo_ is an Object with an [[InitializedTemporalDate]] internal slot, set _plainRelativeTo_ to _relativeTo_. 1. Let _hoursToDaysConversionMayOccur_ be *false*. - 1. If _duration_.[[Days]] ≠ 0 and _relativeTo_ is an Object with an [[InitializedTemporalZonedDateTime]] internal slot, set _hoursToDaysConversionMayOccur_ to *true*. + 1. If _duration_.[[Days]] ≠ 0 and _zonedRelativeTo_ is not *undefined*, set _hoursToDaysConversionMayOccur_ to *true*. 1. Else if _duration_.[[Hours]] ≥ 24, set _hoursToDaysConversionMayOccur_ to *true*. 1. If _smallestUnit_ is *"nanosecond"*, and _roundingIncrement_ = 1, and _largestUnit_ is _existingLargestUnit_, and _duration_.[[Years]] = 0, and _duration_.[[Months]] = 0, and _duration_.[[Weeks]] = 0, and _hoursToDaysConversionMayOccur_ is *false*, and _duration_.[[Minutes]] < 60, and _duration_.[[Seconds]] < 60, and _duration_.[[Milliseconds]] < 1000, and _duration_.[[Microseconds]] < 1000, and _duration_.[[Nanoseconds]] < 1000, then 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 _unbalanceResult_ be ? UnbalanceDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _largestUnit_, _relativeTo_). - 1. Let _roundResult_ be (? RoundDuration(_unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], _unbalanceResult_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _relativeTo_)).[[DurationRecord]]. - 1. Let _adjustResult_ be ? AdjustRoundedDurationDays(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _roundResult_.[[Days]], _roundResult_.[[Hours]], _roundResult_.[[Minutes]], _roundResult_.[[Seconds]], _roundResult_.[[Milliseconds]], _roundResult_.[[Microseconds]], _roundResult_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _relativeTo_). - 1. Let _balanceResult_ be ? BalanceDuration(_adjustResult_.[[Days]], _adjustResult_.[[Hours]], _adjustResult_.[[Minutes]], _adjustResult_.[[Seconds]], _adjustResult_.[[Milliseconds]], _adjustResult_.[[Microseconds]], _adjustResult_.[[Nanoseconds]], _largestUnit_, _relativeTo_). - 1. Let _result_ be ? BalanceDurationRelative(_adjustResult_.[[Years]], _adjustResult_.[[Months]], _adjustResult_.[[Weeks]], _balanceResult_.[[Days]], _largestUnit_, _relativeTo_). + 1. If _zonedRelativeTo_ is not *undefined*; and _smallestUnit_ is any of *"year"*, *"month"*, *"week"*; and any of _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]] ≠ 0; then + 1. NOTE: The above conditions mean that the corresponding `Temporal.PlainDate` for _zonedRelativeTo_ will be used in one of the operations below. + 1. Set _plainRelativeTo_ to ? ToTemporalDate(_zonedRelativeTo_). + 1. Let _unbalanceResult_ be ? UnbalanceDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _largestUnit_, _plainRelativeTo_). + 1. Let _roundResult_ be (? RoundDuration(_unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], _unbalanceResult_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _plainRelativeTo_, _zonedRelativeTo_)).[[DurationRecord]]. + 1. If _zonedRelativeTo_ is not *undefined*, then + 1. Set _roundResult_ to ? AdjustRoundedDurationDays(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _roundResult_.[[Days]], _roundResult_.[[Hours]], _roundResult_.[[Minutes]], _roundResult_.[[Seconds]], _roundResult_.[[Milliseconds]], _roundResult_.[[Microseconds]], _roundResult_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _zonedRelativeTo_). + 1. Let _balanceResult_ be ? BalanceDuration(_roundResult_.[[Days]], _roundResult_.[[Hours]], _roundResult_.[[Minutes]], _roundResult_.[[Seconds]], _roundResult_.[[Milliseconds]], _roundResult_.[[Microseconds]], _roundResult_.[[Nanoseconds]], _largestUnit_, _zonedRelativeTo_). + 1. Let _result_ be ? BalanceDurationRelative(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _balanceResult_.[[Days]], _largestUnit_, _plainRelativeTo_). 1. Return ! CreateTemporalDuration(_result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _result_.[[Days]], _balanceResult_.[[Hours]], _balanceResult_.[[Minutes]], _balanceResult_.[[Seconds]], _balanceResult_.[[Milliseconds]], _balanceResult_.[[Microseconds]], _balanceResult_.[[Nanoseconds]]). @@ -467,15 +475,22 @@

Temporal.Duration.prototype.total ( _totalOf_ )

1. NOTE: The following steps read options and perform independent validation in alphabetical order (ToRelativeTemporalObject reads *"relativeTo"*). 1. Let _relativeTo_ be ? ToRelativeTemporalObject(_totalOf_). 1. Let _unit_ be ? GetTemporalUnit(_totalOf_, *"unit"*, ~datetime~, ~required~). - 1. Let _unbalanceResult_ be ? UnbalanceDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _unit_, _relativeTo_). + 1. Let _zonedRelativeTo_ be *undefined*. + 1. If _relativeTo_ is an Object with an [[InitializedTemporalZonedDateTime]] internal slot, set _zonedRelativeTo_ to _relativeTo_. + 1. Let _plainRelativeTo_ be *undefined*. + 1. If _relativeTo_ is an Object with an [[InitializedTemporalDate]] internal slot, set _plainRelativeTo_ to _relativeTo_. + 1. If _zonedRelativeTo_ is not *undefined*; and _unit_ is any of *"year"*, *"month"*, *"week"*; and any of _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]] ≠ 0; then + 1. NOTE: The above conditions mean that the corresponding `Temporal.PlainDate` for _zonedRelativeTo_ will be used in one of the operations below. + 1. Set _plainRelativeTo_ to ? ToTemporalDate(_zonedRelativeTo_). + 1. Let _unbalanceResult_ be ? UnbalanceDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _unit_, _plainRelativeTo_). 1. Let _intermediate_ be *undefined*. - 1. If Type(_relativeTo_) is Object and _relativeTo_ has an [[InitializedTemporalZonedDateTime]] internal slot, then - 1. Set _intermediate_ to ? MoveRelativeZonedDateTime(_relativeTo_, _unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], 0). + 1. If _zonedRelativeTo_ is not *undefined*, then + 1. Set _intermediate_ to ? MoveRelativeZonedDateTime(_zonedRelativeTo_, _unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], 0). 1. Let _balanceResult_ be ? BalancePossiblyInfiniteDuration(_unbalanceResult_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _unit_, _intermediate_). 1. If _balanceResult_ is ~positive overflow~, return *+∞*𝔽. 1. If _balanceResult_ is ~negative overflow~, return *-∞*𝔽. 1. Assert: _balanceResult_ is a Time Duration Record. - 1. Let _roundRecord_ be ? RoundDuration(_unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], _balanceResult_.[[Days]], _balanceResult_.[[Hours]], _balanceResult_.[[Minutes]], _balanceResult_.[[Seconds]], _balanceResult_.[[Milliseconds]], _balanceResult_.[[Microseconds]], _balanceResult_.[[Nanoseconds]], 1, _unit_, *"trunc"*, _relativeTo_). + 1. Let _roundRecord_ be ? RoundDuration(_unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], _balanceResult_.[[Days]], _balanceResult_.[[Hours]], _balanceResult_.[[Minutes]], _balanceResult_.[[Seconds]], _balanceResult_.[[Milliseconds]], _balanceResult_.[[Microseconds]], _balanceResult_.[[Nanoseconds]], 1, _unit_, *"trunc"*, _plainRelativeTo_, _zonedRelativeTo_). 1. Let _roundResult_ be _roundRecord_.[[DurationRecord]]. 1. If _unit_ is *"year"*, then 1. Let _whole_ be _roundResult_.[[Years]]. @@ -1203,7 +1218,7 @@

_microseconds_: an integer, _nanoseconds_: an integer, _largestUnit_: a String, - optional _relativeTo_: *undefined*, a Temporal.PlainDate, or a Temporal.ZonedDateTime, + optional _zonedRelativeTo_: *undefined* or a Temporal.ZonedDateTime, ): either a normal completion containing a Time Duration Record, or an abrupt completion

@@ -1211,11 +1226,11 @@

It converts the time units of a duration into a form where lower units are converted into higher units as much as possible, up to _largestUnit_. If the Number value for any unit is infinite, it returns abruptly with a *RangeError*.

- This operation may observably call time zone and calendar methods if _relativeTo_ is a Temporal.ZonedDateTime instance. + This operation may observably call time zone and calendar methods if _zonedRelativeTo_ is not *undefined*. Otherwise, it does not call into user code.

- 1. Let _balanceResult_ be ? BalancePossiblyInfiniteDuration(_days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_, _largestUnit_, _relativeTo_). + 1. Let _balanceResult_ be ? BalancePossiblyInfiniteDuration(_days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_, _largestUnit_, _zonedRelativeTo_). 1. If _balanceResult_ is ~positive overflow~ or ~negative overflow~, then 1. Throw a *RangeError* exception. 1. Else, @@ -1234,7 +1249,7 @@

_microseconds_: an integer, _nanoseconds_: an integer, _largestUnit_: a String, - optional _relativeTo_: *undefined*, a Temporal.PlainDate, or a Temporal.ZonedDateTime, + optional _zonedRelativeTo_: *undefined* or a Temporal.ZonedDateTime, ): either a normal completion containing either Time Duration Record if there are no infinite values, ~positive overflow~, or ~negative overflow~ in case of infinite values, or an abrupt completion

@@ -1242,14 +1257,14 @@

It converts the time units of a duration into a form where lower units are converted into higher units as much as possible, up to _largestUnit_. If the Number value for any unit is infinite, it returns a special value indicating the direction of overflow.

- 1. If _relativeTo_ is not present, set _relativeTo_ to *undefined*. - 1. If Type(_relativeTo_) is Object and _relativeTo_ has an [[InitializedTemporalZonedDateTime]] internal slot, then - 1. Let _endNs_ be ? AddZonedDateTime(_relativeTo_.[[Nanoseconds]], _relativeTo_.[[TimeZone]], _relativeTo_.[[Calendar]], 0, 0, 0, _days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). - 1. Set _nanoseconds_ to ℝ(_endNs_ - _relativeTo_.[[Nanoseconds]]). + 1. If _zonedRelativeTo_ is not present, set _zonedRelativeTo_ to *undefined*. + 1. If _zonedRelativeTo_ is not *undefined*, then + 1. Let _endNs_ be ? AddZonedDateTime(_zonedRelativeTo_.[[Nanoseconds]], _zonedRelativeTo_.[[TimeZone]], _zonedRelativeTo_.[[Calendar]], 0, 0, 0, _days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). + 1. Set _nanoseconds_ to ℝ(_endNs_ - _zonedRelativeTo_.[[Nanoseconds]]). 1. Else, 1. Set _nanoseconds_ to ! TotalDurationNanoseconds(_days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_, 0). 1. If _largestUnit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then - 1. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _relativeTo_). + 1. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _zonedRelativeTo_). 1. Set _days_ to _result_.[[Days]]. 1. Set _nanoseconds_ to _result_.[[Nanoseconds]]. 1. Else, @@ -1312,7 +1327,7 @@

_weeks_: an integer, _days_: an integer, _largestUnit_: a String, - _relativeTo_: *undefined*, a Temporal.PlainDate, or a Temporal.ZonedDateTime, + _plainRelativeTo_: *undefined* or a Temporal.PlainDate, )

@@ -1329,12 +1344,12 @@

1. Let _oneYear_ be ! CreateTemporalDuration(_sign_, 0, 0, 0, 0, 0, 0, 0, 0, 0). 1. Let _oneMonth_ be ! CreateTemporalDuration(0, _sign_, 0, 0, 0, 0, 0, 0, 0, 0). 1. Let _oneWeek_ be ! CreateTemporalDuration(0, 0, _sign_, 0, 0, 0, 0, 0, 0, 0). - 1. If _relativeTo_ is not *undefined*, then - 1. Set _relativeTo_ to ? ToTemporalDate(_relativeTo_). - 1. Let _calendar_ be _relativeTo_.[[Calendar]]. + 1. If _plainRelativeTo_ is not *undefined*, then + 1. Let _calendar_ be _plainRelativeTo_.[[Calendar]]. 1. Else, 1. Let _calendar_ be *undefined*. 1. If _largestUnit_ is *"month"*, then + 1. If _years_ = 0, return ? CreateDateDurationRecord(0, _months_, _weeks_, _days_). 1. If _calendar_ is *undefined*, then 1. Throw a *RangeError* exception. 1. If _calendar_ is an Object, then @@ -1344,15 +1359,16 @@

1. Let _dateAdd_ be ~unused~. 1. Let _dateUntil_ be ~unused~. 1. Repeat, while _years_ ≠ 0, - 1. Let _newRelativeTo_ be ? CalendarDateAdd(_calendar_, _relativeTo_, _oneYear_, *undefined*, _dateAdd_). + 1. Let _newRelativeTo_ be ? CalendarDateAdd(_calendar_, _plainRelativeTo_, _oneYear_, *undefined*, _dateAdd_). 1. Let _untilOptions_ be OrdinaryObjectCreate(*null*). 1. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"month"*). - 1. Let _untilResult_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _newRelativeTo_, _untilOptions_, _dateUntil_). + 1. Let _untilResult_ be ? CalendarDateUntil(_calendar_, _plainRelativeTo_, _newRelativeTo_, _untilOptions_, _dateUntil_). 1. Let _oneYearMonths_ be _untilResult_.[[Months]]. - 1. Set _relativeTo_ to _newRelativeTo_. + 1. Set _plainRelativeTo_ to _newRelativeTo_. 1. Set _years_ to _years_ - _sign_. 1. Set _months_ to _months_ + _oneYearMonths_. 1. Else if _largestUnit_ is *"week"*, then + 1. If _years_ = 0 and _months_ = 0, return ? CreateDateDurationRecord(0, 0, _weeks_, _days_). 1. If _calendar_ is *undefined*, then 1. Throw a *RangeError* exception. 1. If _calendar_ is an Object, then @@ -1360,13 +1376,13 @@

1. Else, 1. Let _dateAdd_ be ~unused~. 1. Repeat, while _years_ ≠ 0, - 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _relativeTo_, _oneYear_, _dateAdd_). - 1. Set _relativeTo_ to _moveResult_.[[RelativeTo]]. + 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneYear_, _dateAdd_). + 1. Set _plainRelativeTo_ to _moveResult_.[[RelativeTo]]. 1. Set _days_ to _days_ + _moveResult_.[[Days]]. 1. Set _years_ to _years_ - _sign_. 1. Repeat, while _months_ ≠ 0, - 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _relativeTo_, _oneMonth_, _dateAdd_). - 1. Set _relativeTo_ to _moveResult_.[[RelativeTo]]. + 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneMonth_, _dateAdd_). + 1. Set _plainRelativeTo_ to _moveResult_.[[RelativeTo]]. 1. Set _days_ to _days_ + _moveResult_.[[Days]]. 1. Set _months_ to _months_ - _sign_. 1. Else, @@ -1378,18 +1394,18 @@

1. Else, 1. Let _dateAdd_ be ~unused~. 1. Repeat, while _years_ ≠ 0, - 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _relativeTo_, _oneYear_, _dateAdd_). - 1. Set _relativeTo_ to _moveResult_.[[RelativeTo]]. + 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneYear_, _dateAdd_). + 1. Set _plainRelativeTo_ to _moveResult_.[[RelativeTo]]. 1. Set _days_ to _days_ + _moveResult_.[[Days]]. 1. Set _years_ to _years_ - _sign_. 1. Repeat, while _months_ ≠ 0, - 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _relativeTo_, _oneMonth_, _dateAdd_). - 1. Set _relativeTo_ to _moveResult_.[[RelativeTo]]. + 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneMonth_, _dateAdd_). + 1. Set _plainRelativeTo_ to _moveResult_.[[RelativeTo]]. 1. Set _days_ to _days_ +_moveResult_.[[Days]]. 1. Set _months_ to _months_ - _sign_. 1. Repeat, while _weeks_ ≠ 0, - 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _relativeTo_, _oneWeek_, _dateAdd_). - 1. Set _relativeTo_ to _moveResult_.[[RelativeTo]]. + 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneWeek_, _dateAdd_). + 1. Set _plainRelativeTo_ to _moveResult_.[[RelativeTo]]. 1. Set _days_ to _days_ + _moveResult_.[[Days]]. 1. Set _weeks_ to _weeks_ - _sign_. 1. Return ? CreateDateDurationRecord(_years_, _months_, _weeks_, _days_). @@ -1404,7 +1420,7 @@

_weeks_: an integer, _days_: an integer, _largestUnit_: a String, - _relativeTo_: *undefined*, a Temporal.PlainDate, or a Temporal.ZonedDateTime, + _plainRelativeTo_: *undefined* or a Temporal.PlainDate, )

@@ -1416,71 +1432,70 @@

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 _relativeTo_ is *undefined*, then + 1. If _plainRelativeTo_ is *undefined*, then 1. Throw a *RangeError* exception. 1. Let _sign_ be ! DurationSign(_years_, _months_, _weeks_, _days_, 0, 0, 0, 0, 0, 0). 1. Assert: _sign_ ≠ 0. 1. Let _oneYear_ be ! CreateTemporalDuration(_sign_, 0, 0, 0, 0, 0, 0, 0, 0, 0). 1. Let _oneMonth_ be ! CreateTemporalDuration(0, _sign_, 0, 0, 0, 0, 0, 0, 0, 0). 1. Let _oneWeek_ be ! CreateTemporalDuration(0, 0, _sign_, 0, 0, 0, 0, 0, 0, 0). - 1. Set _relativeTo_ to ? ToTemporalDate(_relativeTo_). - 1. Let _calendar_ be _relativeTo_.[[Calendar]]. + 1. Let _calendar_ be _plainRelativeTo_.[[Calendar]]. 1. If _largestUnit_ is *"year"*, then 1. If _calendar_ is an Object, then 1. Let _dateAdd_ be ? GetMethod(_calendar_, *"dateAdd"*). 1. Else, 1. Let _dateAdd_ be ~unused~. - 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _relativeTo_, _oneYear_, _dateAdd_). + 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneYear_, _dateAdd_). 1. Let _newRelativeTo_ be _moveResult_.[[RelativeTo]]. 1. Let _oneYearDays_ be _moveResult_.[[Days]]. 1. Repeat, while abs(_days_) ≥ abs(_oneYearDays_), 1. Set _days_ to _days_ - _oneYearDays_. 1. Set _years_ to _years_ + _sign_. - 1. Set _relativeTo_ to _newRelativeTo_. - 1. Set _moveResult_ to ? MoveRelativeDate(_calendar_, _relativeTo_, _oneYear_, _dateAdd_). + 1. Set _plainRelativeTo_ to _newRelativeTo_. + 1. Set _moveResult_ to ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneYear_, _dateAdd_). 1. Set _newRelativeTo_ to _moveResult_.[[RelativeTo]]. 1. Set _oneYearDays_ to _moveResult_.[[Days]]. - 1. Set _moveResult_ to ? MoveRelativeDate(_calendar_, _relativeTo_, _oneMonth_, _dateAdd_). + 1. Set _moveResult_ to ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneMonth_, _dateAdd_). 1. Set _newRelativeTo_ to _moveResult_.[[RelativeTo]]. 1. Let _oneMonthDays_ be _moveResult_.[[Days]]. 1. Repeat, while abs(_days_) ≥ abs(_oneMonthDays_), 1. Set _days_ to _days_ - _oneMonthDays_. 1. Set _months_ to _months_ + _sign_. - 1. Set _relativeTo_ to _newRelativeTo_. - 1. Set _moveResult_ to ? MoveRelativeDate(_calendar_, _relativeTo_, _oneMonth_, _dateAdd_). + 1. Set _plainRelativeTo_ to _newRelativeTo_. + 1. Set _moveResult_ to ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneMonth_, _dateAdd_). 1. Set _newRelativeTo_ to _moveResult_.[[RelativeTo]]. 1. Set _oneMonthDays_ to _moveResult_.[[Days]]. - 1. Set _newRelativeTo_ to ? CalendarDateAdd(_calendar_, _relativeTo_, _oneYear_, *undefined*, _dateAdd_). + 1. Set _newRelativeTo_ to ? CalendarDateAdd(_calendar_, _plainRelativeTo_, _oneYear_, *undefined*, _dateAdd_). 1. If _calendar_ is an Object, then 1. Let _dateUntil_ be ? GetMethod(_calendar_, *"dateUntil"*). 1. Else, 1. Let _dateUntil_ be ~unused~. 1. Let _untilOptions_ be OrdinaryObjectCreate(*null*). 1. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"month"*). - 1. Let _untilResult_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _newRelativeTo_, _untilOptions_, _dateUntil_). + 1. Let _untilResult_ be ? CalendarDateUntil(_calendar_, _plainRelativeTo_, _newRelativeTo_, _untilOptions_, _dateUntil_). 1. Let _oneYearMonths_ be _untilResult_.[[Months]]. 1. Repeat, while abs(_months_) ≥ abs(_oneYearMonths_), 1. Set _months_ to _months_ - _oneYearMonths_. 1. Set _years_ to _years_ + _sign_. - 1. Set _relativeTo_ to _newRelativeTo_. - 1. Set _newRelativeTo_ to ? CalendarDateAdd(_calendar_, _relativeTo_, _oneYear_, *undefined*, _dateAdd_). + 1. Set _plainRelativeTo_ to _newRelativeTo_. + 1. Set _newRelativeTo_ to ? CalendarDateAdd(_calendar_, _plainRelativeTo_, _oneYear_, *undefined*, _dateAdd_). 1. Set _untilOptions_ to OrdinaryObjectCreate(*null*). 1. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"month"*). - 1. Set _untilResult_ to ? CalendarDateUntil(_calendar_, _relativeTo_, _newRelativeTo_, _untilOptions_, _dateUntil_). + 1. Set _untilResult_ to ? CalendarDateUntil(_calendar_, _plainRelativeTo_, _newRelativeTo_, _untilOptions_, _dateUntil_). 1. Set _oneYearMonths_ to _untilResult_.[[Months]]. 1. Else if _largestUnit_ is *"month"*, then 1. If _calendar_ is an Object, then 1. Let _dateAdd_ be ? GetMethod(_calendar_, *"dateAdd"*). 1. Else, 1. Let _dateAdd_ be ~unused~. - 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _relativeTo_, _oneMonth_, _dateAdd_). + 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneMonth_, _dateAdd_). 1. Let _newRelativeTo_ be _moveResult_.[[RelativeTo]]. 1. Let _oneMonthDays_ be _moveResult_.[[Days]]. 1. Repeat, while abs(_days_) ≥ abs(_oneMonthDays_), 1. Set _days_ to _days_ - _oneMonthDays_. 1. Set _months_ to _months_ + _sign_. - 1. Set _relativeTo_ to _newRelativeTo_. - 1. Set _moveResult_ to ? MoveRelativeDate(_calendar_, _relativeTo_, _oneMonth_, _dateAdd_). + 1. Set _plainRelativeTo_ to _newRelativeTo_. + 1. Set _moveResult_ to ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneMonth_, _dateAdd_). 1. Set _newRelativeTo_ to _moveResult_.[[RelativeTo]]. 1. Set _oneMonthDays_ to _moveResult_.[[Days]]. 1. Else, @@ -1489,14 +1504,14 @@

1. Let _dateAdd_ be ? GetMethod(_calendar_, *"dateAdd"*). 1. Else, 1. Let _dateAdd_ be ~unused~. - 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _relativeTo_, _oneWeek_, _dateAdd_). + 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneWeek_, _dateAdd_). 1. Let _newRelativeTo_ be _moveResult_.[[RelativeTo]]. 1. Let _oneWeekDays_ be _moveResult_.[[Days]]. 1. Repeat, while abs(_days_) ≥ abs(_oneWeekDays_), 1. Set _days_ to _days_ - _oneWeekDays_. 1. Set _weeks_ to _weeks_ + _sign_. - 1. Set _relativeTo_ to _newRelativeTo_. - 1. Set _moveResult_ to ? MoveRelativeDate(_calendar_, _relativeTo_, _oneWeek_, _dateAdd_). + 1. Set _plainRelativeTo_ to _newRelativeTo_. + 1. Set _moveResult_ to ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneWeek_, _dateAdd_). 1. Set _newRelativeTo_ to _moveResult_.[[RelativeTo]]. 1. Set _oneWeekDays_ to _moveResult_.[[Days]]. 1. Return ! CreateDateDurationRecord(_years_, _months_, _weeks_, _days_). @@ -1653,22 +1668,24 @@

_increment_: an integer, _unit_: a String, _roundingMode_: a String, - optional _relativeTo_: *undefined*, a Temporal.PlainDate, or a Temporal.ZonedDateTime, + optional _plainRelativeTo_: *undefined* or a Temporal.PlainDate, + optional _zonedRelativeTo_: *undefined* or a Temporal.ZonedDateTime, )

description
-
It rounds a duration (denoted by _years_ through _nanoseconds_) according to the rounding parameters _unit_, _increment_, and _roundingMode_, and returns a Record with the Duration Record result in its [[DurationRecord]] field, as well as the remainder from the rounding operation in its [[Remainder]] field. For rounding involving calendar units, the _relativeTo_ parameter is required.
+
It rounds a duration (denoted by _years_ through _nanoseconds_) according to the rounding parameters _unit_, _increment_, and _roundingMode_, and returns a Record with the Duration Record result in its [[DurationRecord]] field, as well as the remainder from the rounding operation in its [[Remainder]] field. For rounding involving calendar units, the _plainRelativeTo_ parameter is required.
- 1. If _relativeTo_ is not present, set _relativeTo_ to *undefined*. - 1. If _unit_ is *"year"*, *"month"*, or *"week"*, and _relativeTo_ is *undefined*, then + 1. If _plainRelativeTo_ is not present, set _plainRelativeTo_ to *undefined*. + 1. If _zonedRelativeTo_ is not present, set _zonedRelativeTo_ to *undefined*. + 1. If _unit_ is *"year"*, *"month"*, or *"week"*, and _plainRelativeTo_ is *undefined*, then 1. Throw a *RangeError* exception. 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 _relativeTo_ is an Object with an [[InitializedTemporalZonedDateTime]] internal slot, then - 1. Let _intermediate_ be ? MoveRelativeZonedDateTime(_relativeTo_, _years_, _months_, _weeks_, _days_). + 1. If _zonedRelativeTo_ is not *undefined*, then + 1. Let _intermediate_ be ? MoveRelativeZonedDateTime(_zonedRelativeTo_, _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. @@ -1676,85 +1693,82 @@

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 _calendar_ be _plainRelativeTo_.[[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"*). 1. Else, 1. Let _dateAdd_ be ~unused~. - 1. Let _yearsLater_ be ? CalendarDateAdd(_calendar_, _relativeTo_, _yearsDuration_, *undefined*, _dateAdd_). + 1. Let _yearsLater_ be ? CalendarDateAdd(_calendar_, _plainRelativeTo_, _yearsDuration_, *undefined*, _dateAdd_). 1. Let _yearsMonthsWeeks_ be ! CreateTemporalDuration(_years_, _months_, _weeks_, 0, 0, 0, 0, 0, 0, 0). - 1. Let _yearsMonthsWeeksLater_ be ? CalendarDateAdd(_calendar_, _relativeTo_, _yearsMonthsWeeks_, *undefined*, _dateAdd_). + 1. Let _yearsMonthsWeeksLater_ be ? CalendarDateAdd(_calendar_, _plainRelativeTo_, _yearsMonthsWeeks_, *undefined*, _dateAdd_). 1. Let _monthsWeeksInDays_ be DaysUntil(_yearsLater_, _yearsMonthsWeeksLater_). - 1. Set _relativeTo_ to _yearsLater_. + 1. Set _plainRelativeTo_ to _yearsLater_. 1. Let _days_ be _days_ + _monthsWeeksInDays_. 1. Let _wholeDaysDuration_ be ? CreateTemporalDuration(0, 0, 0, truncate(_days_), 0, 0, 0, 0, 0, 0). - 1. Let _wholeDaysLater_ be ? CalendarDateAdd(_calendar_, _relativeTo_, _wholeDaysDuration_, *undefined*, _dateAdd_). + 1. Let _wholeDaysLater_ be ? CalendarDateAdd(_calendar_, _plainRelativeTo_, _wholeDaysDuration_, *undefined*, _dateAdd_). 1. Let _untilOptions_ be OrdinaryObjectCreate(*null*). 1. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"year"*). - 1. Let _timePassed_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _wholeDaysLater_, _untilOptions_). + 1. Let _timePassed_ be ? CalendarDateUntil(_calendar_, _plainRelativeTo_, _wholeDaysLater_, _untilOptions_). 1. Let _yearsPassed_ be _timePassed_.[[Years]]. 1. Set _years_ to _years_ + _yearsPassed_. - 1. Let _oldRelativeTo_ be _relativeTo_. + 1. Let _oldRelativeTo_ be _plainRelativeTo_. 1. Let _yearsDuration_ be ! CreateTemporalDuration(_yearsPassed_, 0, 0, 0, 0, 0, 0, 0, 0, 0). - 1. Set _relativeTo_ to ? CalendarDateAdd(_calendar_, _relativeTo_, _yearsDuration_, *undefined*, _dateAdd_). - 1. Let _daysPassed_ be DaysUntil(_oldRelativeTo_, _relativeTo_). + 1. Set _plainRelativeTo_ to ? CalendarDateAdd(_calendar_, _plainRelativeTo_, _yearsDuration_, *undefined*, _dateAdd_). + 1. Let _daysPassed_ be DaysUntil(_oldRelativeTo_, _plainRelativeTo_). 1. Set _days_ to _days_ - _daysPassed_. 1. If _days_ < 0, let _sign_ be -1; else, let _sign_ be 1. 1. Let _oneYear_ be ! CreateTemporalDuration(_sign_, 0, 0, 0, 0, 0, 0, 0, 0, 0). - 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _relativeTo_, _oneYear_, _dateAdd_). + 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneYear_, _dateAdd_). 1. Let _oneYearDays_ be _moveResult_.[[Days]]. 1. Let _fractionalYears_ be _years_ + _days_ / abs(_oneYearDays_). 1. Set _years_ to RoundNumberToIncrement(_fractionalYears_, _increment_, _roundingMode_). 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 _calendar_ be _plainRelativeTo_.[[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"*). 1. Else, 1. Let _dateAdd_ be ~unused~. - 1. Let _yearsMonthsLater_ be ? CalendarDateAdd(_calendar_, _relativeTo_, _yearsMonths_, *undefined*, _dateAdd_). + 1. Let _yearsMonthsLater_ be ? CalendarDateAdd(_calendar_, _plainRelativeTo_, _yearsMonths_, *undefined*, _dateAdd_). 1. Let _yearsMonthsWeeks_ be ! CreateTemporalDuration(_years_, _months_, _weeks_, 0, 0, 0, 0, 0, 0, 0). - 1. Let _yearsMonthsWeeksLater_ be ? CalendarDateAdd(_calendar_, _relativeTo_, _yearsMonthsWeeks_, *undefined*, _dateAdd_). + 1. Let _yearsMonthsWeeksLater_ be ? CalendarDateAdd(_calendar_, _plainRelativeTo_, _yearsMonthsWeeks_, *undefined*, _dateAdd_). 1. Let _weeksInDays_ be DaysUntil(_yearsMonthsLater_, _yearsMonthsWeeksLater_). - 1. Set _relativeTo_ to _yearsMonthsLater_. + 1. Set _plainRelativeTo_ to _yearsMonthsLater_. 1. Let _days_ be _days_ + _weeksInDays_. 1. If _days_ < 0, let _sign_ be -1; else, let _sign_ be 1. 1. Let _oneMonth_ be ! CreateTemporalDuration(0, _sign_, 0, 0, 0, 0, 0, 0, 0, 0). - 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _relativeTo_, _oneMonth_, _dateAdd_). - 1. Set _relativeTo_ to _moveResult_.[[RelativeTo]]. + 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneMonth_, _dateAdd_). + 1. Set _plainRelativeTo_ to _moveResult_.[[RelativeTo]]. 1. Let _oneMonthDays_ be _moveResult_.[[Days]]. 1. Repeat, while abs(_days_) ≥ abs(_oneMonthDays_), 1. Set _months_ to _months_ + _sign_. 1. Set _days_ to _days_ - _oneMonthDays_. - 1. Set _moveResult_ to ? MoveRelativeDate(_calendar_, _relativeTo_, _oneMonth_, _dateAdd_). - 1. Set _relativeTo_ to _moveResult_.[[RelativeTo]]. + 1. Set _moveResult_ to ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneMonth_, _dateAdd_). + 1. Set _plainRelativeTo_ to _moveResult_.[[RelativeTo]]. 1. Set _oneMonthDays_ to _moveResult_.[[Days]]. 1. Let _fractionalMonths_ be _months_ + _days_ / abs(_oneMonthDays_). 1. Set _months_ to RoundNumberToIncrement(_fractionalMonths_, _increment_, _roundingMode_). 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. Let _calendar_ be _plainRelativeTo_.[[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 1. Let _dateAdd_ be ? GetMethod(_calendar_, *"dateAdd"*). 1. Else, 1. Let _dateAdd_ be ~unused~. - 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _relativeTo_, _oneWeek_, _dateAdd_). - 1. Set _relativeTo_ to _moveResult_.[[RelativeTo]]. + 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneWeek_, _dateAdd_). + 1. Set _plainRelativeTo_ to _moveResult_.[[RelativeTo]]. 1. Let _oneWeekDays_ be _moveResult_.[[Days]]. 1. Repeat, while abs(_days_) ≥ abs(_oneWeekDays_), 1. Set _weeks_ to _weeks_ + _sign_. 1. Set _days_ to _days_ - _oneWeekDays_. - 1. Set _moveResult_ to ? MoveRelativeDate(_calendar_, _relativeTo_, _oneWeek_, _dateAdd_). - 1. Set _relativeTo_ to _moveResult_.[[RelativeTo]]. + 1. Set _moveResult_ to ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneWeek_, _dateAdd_). + 1. Set _plainRelativeTo_ to _moveResult_.[[RelativeTo]]. 1. Set _oneWeekDays_ to _moveResult_.[[Days]]. 1. Let _fractionalWeeks_ be _weeks_ + _days_ / abs(_oneWeekDays_). 1. Set _weeks_ to RoundNumberToIncrement(_fractionalWeeks_, _increment_, _roundingMode_). @@ -1818,7 +1832,7 @@

_increment_: an integer, _unit_: a String, _roundingMode_: a String, - _relativeTo_: *undefined*, a Temporal.PlainDate, or a Temporal.ZonedDateTime, + _zonedRelativeTo_: a Temporal.ZonedDateTime, )

@@ -1830,19 +1844,19 @@

- 1. If Type(_relativeTo_) is not Object; or _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot; or _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then + 1. If _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then 1. Return ! CreateDurationRecord(_years_, _months_, _weeks_, _days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). 1. Let _timeRemainderNs_ be ! TotalDurationNanoseconds(0, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_, 0). 1. If _timeRemainderNs_ = 0, let _direction_ be 0. 1. Else if _timeRemainderNs_ < 0, let _direction_ be -1. 1. Else, let _direction_ be 1. - 1. Let _dayStart_ be ? AddZonedDateTime(_relativeTo_.[[Nanoseconds]], _relativeTo_.[[TimeZone]], _relativeTo_.[[Calendar]], _years_, _months_, _weeks_, _days_, 0, 0, 0, 0, 0, 0). - 1. Let _dayEnd_ be ? AddZonedDateTime(_dayStart_, _relativeTo_.[[TimeZone]], _relativeTo_.[[Calendar]], 0, 0, 0, _direction_, 0, 0, 0, 0, 0, 0). + 1. Let _dayStart_ be ? AddZonedDateTime(_zonedRelativeTo_.[[Nanoseconds]], _zonedRelativeTo_.[[TimeZone]], _zonedRelativeTo_.[[Calendar]], _years_, _months_, _weeks_, _days_, 0, 0, 0, 0, 0, 0). + 1. Let _dayEnd_ be ? AddZonedDateTime(_dayStart_, _zonedRelativeTo_.[[TimeZone]], _zonedRelativeTo_.[[Calendar]], 0, 0, 0, _direction_, 0, 0, 0, 0, 0, 0). 1. Let _dayLengthNs_ be ℝ(_dayEnd_ - _dayStart_). 1. If (_timeRemainderNs_ - _dayLengthNs_) × _direction_ < 0, then 1. Return ! CreateDurationRecord(_years_, _months_, _weeks_, _days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). 1. Set _timeRemainderNs_ to ℝ(RoundTemporalInstant(ℤ(_timeRemainderNs_ - _dayLengthNs_), _increment_, _unit_, _roundingMode_)). - 1. Let _adjustedDateDuration_ be ? AddDuration(_years_, _months_, _weeks_, _days_, 0, 0, 0, 0, 0, 0, 0, 0, 0, _direction_, 0, 0, 0, 0, 0, 0, _relativeTo_). + 1. Let _adjustedDateDuration_ be ? AddDuration(_years_, _months_, _weeks_, _days_, 0, 0, 0, 0, 0, 0, 0, 0, 0, _direction_, 0, 0, 0, 0, 0, 0, _zonedRelativeTo_). 1. Let _adjustedTimeDuration_ be ? BalanceDuration(0, 0, 0, 0, 0, 0, _timeRemainderNs_, *"hour"*). 1. Return ! CreateDurationRecord(_adjustedDateDuration_.[[Years]], _adjustedDateDuration_.[[Months]], _adjustedDateDuration_.[[Weeks]], _adjustedDateDuration_.[[Days]], _adjustedTimeDuration_.[[Hours]], _adjustedTimeDuration_.[[Minutes]], _adjustedTimeDuration_.[[Seconds]], _adjustedTimeDuration_.[[Milliseconds]], _adjustedTimeDuration_.[[Microseconds]], _adjustedTimeDuration_.[[Nanoseconds]]). diff --git a/spec/zoneddatetime.html b/spec/zoneddatetime.html index 1465684419..99e8d14691 100644 --- a/spec/zoneddatetime.html +++ b/spec/zoneddatetime.html @@ -1357,13 +1357,13 @@

NanosecondsToDays ( _nanoseconds_: an integer, - _relativeTo_: *undefined*, a Temporal.PlainDate, or a Temporal.ZonedDateTime, + _zonedRelativeTo_: *undefined* or a Temporal.ZonedDateTime, ): either a normal completion containing a Record with fields [[Days]] (an integer), [[Nanoseconds]] (an integer), and [[DayLength]] (an integer), or an abrupt completion

description
- It converts a number of _nanoseconds_ relative to a Temporal.ZonedDateTime _relativeTo_, and converts it into a number of days and remainder of nanoseconds, taking into account any offset changes in the time zone of _relativeTo_. + It converts a number of _nanoseconds_ relative to a Temporal.ZonedDateTime _zonedRelativeTo_ (if supplied), and converts it into a number of days and remainder of nanoseconds, taking into account any offset changes in the time zone of _zonedRelativeTo_. It also returns the length of the last day in nanoseconds, for rounding purposes.
@@ -1372,30 +1372,30 @@

1. If _nanoseconds_ = 0, then 1. Return the Record { [[Days]]: 0, [[Nanoseconds]]: 0, [[DayLength]]: _dayLengthNs_ }. 1. If _nanoseconds_ < 0, let _sign_ be -1; else, let _sign_ be 1. - 1. If Type(_relativeTo_) is not Object or _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot, then + 1. If _zonedRelativeTo_ is *undefined*, then 1. Return the Record { [[Days]]: truncate(_nanoseconds_ / _dayLengthNs_), [[Nanoseconds]]: (abs(_nanoseconds_) modulo _dayLengthNs_) × _sign_, [[DayLength]]: _dayLengthNs_ }. - 1. Let _startNs_ be ℝ(_relativeTo_.[[Nanoseconds]]). + 1. Let _startNs_ be ℝ(_zonedRelativeTo_.[[Nanoseconds]]). 1. Let _startInstant_ be ! CreateTemporalInstant(ℤ(_startNs_)). - 1. Let _startDateTime_ be ? GetPlainDateTimeFor(_relativeTo_.[[TimeZone]], _startInstant_, _relativeTo_.[[Calendar]]). 1. Let _endNs_ be _startNs_ + _nanoseconds_. 1. If ! IsValidEpochNanoseconds(ℤ(_endNs_)) is *false*, throw a *RangeError* exception. 1. Let _endInstant_ be ! CreateTemporalInstant(ℤ(_endNs_)). - 1. Let _endDateTime_ be ? GetPlainDateTimeFor(_relativeTo_.[[TimeZone]], _endInstant_, _relativeTo_.[[Calendar]]). - 1. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _relativeTo_.[[Calendar]], *"day"*, OrdinaryObjectCreate(*null*)). + 1. Let _startDateTime_ be ? GetPlainDateTimeFor(_zonedRelativeTo_.[[TimeZone]], _startInstant_, _zonedRelativeTo_.[[Calendar]]). + 1. Let _endDateTime_ be ? GetPlainDateTimeFor(_zonedRelativeTo_.[[TimeZone]], _endInstant_, _zonedRelativeTo_.[[Calendar]]). + 1. Let _dateDifference_ be ? DifferenceISODateTime(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], _startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]], _zonedRelativeTo_.[[Calendar]], *"day"*, OrdinaryObjectCreate(*null*)). 1. Let _days_ be _dateDifference_.[[Days]]. - 1. Let _intermediateNs_ be ℝ(? AddZonedDateTime(ℤ(_startNs_), _relativeTo_.[[TimeZone]], _relativeTo_.[[Calendar]], 0, 0, 0, _days_, 0, 0, 0, 0, 0, 0)). + 1. Let _intermediateNs_ be ℝ(? AddZonedDateTime(ℤ(_startNs_), _zonedRelativeTo_.[[TimeZone]], _zonedRelativeTo_.[[Calendar]], 0, 0, 0, _days_, 0, 0, 0, 0, 0, 0)). 1. If _sign_ is 1, then 1. Repeat, while _days_ > 0 and _intermediateNs_ > _endNs_, 1. Set _days_ to _days_ - 1. - 1. Set _intermediateNs_ to ℝ(? AddZonedDateTime(ℤ(_startNs_), _relativeTo_.[[TimeZone]], _relativeTo_.[[Calendar]], 0, 0, 0, _days_, 0, 0, 0, 0, 0, 0)). + 1. Set _intermediateNs_ to ℝ(? AddZonedDateTime(ℤ(_startNs_), _zonedRelativeTo_.[[TimeZone]], _zonedRelativeTo_.[[Calendar]], 0, 0, 0, _days_, 0, 0, 0, 0, 0, 0)). 1. Set _nanoseconds_ to _endNs_ - _intermediateNs_. 1. Let _done_ be *false*. 1. Repeat, while _done_ is *false*, - 1. Let _oneDayFartherNs_ be ℝ(? AddZonedDateTime(ℤ(_intermediateNs_), _relativeTo_.[[TimeZone]], _relativeTo_.[[Calendar]], 0, 0, 0, _sign_, 0, 0, 0, 0, 0, 0)). + 1. Let _oneDayFartherNs_ be ℝ(? AddZonedDateTime(ℤ(_intermediateNs_), _zonedRelativeTo_.[[TimeZone]], _zonedRelativeTo_.[[Calendar]], 0, 0, 0, _sign_, 0, 0, 0, 0, 0, 0)). 1. Set _dayLengthNs_ to _oneDayFartherNs_ - _intermediateNs_. 1. If (_nanoseconds_ - _dayLengthNs_) × _sign_ ≥ 0, then 1. Set _nanoseconds_ to _nanoseconds_ - _dayLengthNs_. @@ -1445,7 +1445,11 @@

1. Let _difference_ be ? DifferenceZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _other_.[[Nanoseconds]], _zonedDateTime_.[[TimeZone]], _zonedDateTime_.[[Calendar]], _settings_.[[LargestUnit]], _resolvedOptions_). 1. If _settings_.[[SmallestUnit]] is *"nanosecond"* and _settings_.[[RoundingIncrement]] is 1, then 1. Return ! CreateTemporalDuration(_sign_ × _difference_.[[Years]], _sign_ × _difference_.[[Months]], _sign_ × _difference_.[[Weeks]], _sign_ × _difference_.[[Days]], _sign_ × _difference_.[[Hours]], _sign_ × _difference_.[[Minutes]], _sign_ × _difference_.[[Seconds]], _sign_ × _difference_.[[Milliseconds]], _sign_ × _difference_.[[Microseconds]], _sign_ × _difference_.[[Nanoseconds]]). - 1. Let _roundResult_ be (? RoundDuration(_difference_.[[Years]], _difference_.[[Months]], _difference_.[[Weeks]], _difference_.[[Days]], _difference_.[[Hours]], _difference_.[[Minutes]], _difference_.[[Seconds]], _difference_.[[Milliseconds]], _difference_.[[Microseconds]], _difference_.[[Nanoseconds]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]], _zonedDateTime_)).[[DurationRecord]]. + 1. Let _plainRelativeTo_ be *undefined*. + 1. If _settings_.[[SmallestUnit]] is one of *"year"*, *"month"*, *"day"*, then + 1. NOTE: The above condition means that the corresponding `Temporal.PlainDate` for _zonedDateTime_ will be used in one of the operations below. + 1. Set _plainRelativeTo_ to ? ToTemporalDate(_zonedDateTime_). + 1. Let _roundResult_ be (? RoundDuration(_difference_.[[Years]], _difference_.[[Months]], _difference_.[[Weeks]], _difference_.[[Days]], _difference_.[[Hours]], _difference_.[[Minutes]], _difference_.[[Seconds]], _difference_.[[Milliseconds]], _difference_.[[Microseconds]], _difference_.[[Nanoseconds]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]], _plainRelativeTo_, _zonedDateTime_)).[[DurationRecord]]. 1. Let _result_ be ? AdjustRoundedDurationDays(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _roundResult_.[[Days]], _roundResult_.[[Hours]], _roundResult_.[[Minutes]], _roundResult_.[[Seconds]], _roundResult_.[[Milliseconds]], _roundResult_.[[Microseconds]], _roundResult_.[[Nanoseconds]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]], _zonedDateTime_). 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]]).