From 4b7e274c1e5f59a2b5da89c841e100432b0d679e 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 | 58 +++++++-- polyfill/lib/ecmascript.mjs | 227 +++++++++++++++++++++++++----------- spec/duration.html | 183 +++++++++++++++-------------- spec/zoneddatetime.html | 12 +- 4 files changed, 309 insertions(+), 171 deletions(-) diff --git a/polyfill/lib/duration.mjs b/polyfill/lib/duration.mjs index fdf87550e7..26e4095f15 100644 --- a/polyfill/lib/duration.mjs +++ b/polyfill/lib/duration.mjs @@ -279,12 +279,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 && @@ -295,13 +298,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.UnbalanceDateDurationRelative( years, months, weeks, days, largestUnit, - relativeTo + plainRelativeTo )); ({ years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.RoundDuration( @@ -318,9 +335,10 @@ export class Duration { roundingIncrement, smallestUnit, roundingMode, - relativeTo + plainRelativeTo, + zonedRelativeTo )); - if (ES.IsTemporalZonedDateTime(relativeTo)) { + if (zonedRelativeTo) { ({ years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.AdjustRoundedDurationDays( years, @@ -336,7 +354,7 @@ export class Duration { roundingIncrement, smallestUnit, roundingMode, - relativeTo + zonedRelativeTo )); ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.BalanceTimeDurationRelative( days, @@ -347,7 +365,7 @@ export class Duration { microseconds, nanoseconds, largestUnit, - relativeTo + zonedRelativeTo )); } else { ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.BalanceTimeDuration( @@ -367,7 +385,7 @@ export class Duration { weeks, days, largestUnit, - relativeTo + plainRelativeTo )); return new Duration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds); @@ -396,12 +414,29 @@ 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.UnbalanceDateDurationRelative(years, months, weeks, days, unit, relativeTo)); + ({ years, months, weeks, days } = ES.UnbalanceDateDurationRelative( + years, + months, + weeks, + days, + unit, + plainRelativeTo + )); // If the unit we're totalling is smaller than `days`, convert days down to that unit. let balanceResult; - if (ES.IsTemporalZonedDateTime(relativeTo)) { - const intermediate = ES.MoveRelativeZonedDateTime(relativeTo, years, months, weeks, 0); + if (zonedRelativeTo) { + const intermediate = ES.MoveRelativeZonedDateTime(zonedRelativeTo, years, months, weeks, 0); balanceResult = ES.BalancePossiblyInfiniteTimeDurationRelative( days, hours, @@ -446,7 +481,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 ff5588b04c..3dde39c9cb 100644 --- a/polyfill/lib/ecmascript.mjs +++ b/polyfill/lib/ecmascript.mjs @@ -3495,16 +3495,12 @@ export function BalancePossiblyInfiniteTimeDurationRelative( return { days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds }; } -export function UnbalanceDateDurationRelative(years, months, weeks, days, largestUnit, relativeTo) { +export function UnbalanceDateDurationRelative(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); @@ -3522,6 +3518,7 @@ export function UnbalanceDateDurationRelative(years, months, weeks, days, larges 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; @@ -3530,12 +3527,12 @@ export function UnbalanceDateDurationRelative(years, months, weeks, days, larges 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); } @@ -3543,12 +3540,18 @@ export function UnbalanceDateDurationRelative(years, months, weeks, days, larges 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); } @@ -3556,7 +3559,12 @@ export function UnbalanceDateDurationRelative(years, months, weeks, days, larges // 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); } @@ -3570,7 +3578,12 @@ export function UnbalanceDateDurationRelative(years, months, weeks, days, larges // 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); } @@ -3578,7 +3591,12 @@ export function UnbalanceDateDurationRelative(years, months, weeks, days, larges // 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); } @@ -3586,7 +3604,12 @@ export function UnbalanceDateDurationRelative(years, months, weeks, days, larges // 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); } @@ -3602,17 +3625,16 @@ export function UnbalanceDateDurationRelative(years, months, weeks, days, larges }; } -export function BalanceDateDurationRelative(years, months, weeks, days, largestUnit, relativeTo) { +export function BalanceDateDurationRelative(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); @@ -3625,72 +3647,109 @@ export function BalanceDateDurationRelative(years, months, weeks, days, largestU 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; } @@ -4481,6 +4540,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, @@ -4495,6 +4557,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 } = @@ -5218,10 +5281,9 @@ export function AdjustRoundedDurationDays( increment, unit, roundingMode, - relativeTo + zonedRelativeTo ) { if ( - !IsTemporalZonedDateTime(relativeTo) || unit === 'year' || unit === 'month' || unit === 'week' || @@ -5251,10 +5313,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, @@ -5309,7 +5371,7 @@ export function AdjustRoundedDurationDays( 0, 0, 0, - relativeTo + zonedRelativeTo )); ({ hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = RoundDuration( years, @@ -5354,11 +5416,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`); } @@ -5368,8 +5431,8 @@ export function RoundDuration( if (unit === 'year' || unit === 'month' || unit === 'week' || unit === 'day') { nanoseconds = TotalDurationNanoseconds(0, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, 0); let deltaDays; - if (IsTemporalZonedDateTime(relativeTo)) { - const intermediate = MoveRelativeZonedDateTime(relativeTo, years, months, weeks, days); + if (zonedRelativeTo) { + const intermediate = MoveRelativeZonedDateTime(zonedRelativeTo, years, months, weeks, days); ({ days: deltaDays, nanoseconds, dayLengthNs } = NanosecondsToDays(nanoseconds, intermediate)); } else { ({ quotient: deltaDays, remainder: nanoseconds } = nanoseconds.divmod(DAY_NANOS)); @@ -5383,32 +5446,36 @@ 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 = GetSlot(CalendarDateUntil(calendar, relativeTo, wholeDaysLater, untilOptions), YEARS); + const yearsPassed = GetSlot(CalendarDateUntil(calendar, plainRelativeTo, wholeDaysLater, untilOptions), YEARS); years += yearsPassed; const yearsPassedDuration = new TemporalDuration(yearsPassed); let daysPassed; - ({ relativeTo, days: daysPassed } = MoveRelativeDate(calendar, relativeTo, yearsPassedDuration, dateAdd)); + ({ relativeTo: plainRelativeTo, days: daysPassed } = MoveRelativeDate( + calendar, + plainRelativeTo, + yearsPassedDuration, + dateAdd + )); 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 @@ -5427,18 +5494,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, @@ -5446,11 +5512,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); @@ -5463,8 +5539,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'. @@ -5472,11 +5547,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 1d080cea95..72bee8aa4f 100644 --- a/spec/duration.html +++ b/spec/duration.html @@ -434,21 +434,28 @@

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 ? UnbalanceDateDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _largestUnit_, _relativeTo_). - 1. Let _roundRecord_ 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_). + 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 ? UnbalanceDateDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _largestUnit_, _plainRelativeTo_). + 1. Let _roundRecord_ 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_). 1. Let _roundResult_ be _roundRecord_.[[DurationRecord]]. - 1. If _relativeTo_ is not *undefined* and _relativeTo_ has an [[InitializedTemporalZonedDateTime]] internal slot, 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_, _relativeTo_). - 1. Let _balanceResult_ be ? BalanceTimeDurationRelative(_roundResult_.[[Days]], _roundResult_.[[Hours]], _roundResult_.[[Minutes]], _roundResult_.[[Seconds]], _roundResult_.[[Milliseconds]], _roundResult_.[[Microseconds]], _roundResult_.[[Nanoseconds]], _largestUnit_, _relativeTo_). + 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 ? BalanceTimeDurationRelative(_roundResult_.[[Days]], _roundResult_.[[Hours]], _roundResult_.[[Minutes]], _roundResult_.[[Seconds]], _roundResult_.[[Milliseconds]], _roundResult_.[[Microseconds]], _roundResult_.[[Nanoseconds]], _largestUnit_, _zonedRelativeTo_). 1. Else, 1. Let _balanceResult_ be ? BalanceTimeDuration(_roundResult_.[[Days]], _roundResult_.[[Hours]], _roundResult_.[[Minutes]], _roundResult_.[[Seconds]], _roundResult_.[[Milliseconds]], _roundResult_.[[Microseconds]], _roundResult_.[[Nanoseconds]], _largestUnit_). - 1. Let _result_ be ? BalanceDateDurationRelative(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _balanceResult_.[[Days]], _largestUnit_, _relativeTo_). + 1. Let _result_ be ? BalanceDateDurationRelative(_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]]). @@ -471,16 +478,23 @@

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 ? UnbalanceDateDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _unit_, _relativeTo_). - 1. If Type(_relativeTo_) is Object and _relativeTo_ has an [[InitializedTemporalZonedDateTime]] internal slot, then - 1. Let _intermediate_ be ? MoveRelativeZonedDateTime(_relativeTo_, _unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], 0). + 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 ? UnbalanceDateDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _unit_, _plainRelativeTo_). + 1. If _zonedRelativeTo_ is not *undefined*, then + 1. Let _intermediate_ be ? MoveRelativeZonedDateTime(_zonedRelativeTo_, _unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], 0). 1. Let _balanceResult_ be ? BalancePossiblyInfiniteTimeDurationRelative(_unbalanceResult_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _unit_, _intermediate_). 1. Else, 1. Let _balanceResult_ be BalancePossiblyInfiniteTimeDuration(_unbalanceResult_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _unit_). 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. Return 𝔽(_roundRecord_.[[Total]]). @@ -1357,7 +1371,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, )

