diff --git a/polyfill/lib/duration.mjs b/polyfill/lib/duration.mjs
index 1b3a790646..0722ec9374 100644
--- a/polyfill/lib/duration.mjs
+++ b/polyfill/lib/duration.mjs
@@ -1,7 +1,7 @@
/* global __debug__ */
import * as ES from './ecmascript.mjs';
-import { MakeIntrinsicClass } from './intrinsicclass.mjs';
+import { GetIntrinsic, MakeIntrinsicClass } from './intrinsicclass.mjs';
import { CalendarMethodRecord } from './methodrecord.mjs';
import {
YEARS,
@@ -17,6 +17,9 @@ import {
CALENDAR,
INSTANT,
EPOCHNANOSECONDS,
+ ISO_YEAR,
+ ISO_MONTH,
+ ISO_DAY,
CreateSlots,
GetSlot,
SetSlot
@@ -327,79 +330,106 @@ export class Duration {
'dateUntil'
]);
- ({ years, months, weeks, days } = ES.UnbalanceDateDurationRelative(
- years,
- months,
- weeks,
- days,
- largestUnit,
- plainRelativeTo,
- calendarRec
- ));
let norm = TimeDuration.normalize(hours, minutes, seconds, milliseconds, microseconds, nanoseconds);
- ({ years, months, weeks, days, norm } = ES.RoundDuration(
- years,
- months,
- weeks,
- days,
- norm,
- roundingIncrement,
- smallestUnit,
- roundingMode,
- plainRelativeTo,
- calendarRec,
- zonedRelativeTo,
- timeZoneRec,
- precalculatedPlainDateTime
- ));
+
if (zonedRelativeTo) {
- ({ years, months, weeks, days, norm } = ES.AdjustRoundedDurationDays(
- years,
- months,
- weeks,
- days,
- norm,
- roundingIncrement,
- smallestUnit,
- roundingMode,
- zonedRelativeTo,
- calendarRec,
+ const relativeEpochNs = GetSlot(zonedRelativeTo, EPOCHNANOSECONDS);
+ const targetEpochNs = ES.AddZonedDateTime(
+ GetSlot(zonedRelativeTo, INSTANT),
timeZoneRec,
- precalculatedPlainDateTime
- ));
- const intermediate = ES.MoveRelativeZonedDateTime(
- zonedRelativeTo,
calendarRec,
- timeZoneRec,
years,
months,
weeks,
- 0,
- precalculatedPlainDateTime
- );
- ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.BalanceTimeDurationRelative(
days,
norm,
- largestUnit,
- intermediate,
- timeZoneRec
- ));
+ precalculatedPlainDateTime
+ );
+ ({ years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } =
+ ES.DifferenceZonedDateTimeWithRounding(
+ relativeEpochNs,
+ targetEpochNs,
+ plainRelativeTo,
+ calendarRec,
+ zonedRelativeTo,
+ timeZoneRec,
+ precalculatedPlainDateTime,
+ ObjectCreate(null),
+ largestUnit,
+ roundingIncrement,
+ smallestUnit,
+ roundingMode
+ ));
+ } else if (plainRelativeTo) {
+ let targetTime = ES.AddTime(0, 0, 0, 0, 0, 0, norm);
+
+ // Delegate the date part addition to the calendar
+ const TemporalDuration = GetIntrinsic('%Temporal.Duration%');
+ const dateDuration = new TemporalDuration(years, months, weeks, days + targetTime.deltaDays, 0, 0, 0, 0, 0, 0);
+ const targetDate = ES.AddDate(calendarRec, plainRelativeTo, dateDuration);
+
+ ({ years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } =
+ ES.DifferencePlainDateTimeWithRounding(
+ plainRelativeTo,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ GetSlot(targetDate, ISO_YEAR),
+ GetSlot(targetDate, ISO_MONTH),
+ GetSlot(targetDate, ISO_DAY),
+ targetTime.hour,
+ targetTime.minute,
+ targetTime.second,
+ targetTime.millisecond,
+ targetTime.microsecond,
+ targetTime.nanosecond,
+ calendarRec,
+ largestUnit,
+ roundingIncrement,
+ smallestUnit,
+ roundingMode
+ ));
} else {
- ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = ES.BalanceTimeDuration(
- norm.add24HourDays(days),
- largestUnit
- ));
+ if (calendarUnitsPresent) {
+ throw new RangeError('a starting point is required for years, months, or weeks balancing');
+ }
+ if (largestUnit === 'year' || largestUnit === 'month' || largestUnit === 'week') {
+ throw new RangeError(`a starting point is required for ${largestUnit}s balancing`);
+ }
+ if (smallestUnit === 'year' || smallestUnit === 'month' || smallestUnit === 'week') {
+ throw new RangeError(`a starting point is required for ${smallestUnit}s rounding`);
+ }
+
+ const isoCalendarRec = new CalendarMethodRecord('iso8601', ['dateAdd', 'dateUntil']);
+ const target = ES.AddDateTime(1970, 1, 1, 0, 0, 0, 0, 0, 0, isoCalendarRec, years, months, weeks, days, norm);
+ ({ years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } =
+ ES.DifferencePlainDateTimeWithRounding(
+ undefined,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ target.year,
+ target.month,
+ target.day,
+ target.hour,
+ target.minute,
+ target.second,
+ target.millisecond,
+ target.microsecond,
+ target.nanosecond,
+ isoCalendarRec,
+ largestUnit,
+ roundingIncrement,
+ smallestUnit,
+ roundingMode
+ ));
}
- ({ years, months, weeks, days } = ES.BalanceDateDurationRelative(
- years,
- months,
- weeks,
- days,
- largestUnit,
- smallestUnit,
- plainRelativeTo,
- calendarRec
- ));
return new Duration(years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds);
}
@@ -446,69 +476,100 @@ export class Duration {
'dateUntil'
]);
- // Convert larger units down to days
- ({ years, months, weeks, days } = ES.UnbalanceDateDurationRelative(
- years,
- months,
- weeks,
- days,
- unit,
- plainRelativeTo,
- calendarRec
- ));
- let norm;
- // If the unit we're totalling is smaller than `days`, convert days down to that unit.
+ let norm = TimeDuration.normalize(hours, minutes, seconds, milliseconds, microseconds, nanoseconds);
+ let total;
if (zonedRelativeTo) {
- const intermediate = ES.MoveRelativeZonedDateTime(
- zonedRelativeTo,
- calendarRec,
+ const relativeEpochNs = GetSlot(zonedRelativeTo, EPOCHNANOSECONDS);
+ const targetEpochNs = ES.AddZonedDateTime(
+ GetSlot(zonedRelativeTo, INSTANT),
timeZoneRec,
+ calendarRec,
years,
months,
weeks,
- 0,
+ days,
+ norm,
precalculatedPlainDateTime
);
- norm = TimeDuration.normalize(hours, minutes, seconds, milliseconds, microseconds, nanoseconds);
-
- // Inline BalanceTimeDurationRelative, without the final balance step
- const start = GetSlot(intermediate, INSTANT);
- const startNs = GetSlot(intermediate, EPOCHNANOSECONDS);
- let intermediateNs = startNs;
- let startDt;
- if (days !== 0) {
- startDt = ES.GetPlainDateTimeFor(timeZoneRec, start, 'iso8601');
- intermediateNs = ES.AddDaysToZonedDateTime(start, startDt, timeZoneRec, 'iso8601', days).epochNs;
+ ({ total } = ES.DifferenceZonedDateTimeWithRounding(
+ relativeEpochNs,
+ targetEpochNs,
+ plainRelativeTo,
+ calendarRec,
+ zonedRelativeTo,
+ timeZoneRec,
+ precalculatedPlainDateTime,
+ ObjectCreate(null),
+ unit,
+ 1,
+ unit,
+ 'trunc'
+ ));
+ } else if (plainRelativeTo) {
+ let targetTime = ES.AddTime(0, 0, 0, 0, 0, 0, norm);
+
+ // Delegate the date part addition to the calendar
+ const TemporalDuration = GetIntrinsic('%Temporal.Duration%');
+ const dateDuration = new TemporalDuration(years, months, weeks, days + targetTime.deltaDays, 0, 0, 0, 0, 0, 0);
+ const targetDate = ES.AddDate(calendarRec, plainRelativeTo, dateDuration);
+
+ ({ total } = ES.DifferencePlainDateTimeWithRounding(
+ plainRelativeTo,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ GetSlot(targetDate, ISO_YEAR),
+ GetSlot(targetDate, ISO_MONTH),
+ GetSlot(targetDate, ISO_DAY),
+ targetTime.hour,
+ targetTime.minute,
+ targetTime.second,
+ targetTime.millisecond,
+ targetTime.microsecond,
+ targetTime.nanosecond,
+ calendarRec,
+ unit,
+ 1,
+ unit,
+ 'trunc'
+ ));
+ } else {
+ if (years !== 0 || months !== 0 || weeks !== 0) {
+ throw new RangeError('a starting point is required for years, months, or weeks total');
}
- const endNs = ES.AddInstant(intermediateNs, norm);
- norm = TimeDuration.fromEpochNsDiff(endNs, startNs);
- if (ES.IsCalendarUnit(unit) || unit === 'day') {
- if (!norm.isZero()) startDt ??= ES.GetPlainDateTimeFor(timeZoneRec, start, 'iso8601');
- ({ days, norm } = ES.NormalizedTimeDurationToDays(norm, intermediate, timeZoneRec, startDt));
- } else {
- days = 0;
+ if (unit === 'year' || unit === 'month' || unit === 'week') {
+ throw new RangeError(`a starting point is required for ${unit}s total`);
}
- } else {
- norm = TimeDuration.normalize(hours, minutes, seconds, milliseconds, microseconds, nanoseconds);
- norm = norm.add24HourDays(days);
- days = 0;
+
+ const isoCalendarRec = new CalendarMethodRecord('iso8601', ['dateAdd', 'dateUntil']);
+ const target = ES.AddDateTime(1970, 1, 1, 0, 0, 0, 0, 0, 0, isoCalendarRec, years, months, weeks, days, norm);
+ ({ total } = ES.DifferencePlainDateTimeWithRounding(
+ undefined,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ target.year,
+ target.month,
+ target.day,
+ target.hour,
+ target.minute,
+ target.second,
+ target.millisecond,
+ target.microsecond,
+ target.nanosecond,
+ isoCalendarRec,
+ unit,
+ 1,
+ unit,
+ 'trunc'
+ ));
}
- // Finally, truncate to the correct unit and calculate remainder
- const { total } = ES.RoundDuration(
- years,
- months,
- weeks,
- days,
- norm,
- 1,
- unit,
- 'trunc',
- plainRelativeTo,
- calendarRec,
- zonedRelativeTo,
- timeZoneRec,
- precalculatedPlainDateTime
- );
return total;
}
toString(options = undefined) {
diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs
index 14f3355ba1..2f698d9642 100644
--- a/polyfill/lib/ecmascript.mjs
+++ b/polyfill/lib/ecmascript.mjs
@@ -3765,9 +3765,7 @@ export function DifferenceTime(h1, min1, s1, ms1, µs1, ns1, h2, min2, s2, ms2,
export function DifferenceInstant(ns1, ns2, increment, smallestUnit, roundingMode) {
const diff = TimeDuration.fromEpochNsDiff(ns2, ns1);
- if (smallestUnit === 'nanosecond' && increment === 1) return diff;
-
- return RoundDuration(0, 0, 0, 0, diff, increment, smallestUnit, roundingMode).norm;
+ return RoundDuration(0, 0, 0, 0, diff, increment, smallestUnit, roundingMode);
}
export function DifferenceDate(calendarRec, plainDate1, plainDate2, options) {
@@ -3909,6 +3907,212 @@ export function DifferenceZonedDateTime(
return { years, months, weeks, days, norm };
}
+export function DifferencePlainDateTimeWithRounding(
+ plainDate1,
+ h1,
+ min1,
+ s1,
+ ms1,
+ µs1,
+ ns1,
+ y2,
+ mon2,
+ d2,
+ h2,
+ min2,
+ s2,
+ ms2,
+ µs2,
+ ns2,
+ calendarRec,
+ largestUnit,
+ roundingIncrement,
+ smallestUnit,
+ roundingMode,
+ resolvedOptions
+) {
+ const y1 = plainDate1 ? GetSlot(plainDate1, ISO_YEAR) : 1970;
+ const mon1 = plainDate1 ? GetSlot(plainDate1, ISO_MONTH) : 1;
+ const d1 = plainDate1 ? GetSlot(plainDate1, ISO_DAY) : 1;
+ if (CompareISODateTime(y1, mon1, d1, h1, min1, s1, ms1, µs1, ns1, y2, mon2, d2, h2, min2, s2, ms2, µs2, ns2) == 0) {
+ return {
+ years: 0,
+ months: 0,
+ weeks: 0,
+ days: 0,
+ hours: 0,
+ minutes: 0,
+ seconds: 0,
+ milliseconds: 0,
+ microseconds: 0,
+ nanoseconds: 0,
+ total: 0
+ };
+ }
+
+ let { years, months, weeks, days, norm } = DifferenceISODateTime(
+ y1,
+ mon1,
+ d1,
+ h1,
+ min1,
+ s1,
+ ms1,
+ µs1,
+ ns1,
+ y2,
+ mon2,
+ d2,
+ h2,
+ min2,
+ s2,
+ ms2,
+ µs2,
+ ns2,
+ calendarRec,
+ largestUnit,
+ resolvedOptions
+ );
+
+ const roundingIsNoop = smallestUnit === 'nanosecond' && roundingIncrement === 1;
+ if (roundingIsNoop) {
+ const normWithDays = norm.add24HourDays(days);
+ let hours, minutes, seconds, milliseconds, microseconds, nanoseconds;
+ ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration(
+ normWithDays,
+ largestUnit
+ ));
+ return { years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds };
+ }
+
+ let total;
+ ({ years, months, weeks, days, norm, total } = RoundDuration(
+ years,
+ months,
+ weeks,
+ days,
+ norm,
+ roundingIncrement,
+ smallestUnit,
+ roundingMode,
+ plainDate1,
+ calendarRec
+ ));
+ const normWithDays = norm.add24HourDays(days);
+ let hours, minutes, seconds, milliseconds, microseconds, nanoseconds;
+ ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration(
+ normWithDays,
+ largestUnit
+ ));
+ ({ years, months, weeks, days } = BalanceDateDurationRelative(
+ years,
+ months,
+ weeks,
+ days,
+ largestUnit,
+ smallestUnit,
+ plainDate1,
+ calendarRec
+ ));
+ return { years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, total };
+}
+
+export function DifferenceZonedDateTimeWithRounding(
+ ns1,
+ ns2,
+ plainRelativeTo,
+ calendarRec,
+ zonedDateTime,
+ timeZoneRec,
+ precalculatedPlainDateTime,
+ resolvedOptions,
+ largestUnit,
+ roundingIncrement,
+ smallestUnit,
+ roundingMode
+) {
+ if (!IsCalendarUnit(largestUnit) && largestUnit !== 'day') {
+ // The user is only asking for a time difference, so return difference of instants.
+ const { norm, total } = DifferenceInstant(ns1, ns2, roundingIncrement, smallestUnit, largestUnit, roundingMode);
+ const { hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration(norm, largestUnit);
+ return {
+ years: 0,
+ months: 0,
+ weeks: 0,
+ days: 0,
+ hours,
+ minutes,
+ seconds,
+ milliseconds,
+ microseconds,
+ nanoseconds,
+ total
+ };
+ }
+
+ resolvedOptions.largestUnit = largestUnit;
+ let { years, months, weeks, days, norm } = DifferenceZonedDateTime(
+ ns1,
+ ns2,
+ timeZoneRec,
+ calendarRec,
+ largestUnit,
+ resolvedOptions,
+ precalculatedPlainDateTime
+ );
+
+ const roundingIsNoop = smallestUnit === 'nanosecond' && roundingIncrement === 1;
+ if (roundingIsNoop) {
+ const { hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration(norm, 'hour');
+ return { years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds };
+ }
+
+ let total;
+ ({ years, months, weeks, days, norm, total } = RoundDuration(
+ years,
+ months,
+ weeks,
+ days,
+ norm,
+ roundingIncrement,
+ smallestUnit,
+ roundingMode,
+ plainRelativeTo,
+ calendarRec,
+ zonedDateTime,
+ timeZoneRec,
+ precalculatedPlainDateTime
+ ));
+ ({ years, months, weeks, days, norm } = AdjustRoundedDurationDays(
+ years,
+ months,
+ weeks,
+ days,
+ norm,
+ roundingIncrement,
+ smallestUnit,
+ roundingMode,
+ zonedDateTime,
+ calendarRec,
+ timeZoneRec,
+ precalculatedPlainDateTime
+ ));
+ ({ years, months, weeks, days } = BalanceDateDurationRelative(
+ years,
+ months,
+ weeks,
+ days,
+ largestUnit,
+ smallestUnit,
+ plainRelativeTo,
+ calendarRec
+ ));
+ CombineDateAndNormalizedTimeDuration(years, months, weeks, days, norm);
+ const { hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration(norm, 'hour');
+
+ return { years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, total };
+}
+
export function GetDifferenceSettings(op, options, group, disallowed, fallbackSmallest, smallestLargestDefaultUnit) {
const ALLOWED_UNITS = SINGULAR_PLURAL_UNITS.reduce((allowed, unitInfo) => {
const p = unitInfo[0];
@@ -3963,7 +4167,7 @@ export function DifferenceTemporalInstant(operation, instant, other, options) {
const onens = GetSlot(instant, EPOCHNANOSECONDS);
const twons = GetSlot(other, EPOCHNANOSECONDS);
- const norm = DifferenceInstant(
+ const { norm } = DifferenceInstant(
onens,
twons,
settings.roundingIncrement,
@@ -4073,68 +4277,33 @@ export function DifferenceTemporalPlainDateTime(operation, plainDateTime, other,
return new Duration();
}
+ const plainDate1 = TemporalDateTimeToDate(plainDateTime);
const calendarRec = new CalendarMethodRecord(calendar, ['dateAdd', 'dateUntil']);
-
- let { years, months, weeks, days, norm } = DifferenceISODateTime(
- GetSlot(plainDateTime, ISO_YEAR),
- GetSlot(plainDateTime, ISO_MONTH),
- GetSlot(plainDateTime, ISO_DAY),
- GetSlot(plainDateTime, ISO_HOUR),
- GetSlot(plainDateTime, ISO_MINUTE),
- GetSlot(plainDateTime, ISO_SECOND),
- GetSlot(plainDateTime, ISO_MILLISECOND),
- GetSlot(plainDateTime, ISO_MICROSECOND),
- GetSlot(plainDateTime, ISO_NANOSECOND),
- GetSlot(other, ISO_YEAR),
- GetSlot(other, ISO_MONTH),
- GetSlot(other, ISO_DAY),
- GetSlot(other, ISO_HOUR),
- GetSlot(other, ISO_MINUTE),
- GetSlot(other, ISO_SECOND),
- GetSlot(other, ISO_MILLISECOND),
- GetSlot(other, ISO_MICROSECOND),
- GetSlot(other, ISO_NANOSECOND),
- calendarRec,
- settings.largestUnit,
- resolvedOptions
- );
-
- let hours, minutes, seconds, milliseconds, microseconds, nanoseconds;
- const roundingIsNoop = settings.smallestUnit === 'nanosecond' && settings.roundingIncrement === 1;
- if (!roundingIsNoop) {
- const relativeTo = TemporalDateTimeToDate(plainDateTime);
- ({ years, months, weeks, days, norm } = RoundDuration(
- years,
- months,
- weeks,
- days,
- norm,
+ const { years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } =
+ DifferencePlainDateTimeWithRounding(
+ plainDate1,
+ GetSlot(plainDateTime, ISO_HOUR),
+ GetSlot(plainDateTime, ISO_MINUTE),
+ GetSlot(plainDateTime, ISO_SECOND),
+ GetSlot(plainDateTime, ISO_MILLISECOND),
+ GetSlot(plainDateTime, ISO_MICROSECOND),
+ GetSlot(plainDateTime, ISO_NANOSECOND),
+ GetSlot(other, ISO_YEAR),
+ GetSlot(other, ISO_MONTH),
+ GetSlot(other, ISO_DAY),
+ GetSlot(other, ISO_HOUR),
+ GetSlot(other, ISO_MINUTE),
+ GetSlot(other, ISO_SECOND),
+ GetSlot(other, ISO_MILLISECOND),
+ GetSlot(other, ISO_MICROSECOND),
+ GetSlot(other, ISO_NANOSECOND),
+ calendarRec,
+ settings.largestUnit,
settings.roundingIncrement,
settings.smallestUnit,
settings.roundingMode,
- relativeTo,
- calendarRec
- ));
- ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration(
- norm.add24HourDays(days),
- settings.largestUnit
- ));
- ({ years, months, weeks, days } = BalanceDateDurationRelative(
- years,
- months,
- weeks,
- days,
- settings.largestUnit,
- settings.smallestUnit,
- relativeTo,
- calendarRec
- ));
- } else {
- ({ days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration(
- norm.add24HourDays(days),
- settings.largestUnit
- ));
- }
+ resolvedOptions
+ );
return new Duration(
sign * years,
@@ -4290,7 +4459,13 @@ export function DifferenceTemporalZonedDateTime(operation, zonedDateTime, other,
months = 0;
weeks = 0;
days = 0;
- const norm = DifferenceInstant(ns1, ns2, settings.roundingIncrement, settings.smallestUnit, settings.roundingMode);
+ const { norm } = DifferenceInstant(
+ ns1,
+ ns2,
+ settings.roundingIncrement,
+ settings.smallestUnit,
+ settings.roundingMode
+ );
({ hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration(
norm,
settings.largestUnit
@@ -4319,66 +4494,21 @@ export function DifferenceTemporalZonedDateTime(operation, zonedDateTime, other,
);
const plainRelativeTo = TemporalDateTimeToDate(precalculatedPlainDateTime);
- resolvedOptions.largestUnit = settings.largestUnit;
- let norm;
- ({ years, months, weeks, days, norm } = DifferenceZonedDateTime(
- ns1,
- ns2,
- timeZoneRec,
- calendarRec,
- settings.largestUnit,
- resolvedOptions,
- precalculatedPlainDateTime
- ));
-
- const roundingIsNoop = settings.smallestUnit === 'nanosecond' && settings.roundingIncrement === 1;
- if (!roundingIsNoop) {
- ({ years, months, weeks, days, norm } = RoundDuration(
- years,
- months,
- weeks,
- days,
- norm,
- settings.roundingIncrement,
- settings.smallestUnit,
- settings.roundingMode,
+ ({ years, months, weeks, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds } =
+ DifferenceZonedDateTimeWithRounding(
+ ns1,
+ ns2,
plainRelativeTo,
calendarRec,
zonedDateTime,
timeZoneRec,
- precalculatedPlainDateTime
- ));
- let deltaDays;
- ({ days: deltaDays, norm } = NormalizedTimeDurationToDays(norm, zonedDateTime, timeZoneRec));
- days += deltaDays;
- ({ years, months, weeks, days, norm } = AdjustRoundedDurationDays(
- years,
- months,
- weeks,
- days,
- norm,
- settings.roundingIncrement,
- settings.smallestUnit,
- settings.roundingMode,
- zonedDateTime,
- calendarRec,
- timeZoneRec,
- precalculatedPlainDateTime
- ));
- // BalanceTimeDuration already performed in AdjustRoundedDurationDays
- ({ years, months, weeks, days } = BalanceDateDurationRelative(
- years,
- months,
- weeks,
- days,
+ precalculatedPlainDateTime,
+ resolvedOptions,
settings.largestUnit,
+ settings.roundingIncrement,
settings.smallestUnit,
- plainRelativeTo,
- calendarRec
+ settings.roundingMode
));
- CombineDateAndNormalizedTimeDuration(years, months, weeks, days, norm);
- }
- ({ hours, minutes, seconds, milliseconds, microseconds, nanoseconds } = BalanceTimeDuration(norm, 'hour'));
}
return new Duration(
diff --git a/spec/duration.html b/spec/duration.html
index ea593b18e9..d1cb3c691c 100644
--- a/spec/duration.html
+++ b/spec/duration.html
@@ -468,19 +468,25 @@
Temporal.Duration.prototype.round ( _roundTo_ )
1. Set _precalculatedPlainDateTime_ to ? GetPlainDateTimeFor(_timeZoneRec_, _instant_, _zonedRelativeTo_.[[Calendar]]).
1. Set _plainRelativeTo_ to ! CreateTemporalDate(_precalculatedPlainDateTime_.[[ISOYear]], _precalculatedPlainDateTime_.[[ISOMonth]], _precalculatedPlainDateTime_.[[ISODay]], _zonedRelativeTo_.[[Calendar]]).
1. Let _calendarRec_ be ? CreateCalendarMethodsRecordFromRelativeTo(_plainRelativeTo_, _zonedRelativeTo_, « ~date-add~, ~date-until~ »).
- 1. Let _unbalanceResult_ be ? UnbalanceDateDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _largestUnit_, _plainRelativeTo_, _calendarRec_).
1. Let _norm_ be NormalizeTimeDuration(_duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]]).
- 1. Let _roundRecord_ be ? RoundDuration(_unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], _unbalanceResult_.[[Days]], _norm_, _roundingIncrement_, _smallestUnit_, _roundingMode_, _plainRelativeTo_, _calendarRec_, _zonedRelativeTo_, _timeZoneRec_, _precalculatedPlainDateTime_).
- 1. Let _roundResult_ be _roundRecord_.[[NormalizedDuration]].
+ 1. Let _emptyOptions_ be OrdinaryObjectCreate(*null*).
1. If _zonedRelativeTo_ is not *undefined*, then
- 1. Set _roundResult_ to ? AdjustRoundedDurationDays(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _roundResult_.[[Days]], _roundResult_.[[NormalizedTime]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _zonedRelativeTo_, _calendarRec_, _timeZoneRec_, _precalculatedPlainDateTime_).
- 1. Let _intermediate_ be ? MoveRelativeZonedDateTime(_zonedRelativeTo_, _calendarRec_, _timeZoneRec_, _roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], 0, _precalculatedPlainDateTime_).
- 1. Let _balanceResult_ be ? BalanceTimeDurationRelative(_roundResult_.[[Days]], _roundResult_.[[NormalizedTime]], _largestUnit_, _intermediate_, _timeZoneRec_, _precalculatedPlainDateTime_).
+ 1. Let _relativeEpochNs_ be _zonedRelativeTo_.[[Nanoseconds]].
+ 1. Let _relativeInstant_ be ! CreateTemporalInstant(_relativeEpochNs_).
+ 1. Let _targetEpochNs_ be ? AddZonedDateTime(_relativeInstant_, _timeZoneRec_, _calendarRec_, _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _norm_, _precalculatedPlainDateTime_).
+ 1. Let _roundRecord_ be ? DifferenceZonedDateTimeWithRounding(_relativeEpochNs_, _targetEpochNs_, _plainRelativeTo_, _calendarRec_, _zonedRelativeTo_, _timeZoneRec_, _precalculatedPlainDateTime_, _emptyOptions_, _largestUnit_, _roundingIncrement_, _smallestUnit_, _roundingMode_).
+ 1. Else if _plainRelativeTo_ is not *undefined*, then
+ 1. Let _targetTime_ be AddTime(0, 0, 0, 0, 0, 0, _norm_).
+ 1. Let _dateDuration_ be ? CreateTemporalDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]] + _targetTime_.[[Days]], 0, 0, 0, 0, 0, 0).
+ 1. Let _targetDate_ be ? AddDate(_calendarRec_, _plainRelativeTo_, _dateDuration_).
+ 1. Let _roundRecord_ be ? DifferencePlainDateTimeWithRounding(_plainRelativeTo_, 0, 0, 0, 0, 0, 0, _targetDate_.[[ISOYear]], _targetDate_.[[ISOMonth]], _targetDate_.[[ISODay]], _targetTime_.[[Hours]], _targetTime_.[[Minutes]], _targetTime_.[[Seconds]], _targetTime_.[[Milliseconds]], _targetTime_.[[Microseconds]], _targetTime_.[[Nanoseconds]], _calendarRec_, _largestUnit_, _roundingIncrement_, _smallestUnit_, _roundingMode_, _emptyOptions_).
1. Else,
- 1. Let _normWithDays_ be ? Add24HourDaysToNormalizedTimeDuration(_roundResult_.[[NormalizedTime]], _roundResult_.[[Days]]).
- 1. Let _balanceResult_ be BalanceTimeDuration(_normWithDays_, _largestUnit_).
- 1. Let _result_ be ? BalanceDateDurationRelative(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _balanceResult_.[[Days]], _largestUnit_, _smallestUnit_, _plainRelativeTo_, _calendarRec_).
- 1. Return ! CreateTemporalDuration(_result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _result_.[[Days]], _balanceResult_.[[Hours]], _balanceResult_.[[Minutes]], _balanceResult_.[[Seconds]], _balanceResult_.[[Milliseconds]], _balanceResult_.[[Microseconds]], _balanceResult_.[[Nanoseconds]]).
+ 1. If _calendarUnitsPresent_ is *true*, or IsCalendarUnit(_largestUnit_) is *true*, or IsCalendarUnit(_smallestUnit_) is *true*, throw a *RangeError* exception.
+ 1. Let _isoCalendarRec_ be ! CreateCalendarMethodsRecord(*"iso8601"*, « ~date-add~, ~date-until~ »).
+ 1. Let _target_ be ? AddDateTime(1970, 1, 1, 0, 0, 0, 0, 0, 0, _isoCalendarRec_, _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _norm_, *undefined*).
+ 1. Let _roundRecord_ be ? DifferencePlainDateTimeWithRounding(~empty~, 0, 0, 0, 0, 0, 0, _target_.[[ISOYear]], _target_.[[ISOMonth]], _target_.[[ISODay]], _target_.[[ISOHour]], _target_.[[ISOMinute]], _target_.[[ISOSecond]], _target_.[[ISOMillisecond]], _target_.[[ISOMicrosecond]], _target_.[[ISONanosecond]], _isoCalendarRec_, _largestUnit_, _roundingIncrement_, _smallestUnit_, _roundingMode_, _emptyOptions_).
+ 1. Let _roundResult_ be _roundRecord_.[[DurationRecord]].
+ 1. Return ! CreateTemporalDuration(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _roundResult_.[[Days]], _roundResult_.[[Hours]], _roundResult_.[[Minutes]], _roundResult_.[[Seconds]], _roundResult_.[[Milliseconds]], _roundResult_.[[Microseconds]], _roundResult_.[[Nanoseconds]]).
@@ -513,34 +519,23 @@ Temporal.Duration.prototype.total ( _totalOf_ )
1. Set _precalculatedPlainDateTime_ to ? GetPlainDateTimeFor(_timeZoneRec_, _instant_, _zonedRelativeTo_.[[Calendar]]).
1. Set _plainRelativeTo_ to ! CreateTemporalDate(_precalculatedPlainDateTime_.[[ISOYear]], _precalculatedPlainDateTime_.[[ISOMonth]], _precalculatedPlainDateTime_.[[ISODay]], _zonedRelativeTo_.[[Calendar]]).
1. Let _calendarRec_ be ? CreateCalendarMethodsRecordFromRelativeTo(_plainRelativeTo_, _zonedRelativeTo_, « ~date-add~, ~date-until~ »).
- 1. Let _unbalanceResult_ be ? UnbalanceDateDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _unit_, _plainRelativeTo_, _calendarRec_).
- 1. Let _days_ be _unbalanceResult_.[[Days]].
+ 1. Let _norm_ be NormalizeTimeDuration(_duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]]).
+ 1. Let _emptyOptions_ be OrdinaryObjectCreate(*null*).
1. If _zonedRelativeTo_ is not *undefined*, then
- 1. Let _intermediate_ be ? MoveRelativeZonedDateTime(_zonedRelativeTo_, _calendarRec_, _timeZoneRec_, _unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], 0, _precalculatedPlainDateTime_).
- 1. Let _norm_ be NormalizeTimeDuration(_duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]]).
- 1. Let _startNs_ be _intermediate_.[[Nanoseconds]].
- 1. Let _startInstant_ be ! CreateTemporalInstant(_startNs_).
- 1. Let _startDateTime_ be *undefined*.
- 1. If _days_ ≠ 0, then
- 1. Set _startDateTime_ to ? GetPlainDateTimeFor(_timeZoneRec_, _startInstant_, *"iso8601"*).
- 1. Let _addResult_ be ? AddDaysToZonedDateTime(_startInstant_, _startDateTime_, _timeZoneRec_, *"iso8601"*, _days_).
- 1. Let _intermediateNs_ be _addResult_.[[EpochNanoseconds]].
- 1. Else,
- 1. Let _intermediateNs_ be _startNs_.
- 1. Let _endNs_ be ? AddInstant(_intermediateNs_, _norm_).
- 1. Set _norm_ to NormalizedTimeDurationFromEpochNanosecondsDifference(_endNs_, _startNs_).
- 1. If IsCalendarUnit(_unit_) is *true* or _unit_ is *"day"*, then
- 1. If NormalizedTimeDurationIsZero(_norm_) is *false* and _startDateTime_ is *undefined*, set _startDateTime_ to ? GetPlainDateTimeFor(_timeZoneRec_, _startInstant_, *"iso8601"*).
- 1. Let _result_ be ? NormalizedTimeDurationToDays(_norm_, _intermediate_, _timeZoneRec_, _startDateTime_).
- 1. Set _norm_ to _result_.[[Remainder]].
- 1. Set _days_ to _result_.[[Days]].
- 1. Else,
- 1. Set _days_ to 0.
+ 1. Let _relativeEpochNs_ be _zonedRelativeTo_.[[Nanoseconds]].
+ 1. Let _relativeInstant_ be ! CreateTemporalInstant(_relativeEpochNs_).
+ 1. Let _targetEpochNs_ be ? AddZonedDateTime(_relativeInstant_, _timeZoneRec_, _calendarRec_, _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _norm_, _precalculatedPlainDateTime_).
+ 1. Let _roundRecord_ be ? DifferenceZonedDateTimeWithRounding(_relativeEpochNs_, _targetEpochNs_, _plainRelativeTo_, _calendarRec_, _zonedRelativeTo_, _timeZoneRec_, _precalculatedPlainDateTime_, _emptyOptions_, _unit_, 1, _unit_, *"trunc"*).
+ 1. Else if _plainRelativeTo_ is not *undefined*, then
+ 1. Let _targetTime_ be AddTime(0, 0, 0, 0, 0, 0, _norm_).
+ 1. Let _dateDuration_ be ? CreateTemporalDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]] + _targetTime_.[[Days]], 0, 0, 0, 0, 0, 0).
+ 1. Let _targetDate_ be ? AddDate(_calendarRec_, _plainRelativeTo_, _dateDuration_).
+ 1. Let _roundRecord_ be ? DifferencePlainDateTimeWithRounding(_plainRelativeTo_, 0, 0, 0, 0, 0, 0, _targetDate_.[[ISOYear]], _targetDate_.[[ISOMonth]], _targetDate_.[[ISODay]], _targetTime_.[[Hours]], _targetTime_.[[Minutes]], _targetTime_.[[Seconds]], _targetTime_.[[Milliseconds]], _targetTime_.[[Microseconds]], _targetTime_.[[Nanoseconds]], _calendarRec_, _unit_, 1, _unit_, *"trunc"*, _emptyOptions_).
1. Else,
- 1. Let _norm_ be NormalizeTimeDuration(_duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]]).
- 1. Set _norm_ to ? Add24HourDaysToNormalizedTimeDuration(_norm_, _days_).
- 1. Set _days_ to 0.
- 1. Let _roundRecord_ be ? RoundDuration(_unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], _days_, _norm_, 1, _unit_, *"trunc"*, _plainRelativeTo_, _calendarRec_, _zonedRelativeTo_, _timeZoneRec_, _precalculatedPlainDateTime_).
+ 1. If _duration_.[[Years]] ≠ 0, or _duration_.[[Months]] ≠ 0, or _duration_.[[Weeks]] ≠ 0, or IsCalendarUnit(_unit_) is *true*, throw a *RangeError* exception.
+ 1. Let _isoCalendarRec_ be ! CreateCalendarMethodsRecord(*"iso8601"*, « ~date-add~, ~date-until~ »).
+ 1. Let _target_ be ? AddDateTime(1970, 1, 1, 0, 0, 0, 0, 0, 0, _isoCalendarRec_, _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _norm_, *undefined*).
+ 1. Let _roundRecord_ be ? DifferencePlainDateTimeWithRounding(~empty~, 0, 0, 0, 0, 0, 0, _target_.[[ISOYear]], _target_.[[ISOMonth]], _target_.[[ISODay]], _target_.[[ISOHour]], _target_.[[ISOMinute]], _target_.[[ISOSecond]], _target_.[[ISOMillisecond]], _target_.[[ISOMicrosecond]], _target_.[[ISONanosecond]], _isoCalendarRec_, _unit_, 1, _unit_, *"trunc"*, _emptyOptions_).
1. Return 𝔽(_roundRecord_.[[Total]]).
diff --git a/spec/instant.html b/spec/instant.html
index dedc1e280b..d546fc1553 100644
--- a/spec/instant.html
+++ b/spec/instant.html
@@ -574,7 +574,7 @@
_roundingIncrement_: a positive integer,
_smallestUnit_: a String,
_roundingMode_: a String from the Identifier column of ,
- ): a Normalized Time Duration Record
+ ): a Record with fields [[NormalizedTimeDuration]] (a Normalized Time Duration Record) and [[Total]] (a mathematical value)
1. Let _difference_ be NormalizedTimeDurationFromEpochNanosecondsDifference(_ns2_, _ns1_).
- 1. If _smallestUnit_ is *"nanosecond"* and _roundingIncrement_ is 1, then
- 1. Return _difference_.
1. Let _roundRecord_ be ! RoundDuration(0, 0, 0, 0, _difference_, _roundingIncrement_, _smallestUnit_, _roundingMode_).
- 1. Return _roundRecord_.[[NormalizedDuration]].[[NormalizedTime]].
+ 1. Return the Record { [[NormalizedTimeDuration]]: _roundRecord_.[[NormalizedDuration]].[[NormalizedTime]], [[Total]]: _roundRecord_.[[Total]] }.
@@ -656,7 +654,8 @@
1. Set _other_ to ? ToTemporalInstant(_other_).
1. Let _resolvedOptions_ be ? SnapshotOwnProperties(? GetOptionsObject(_options_), *null*).
1. Let _settings_ be ? GetDifferenceSettings(_operation_, _resolvedOptions_, ~time~, « », *"nanosecond"*, *"second"*).
- 1. Let _norm_ be DifferenceInstant(_instant_.[[Nanoseconds]], _other_.[[Nanoseconds]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]]).
+ 1. Let _diffRecord_ be DifferenceInstant(_instant_.[[Nanoseconds]], _other_.[[Nanoseconds]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]]).
+ 1. Let _norm_ be _diffRecord_.[[NormalizedTimeDuration]].
1. Let _result_ be BalanceTimeDuration(_norm_, _settings_.[[LargestUnit]]).
1. Return ! CreateTemporalDuration(0, 0, 0, 0, _sign_ × _result_.[[Hours]], _sign_ × _result_.[[Minutes]], _sign_ × _result_.[[Seconds]], _sign_ × _result_.[[Milliseconds]], _sign_ × _result_.[[Microseconds]], _sign_ × _result_.[[Nanoseconds]]).
diff --git a/spec/plaindatetime.html b/spec/plaindatetime.html
index 1e28c59490..c11cff48f0 100644
--- a/spec/plaindatetime.html
+++ b/spec/plaindatetime.html
@@ -1274,6 +1274,66 @@
1. Return ? CreateNormalizedDurationRecord(_dateDifference_.[[Years]], _dateDifference_.[[Months]], _dateDifference_.[[Weeks]], _dateDifference_.[[Days]], _timeDuration_).
+
+
+
+ DifferencePlainDateTimeWithRounding (
+ _plainDate1_: a Temporal.PlainDate or ~empty~,
+ _h1_: an integer in the inclusive interval from 0 to 23,
+ _min1_: an integer in the inclusive interval from 0 to 59,
+ _s1_: an integer in the inclusive interval from 0 to 59,
+ _ms1_: an integer in the inclusive interval from 0 to 999,
+ _mus1_: an integer in the inclusive interval from 0 to 999,
+ _ns1_: an integer in the inclusive interval from 0 to 999,
+ _y2_: an integer,
+ _mon2_: an integer in the inclusive interval from 1 to 12,
+ _d2_: an integer in the inclusive interval from 1 to ISODaysInMonth(_mon2_),
+ _h2_: an integer in the inclusive interval from 0 to 23,
+ _min2_: an integer in the inclusive interval from 0 to 59,
+ _s2_: an integer in the inclusive interval from 0 to 59,
+ _ms2_: an integer in the inclusive interval from 0 to 999,
+ _mus2_: an integer in the inclusive interval from 0 to 999,
+ _ns2_: an integer in the inclusive interval from 0 to 999,
+ _calendarRec_: a Calendar Methods Record,
+ _largestUnit_: a String etc,
+ _roundingIncrement_: an integer,
+ _smallestUnit_: a String,
+ _roundingMode_: a String,
+ _resolvedOptions_: an Object with [[Prototype]] slot *null*,
+ ): either a normal completion containing a Record with fields [[DurationRecord]] (a Duration Record) and [[Total]] (a mathematical value or ~empty~), or a throw completion
+
+
+
+ 1. If _plainDate1_ is ~empty~, then
+ 1. Let _y1_ be 1970.
+ 1. Let _mon1_ be 1.
+ 1. Let _d1_ be 1.
+ 1. Else,
+ 1. Let _y1_ be _plainDate1_.[[ISOYear]].
+ 1. Let _mon1_ be _plainDate1_.[[ISOMonth]].
+ 1. Let _d1_ be _plainDate1_.[[ISODay]].
+ 1. If CompareISODateTime(_y1_, _mon1_, _d1_, _h1_, _min1_, _s1_, _ms1_, _mus1_, _ns1_, _y2_, _mon2_, _d2_, _h2_, _min2_, _s2_, _ms2_, _mus2_, _ns2_) = 0, then
+ 1. Let _durationRecord_ be CreateDurationRecord(0, 0, 0, 0, 0, 0, 0, 0, 0, 0).
+ 1. Return the Record { [[DurationRecord]]: _durationRecord_, [[Total]]: 0 }.
+ 1. Let _diff_ be ? DifferenceISODateTime(_y1_, _mon1_, _d1_, _h1_, _min1_, _s1_, _ms1_, _mus1_, _ns1_, _y2_, _mon2_, _d2_, _h2_, _min2_, _s2_, _ms2_, _mus2_, _ns2_, _calendarRec_, _largestUnit_, _resolvedOptions_).
+ 1. If _smallestUnit_ is *"nanosecond"* and _roundingIncrement_ = 1, then
+ 1. Let _normWithDays_ be ? Add24HourDaysToNormalizedTimeDuration(_diff_.[[NormalizedTime]], _diff_.[[Days]]).
+ 1. Let _timeResult_ be BalanceTimeDuration(_normWithDays_, _largestUnit_).
+ 1. Let _durationRecord_ be CreateDurationRecord(_diff_.[[Years]], _diff_.[[Months]], _diff_.[[Weeks]], _timeResult_.[[Days]], _timeResult_.[[Hours]], _timeResult_.[[Minutes]], _timeResult_.[[Seconds]], _timeResult_.[[Milliseconds]], _timeResult_.[[Microseconds]], _timeResult_.[[Nanoseconds]]).
+ 1. Return the Record { [[DurationRecord]]: _durationRecord_, [[Total]]: ~empty~ }.
+ 1. Let _roundRecord_ be ? RoundDuration(_diff_.[[Years]], _diff_.[[Months]], _diff_.[[Weeks]], _diff_.[[Days]], _diff_.[[NormalizedTime]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _plainDate1_, _calendarRec_).
+ 1. Let _roundResult_ be _roundRecord_.[[NormalizedDuration]].
+ 1. Let _normWithDays_ be ? Add24HourDaysToNormalizedTimeDuration(_roundResult_.[[NormalizedTime]], _roundResult_.[[Days]]).
+ 1. Let _timeResult_ be BalanceTimeDuration(_normWithDays_, _largestUnit_).
+ 1. Let _balanceResult_ be ? BalanceDateDurationRelative(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _timeResult_.[[Days]], _largestUnit_, _smallestUnit_, _plainDate1_, _calendarRec_).
+ 1. Let _durationRecord_ be CreateDurationRecord(_balanceResult_.[[Years]], _balanceResult_.[[Months]], _balanceResult_.[[Weeks]], _balanceResult_.[[Days]], _timeResult_.[[Hours]], _timeResult_.[[Minutes]], _timeResult_.[[Seconds]], _timeResult_.[[Milliseconds]], _timeResult_.[[Microseconds]], _timeResult_.[[Nanoseconds]]).
+ 1. Return the Record { [[DurationRecord]]: _durationRecord_, [[Total]]: _roundRecord_.[[Total]] }.
+
+
+
DifferenceTemporalPlainDateTime (
@@ -1298,21 +1358,11 @@
1. Set _datePartsIdentical_ to *true*.
1. If _datePartsIdentical_ is *true*, and _dateTime_.[[ISOHour]] = _other_.[[ISOHour]], and _dateTime_.[[ISOMinute]] = _other_.[[ISOMinute]], and _dateTime_.[[ISOSecond]] = _other_.[[ISOSecond]], and _dateTime_.[[ISOMillisecond]] = _other_.[[ISOMillisecond]], and _dateTime_.[[ISOMicrosecond]] = _other_.[[ISOMicrosecond]], and _dateTime_.[[ISONanosecond]] = _other_.[[ISONanosecond]], then
1. Return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0).
+ 1. Let _plainDate_ be ! CreateTemporalDate(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[Calendar]]).
1. Let _calendarRec_ be ? CreateCalendarMethodsRecord(_dateTime_.[[Calendar]], « ~date-add~, ~date-until~ »).
- 1. Let _result_ be ? DifferenceISODateTime(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _other_.[[ISOYear]], _other_.[[ISOMonth]], _other_.[[ISODay]], _other_.[[ISOHour]], _other_.[[ISOMinute]], _other_.[[ISOSecond]], _other_.[[ISOMillisecond]], _other_.[[ISOMicrosecond]], _other_.[[ISONanosecond]], _calendarRec_, _settings_.[[LargestUnit]], _resolvedOptions_).
- 1. If _settings_.[[SmallestUnit]] is *"nanosecond"* and _settings_.[[RoundingIncrement]] = 1, let _roundingGranularityIsNoop_ be *true*; else let _roundingGranularityIsNoop_ be *false*.
- 1. If _roundingGranularityIsNoop_ is *false*, then
- 1. Let _relativeTo_ be ! CreateTemporalDate(_dateTime_.[[ISOYear]], _dateTime_.[[ISOMonth]], _dateTime_.[[ISODay]], _dateTime_.[[Calendar]]).
- 1. Let _roundRecord_ be ? RoundDuration(_result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _result_.[[Days]], _result_.[[NormalizedTime]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]], _relativeTo_, _calendarRec_).
- 1. Let _roundResult_ be _roundRecord_.[[NormalizedDuration]].
- 1. Let _normWithDays_ be ? Add24HourDaysToNormalizedTimeDuration(_roundResult_.[[NormalizedTime]], _roundResult_.[[Days]]).
- 1. Let _timeResult_ be BalanceTimeDuration(_normWithDays_, _settings_.[[LargestUnit]]).
- 1. Let _balanceResult_ be ? BalanceDateDurationRelative(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _timeResult_.[[Days]], _settings_.[[LargestUnit]], _settings_.[[SmallestUnit]], _relativeTo_, _calendarRec_).
- 1. Else,
- 1. Let _normWithDays_ be ? Add24HourDaysToNormalizedTimeDuration(_result_.[[NormalizedTime]], _result_.[[Days]]).
- 1. Let _timeResult_ be BalanceTimeDuration(_normWithDays_, _settings_.[[LargestUnit]]).
- 1. Let _balanceResult_ be ! CreateDateDurationRecord(_result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _timeResult_.[[Days]]).
- 1. Return ! CreateTemporalDuration(_sign_ × _balanceResult_.[[Years]], _sign_ × _balanceResult_.[[Months]], _sign_ × _balanceResult_.[[Weeks]], _sign_ × _balanceResult_.[[Days]], _sign_ × _timeResult_.[[Hours]], _sign_ × _timeResult_.[[Minutes]], _sign_ × _timeResult_.[[Seconds]], _sign_ × _timeResult_.[[Milliseconds]], _sign_ × _timeResult_.[[Microseconds]], _sign_ × _timeResult_.[[Nanoseconds]]).
+ 1. Let _resultRecord_ be ? DifferencePlainDateTimeWithRounding(_plainDate_, _dateTime_.[[ISOHour]], _dateTime_.[[ISOMinute]], _dateTime_.[[ISOSecond]], _dateTime_.[[ISOMillisecond]], _dateTime_.[[ISOMicrosecond]], _dateTime_.[[ISONanosecond]], _other_.[[ISOYear]], _other_.[[ISOMonth]], _other_.[[ISODay]], _other_.[[ISOHour]], _other_.[[ISOMinute]], _other_.[[ISOSecond]], _other_.[[ISOMillisecond]], _other_.[[ISOMicrosecond]], _other_.[[ISONanosecond]], _calendarRec_, _settings_.[[LargestUnit]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]], _resolvedOptions_).
+ 1. Let _result_ be _resultRecord_.[[DurationRecord]].
+ 1. Return ! CreateTemporalDuration(_sign_ × _result_.[[Years]], _sign_ × _result_.[[Months]], _sign_ × _result_.[[Weeks]], _sign_ × _result_.[[Days]], _sign_ × _result_.[[Hours]], _sign_ × _result_.[[Minutes]], _sign_ × _result_.[[Seconds]], _sign_ × _result_.[[Milliseconds]], _sign_ × _result_.[[Microseconds]], _sign_ × _result_.[[Nanoseconds]]).
diff --git a/spec/zoneddatetime.html b/spec/zoneddatetime.html
index ba333b1703..9735e19f46 100644
--- a/spec/zoneddatetime.html
+++ b/spec/zoneddatetime.html
@@ -1477,6 +1477,53 @@
}.
+
+
+
+ DifferenceZonedDateTimeWithRounding (
+ _ns1_: a BigInt,
+ _ns2_: a BigInt,
+ _plainRelativeTo_: a Temporal.PlainDate,
+ _calendarRec_: a Calendar Methods Record,
+ _zonedDateTime_: a Temporal.ZonedDateTime,
+ _timeZoneRec_: a Time Zone Methods Record,
+ _precalculatedPlainDateTime_: a Temporal.PlainDateTime,
+ _resolvedOptions_: an Object with [[Prototype]] slot *null*,
+ _largestUnit_: a String,
+ _roundingIncrement_: an integer,
+ _smallestUnit_: a String,
+ _roundingMode_: a String,
+ ): either a normal completion containing a Record with fields [[DurationRecord]] (a Duration Record) and [[Total]] (a mathematical value or ~empty~), or a throw completion
+
+
+
+ 1. If IsCalendarUnit(_largestUnit_) is *false* and _largestUnit_ is not *"day"*, then
+ 1. Let _diffRecord_ be DifferenceInstant(_ns1_, _ns2_, _roundingIncrement_, _smallestUnit_, _roundingMode_).
+ 1. Let _norm_ be _diffRecord_.[[NormalizedTimeDuration]].
+ 1. Let _result_ be BalanceTimeDuration(_norm_, _largestUnit_).
+ 1. Let _durationRecord_ be CreateDurationRecord(0, 0, 0, 0, _result_.[[Hours]], _result_.[[Minutes]], _result_.[[Seconds]], _result_.[[Milliseconds]], _result_.[[Microseconds]], _result_.[[Nanoseconds]]).
+ 1. Return the Record { [[DurationRecord]]: _durationRecord_, [[Total]]: _diffRecord_.[[Total]] }.
+ 1. Perform ! CreateDataPropertyOrThrow(_resolvedOptions_, *"largestUnit"*, _largestUnit_).
+ 1. Let _difference_ be ? DifferenceZonedDateTime(_ns1_, _ns2_, _timeZoneRec_, _calendarRec_, _largestUnit_, _resolvedOptions_, _precalculatedPlainDateTime_).
+ 1. If _smallestUnit_ is *"nanosecond"* and _roundingIncrement_ is 1, let _roundingGranularityIsNoop_ be *true*; else let _roundingGranularityIsNoop_ be *false*.
+ 1. If _roundingGranularityIsNoop_ is *true*, then
+ 1. Let _timeResult_ be BalanceTimeDuration(_difference_.[[NormalizedTime]], *"hour"*).
+ 1. Let _durationRecord_ be CreateDurationRecord(_difference_.[[Years]], _difference_.[[Months]], _difference_.[[Weeks]], _difference_.[[Days]], _timeResult_.[[Hours]], _timeResult_.[[Minutes]], _timeResult_.[[Seconds]], _timeResult_.[[Milliseconds]], _timeResult_.[[Microseconds]], _timeResult_.[[Nanoseconds]]).
+ 1. Return the Record { [[DurationRecord]]: _durationRecord_, [[Total]]: ~empty~ }.
+ 1. Let _roundRecord_ be ? RoundDuration(_difference_.[[Years]], _difference_.[[Months]], _difference_.[[Weeks]], _difference_.[[Days]], _difference_.[[NormalizedTime]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _plainRelativeTo_, _calendarRec_, _zonedDateTime_, _timeZoneRec_, _precalculatedPlainDateTime_).
+ 1. Let _roundResult_ be _roundRecord_.[[NormalizedDuration]].
+ 1. Let _adjustResult_ be ? AdjustRoundedDurationDays(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _roundResult_.[[Days]], _roundResult_.[[NormalizedTime]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _zonedDateTime_, _calendarRec_, _timeZoneRec_, _precalculatedPlainDateTime_).
+ 1. Let _balanceResult_ be ? BalanceDateDurationRelative(_adjustResult_.[[Years]], _adjustResult_.[[Months]], _adjustResult_.[[Weeks]], _adjustResult_.[[Days]], _largestUnit_, _smallestUnit_, _plainRelativeTo_, _calendarRec_).
+ 1. Set _result_ to ? CombineDateAndNormalizedTimeDuration(_balanceResult_, _adjustResult_.[[NormalizedTime]]).
+ 1. Let _timeResult_ be BalanceTimeDuration(_result_.[[NormalizedTime]], *"hour"*).
+ 1. Let _durationRecord_ be CreateDurationRecord(_result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _result_.[[Days]], _timeResult_.[[Hours]], _timeResult_.[[Minutes]], _timeResult_.[[Seconds]], _timeResult_.[[Milliseconds]], _timeResult_.[[Microseconds]], _timeResult_.[[Nanoseconds]]).
+ 1. Return the Record { [[DurationRecord]]: _durationRecord_, [[Total]]: _roundRecord_.[[Total]] }.
+
+
+
DifferenceTemporalZonedDateTime (
@@ -1498,7 +1545,8 @@
1. Let _resolvedOptions_ be ? SnapshotOwnProperties(? GetOptionsObject(_options_), *null*).
1. Let _settings_ be ? GetDifferenceSettings(_operation_, _resolvedOptions_, ~datetime~, « », *"nanosecond"*, *"hour"*).
1. If _settings_.[[LargestUnit]] is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then
- 1. Let _norm_ be DifferenceInstant(_zonedDateTime_.[[Nanoseconds]], _other_.[[Nanoseconds]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]]).
+ 1. Let _diffRecord_ be DifferenceInstant(_zonedDateTime_.[[Nanoseconds]], _other_.[[Nanoseconds]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]]).
+ 1. Let _norm_ be _diffRecord_.[[NormalizedTimeDuration]].
1. Let _result_ be BalanceTimeDuration(_norm_, _settings_.[[LargestUnit]]).
1. Return ! CreateTemporalDuration(0, 0, 0, 0, _sign_ × _result_.[[Hours]], _sign_ × _result_.[[Minutes]], _sign_ × _result_.[[Seconds]], _sign_ × _result_.[[Milliseconds]], _sign_ × _result_.[[Microseconds]], _sign_ × _result_.[[Nanoseconds]]).
1. If ? TimeZoneEquals(_zonedDateTime_.[[TimeZone]], _other_.[[TimeZone]]) is *false*, then
@@ -1510,19 +1558,9 @@
1. Let _instant_ be ! CreateTemporalInstant(_zonedDateTime_.[[Nanoseconds]]).
1. Let _precalculatedPlainDateTime_ be ? GetPlainDateTimeFor(_timeZoneRec_, _instant_, _calendarRec_.[[Receiver]]).
1. Let _plainRelativeTo_ be ! CreateTemporalDate(_precalculatedPlainDateTime_.[[ISOYear]], _precalculatedPlainDateTime_.[[ISOMonth]], _precalculatedPlainDateTime_.[[ISODay]], _calendarRec_.[[Receiver]]).
- 1. Perform ! CreateDataPropertyOrThrow(_resolvedOptions_, *"largestUnit"*, _settings_.[[LargestUnit]]).
- 1. Let _result_ be ? DifferenceZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _other_.[[Nanoseconds]], _timeZoneRec_, _calendarRec_, _settings_.[[LargestUnit]], _resolvedOptions_, _precalculatedPlainDateTime_).
- 1. If _settings_.[[SmallestUnit]] is *"nanosecond"* and _settings_.[[RoundingIncrement]] is 1, let _roundingGranularityIsNoop_ be *true*; else let _roundingGranularityIsNoop_ be *false*.
- 1. If _roundingGranularityIsNoop_ is *false*, then
- 1. Let _roundRecord_ be ? RoundDuration(_result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _result_.[[Days]], _result_.[[NormalizedTime]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]], _plainRelativeTo_, _calendarRec_, _zonedDateTime_, _timeZoneRec_, _precalculatedPlainDateTime_).
- 1. Let _roundResult_ be _roundRecord_.[[NormalizedDuration]].
- 1. Let _daysResult_ be ! NormalizedTimeDurationToDays(_roundResult_.[[NormalizedTime]], _zonedDateTime_, _timeZoneRec_).
- 1. Let _days_ be _roundResult_.[[Days]] + _daysResult_.[[Days]].
- 1. Let _adjustResult_ be ? AdjustRoundedDurationDays(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _days_, _daysResult_.[[NormalizedTime]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]], _zonedDateTime_, _calendarRec_, _timeZoneRec_, _precalculatedPlainDateTime_).
- 1. Let _balanceResult_ be ? BalanceDateDurationRelative(_adjustResult_.[[Years]], _adjustResult_.[[Months]], _adjustResult_.[[Weeks]], _adjustResult_.[[Days]], _settings_.[[LargestUnit]], _settings_.[[SmallestUnit]], _plainRelativeTo_, _calendarRec_).
- 1. Set _result_ to ? CombineDateAndNormalizedTimeDuration(_balanceResult_, _adjustResult_.[[NormalizedTime]]).
- 1. Let _timeResult_ be BalanceTimeDuration(_result_.[[NormalizedTime]], *"hour"*).
- 1. Return ! CreateTemporalDuration(_sign_ × _result_.[[Years]], _sign_ × _result_.[[Months]], _sign_ × _result_.[[Weeks]], _sign_ × _result_.[[Days]], _sign_ × _timeResult_.[[Hours]], _sign_ × _timeResult_.[[Minutes]], _sign_ × _timeResult_.[[Seconds]], _sign_ × _timeResult_.[[Milliseconds]], _sign_ × _timeResult_.[[Microseconds]], _sign_ × _timeResult_.[[Nanoseconds]]).
+ 1. Let _resultRecord_ be ? DifferenceZonedDateTimeWithRounding(_zonedDateTime_.[[Nanoseconds]], _other_.[[Nanoseconds]], _plainRelativeTo_, _calendarRec_, _zonedDateTime_, _timeZoneRec_, _precalculatedPlainDateTime_, _resolvedOptions_, _settings_.[[LargestUnit]], _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]]).
+ 1. Let _result_ be _resultRecord_.[[DurationRecord]].
+ 1. Return ! CreateTemporalDuration(_sign_ × _result_.[[Years]], _sign_ × _result_.[[Months]], _sign_ × _result_.[[Weeks]], _sign_ × _result_.[[Days]], _sign_ × _result_.[[Hours]], _sign_ × _result_.[[Minutes]], _sign_ × _result_.[[Seconds]], _sign_ × _result_.[[Milliseconds]], _sign_ × _result_.[[Microseconds]], _sign_ × _result_.[[Nanoseconds]]).