@@ -1374,12 +1388,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 @@ -1389,15 +1403,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 @@ -1405,13 +1420,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, @@ -1423,18 +1438,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_). @@ -1449,7 +1464,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, )

@@ -1461,71 +1476,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, @@ -1534,14 +1548,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_). @@ -1696,7 +1710,8 @@

_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, ): either a normal completion containing a Record with fields [[DurationRecord]] (a Duration Record) and [[Total]] (a mathematical value), or a throw completion

@@ -1708,13 +1723,14 @@

- 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. 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. Let _fractionalDays_ be _days_ + _result_.[[Days]] + _result_.[[Nanoseconds]] / _result_.[[DayLength]]. 1. Else, @@ -1726,85 +1742,82 @@

1. Assert: _fractionalDays_ is not used below. 1. Let _total_ be ~unset~. 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. Set _fractionalDays_ to _fractionalDays_ + _monthsWeeksInDays_. - 1. Let _wholeDaysDuration_ be ? CreateTemporalDuration(0, 0, 0, truncate(_fractionalDays_), 0, 0, 0, 0, 0, 0). - 1. Let _wholeDaysLater_ be ? CalendarDateAdd(_calendar_, _relativeTo_, _wholeDaysDuration_, *undefined*, _dateAdd_). + 1. Let _wholeDaysDuration_ be ? CreateTemporalDuration(0, 0, 0, truncate(_days_), 0, 0, 0, 0, 0, 0). + 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 _yearsDuration_ be ! CreateTemporalDuration(_yearsPassed_, 0, 0, 0, 0, 0, 0, 0, 0, 0). - 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _relativeTo_, _yearsDuration_, _dateAdd_). - 1. Set _relativeTo_ to _moveResult_.[[RelativeTo]]. + 1. Let _moveResult_ be ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _yearsDuration_, _dateAdd_). + 1. Set _plainRelativeTo_ to _moveResult_.[[RelativeTo]]. 1. Let _daysPassed_ be _moveResult_.[[Days]]. 1. Set _fractionalDays_ to _fractionalDays_ - _daysPassed_. 1. If _fractionalDays_ < 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. Set _moveResult_ to ? MoveRelativeDate(_calendar_, _relativeTo_, _oneYear_, _dateAdd_). + 1. Set _moveResult_ to ? MoveRelativeDate(_calendar_, _plainRelativeTo_, _oneYear_, _dateAdd_). 1. Let _oneYearDays_ be _moveResult_.[[Days]]. 1. Let _fractionalYears_ be _years_ + _fractionalDays_ / abs(_oneYearDays_). 1. Set _years_ to RoundNumberToIncrement(_fractionalYears_, _increment_, _roundingMode_). 1. Set _total_ to _fractionalYears_. 1. Set _months_ and _weeks_ 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. Set _fractionalDays_ to _fractionalDays_ + _weeksInDays_. 1. If _fractionalDays_ < 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(_fractionalDays_) ≥ abs(_oneMonthDays_), 1. Set _months_ to _months_ + _sign_. 1. Set _fractionalDays_ to _fractionalDays_ - _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_ + _fractionalDays_ / abs(_oneMonthDays_). 1. Set _months_ to RoundNumberToIncrement(_fractionalMonths_, _increment_, _roundingMode_). 1. Set _total_ to _fractionalMonths_. 1. Set _weeks_ 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 _fractionalDays_ < 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(_fractionalDays_) ≥ abs(_oneWeekDays_), 1. Set _weeks_ to _weeks_ + _sign_. 1. Set _fractionalDays_ to _fractionalDays_ - _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_ + _fractionalDays_ / abs(_oneWeekDays_). 1. Set _weeks_ to RoundNumberToIncrement(_fractionalWeeks_, _increment_, _roundingMode_). @@ -1864,7 +1877,7 @@

_increment_: an integer, _unit_: a String, _roundingMode_: a String, - _relativeTo_: *undefined*, a Temporal.PlainDate, or a Temporal.ZonedDateTime, + _zonedRelativeTo_: a Temporal.ZonedDateTime, ): either a normal completion containing a Duration Record, or a throw completion

@@ -1876,19 +1889,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. Let _oneDayLess_ be _timeRemainderNs_ - _dayLengthNs_. 1. If _oneDayLess_ × _direction_ < 0, then 1. Return ! CreateDurationRecord(_years_, _months_, _weeks_, _days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_). - 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 ! RoundDuration(_adjustedDateDuration_.[[Years]], _adjustedDateDuration_.[[Months]], _adjustedDateDuration_.[[Weeks]], _adjustedDateDuration_.[[Days]], 0, 0, 0, 0, 0, _oneDayLess_, _increment_, _unit_, _roundingMode_). 1. Set _adjustedTimeDuration_ to ? BalanceTimeDuration(0, _adjustedTimeDuration_.[[Hours]], _adjustedTimeDuration_.[[Minutes]], _adjustedTimeDuration_.[[Seconds]], _adjustedTimeDuration_.[[Milliseconds]], _adjustedTimeDuration_.[[Microseconds]], _adjustedTimeDuration_.[[Nanoseconds]], *"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 5628458ae8..6661286a80 100644 --- a/spec/zoneddatetime.html +++ b/spec/zoneddatetime.html @@ -1361,7 +1361,7 @@

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.
@@ -1371,12 +1371,12 @@

1. If _nanoseconds_ < 0, let _sign_ be -1; else, let _sign_ be 1. 1. Let _startNs_ be ℝ(_zonedRelativeTo_.[[Nanoseconds]]). 1. Let _startInstant_ be ! CreateTemporalInstant(ℤ(_startNs_)). - 1. Let _startDateTime_ be ? GetPlainDateTimeFor(_zonedRelativeTo_.[[TimeZone]], _startInstant_, _zonedRelativeTo_.[[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 _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]], _relativeTo_.[[Calendar]], *"day"*, OrdinaryObjectCreate(*null*)). + 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_), _zonedRelativeTo_.[[TimeZone]], _zonedRelativeTo_.[[Calendar]], 0, 0, 0, _days_, 0, 0, 0, 0, 0, 0)). 1. If _sign_ is 1, then @@ -1437,7 +1437,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 _roundRecord_ 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_). + 1. Let _plainRelativeTo_ be *undefined*. + 1. If _settings_.[[SmallestUnit]] is one of *"year"*, *"month"*, *"week"*, 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 _roundRecord_ 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_). 1. Let _roundResult_ be _roundRecord_.[[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]]).