From 96e31e7e2887a7444c70e5fa67f5c111fb60b5b2 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Thu, 8 Feb 2024 11:49:56 -0800 Subject: [PATCH] Temporal: Tests for round() and since()/until() using the same code path This should produce all the same results (except for a change to weeks balancing in round(), which is now more consistent with since()/until()) but leads to different observable user code calls. See https://github.com/tc39/proposal-temporal/issues/2742 --- ...r-dateadd-called-with-options-undefined.js | 40 ++--- ...euntil-called-with-singular-largestunit.js | 74 +------- .../date-and-time-durations-opposite-signs.js | 8 +- .../prototype/round/dateuntil-field.js | 3 +- .../prototype/round/dst-rounding-result.js | 30 +++- ...-time-duration-to-days-loop-arbitrarily.js | 44 ----- .../prototype/round/order-of-operations.js | 162 ++++++++---------- ...nstantsfor-called-with-iso8601-calendar.js | 2 +- ...ized-time-duration-to-days-range-errors.js | 125 -------------- .../prototype/round/roundingmode-ceil.js | 2 +- .../prototype/round/roundingmode-expand.js | 2 +- .../prototype/round/roundingmode-floor.js | 2 +- .../prototype/round/roundingmode-halfCeil.js | 2 +- .../prototype/round/roundingmode-halfEven.js | 2 +- .../round/roundingmode-halfExpand.js | 2 +- .../prototype/round/roundingmode-halfFloor.js | 2 +- .../prototype/round/roundingmode-halfTrunc.js | 2 +- .../prototype/round/roundingmode-trunc.js | 2 +- ...-duration-relative-when-sign-mismatched.js | 35 ---- ...imezone-getpossibleinstantsfor-iterable.js | 5 +- ...r-dateadd-called-with-options-undefined.js | 10 +- ...euntil-called-with-singular-largestunit.js | 37 +--- .../prototype/total/dst-rounding-result.js | 8 +- ...-time-duration-to-days-loop-arbitrarily.js | 43 ----- .../prototype/total/order-of-operations.js | 153 ++++++++--------- .../precision-exact-mathematical-values-3.js | 69 ++++---- .../precision-exact-mathematical-values-4.js | 85 +++------ ...ized-time-duration-to-days-range-errors.js | 125 -------------- ...-dateadd-called-with-plaindate-instance.js | 17 -- .../prototype/since/order-of-operations.js | 45 ++--- ...-dateadd-called-with-plaindate-instance.js | 17 -- .../prototype/until/order-of-operations.js | 43 ++--- .../prototype/since/order-of-operations.js | 44 ++--- .../prototype/since/result-mixed-sign.js | 4 +- .../prototype/until/order-of-operations.js | 44 ++--- .../prototype/until/result-mixed-sign.js | 4 +- .../prototype/since/order-of-operations.js | 37 ++-- .../prototype/until/order-of-operations.js | 37 ++-- ...r-dateadd-called-with-options-undefined.js | 9 +- ...euntil-called-with-singular-largestunit.js | 56 +----- .../date-and-time-durations-opposite-signs.js | 8 +- ...-time-duration-to-days-loop-arbitrarily.js | 43 ----- ...ized-time-duration-to-days-range-errors.js | 138 --------------- .../prototype/since/order-of-operations.js | 61 ++----- .../since/roundingincrement-non-integer.js | 2 - ...r-dateadd-called-with-options-undefined.js | 9 +- ...euntil-called-with-singular-largestunit.js | 56 +----- .../date-and-time-durations-opposite-signs.js | 8 +- ...-time-duration-to-days-loop-arbitrarily.js | 43 ----- ...ized-time-duration-to-days-range-errors.js | 138 --------------- .../prototype/until/order-of-operations.js | 61 ++----- .../until/roundingincrement-non-integer.js | 2 - test/staging/Temporal/Duration/old/round.js | 4 +- test/staging/Temporal/Duration/old/total.js | 2 +- 54 files changed, 409 insertions(+), 1599 deletions(-) delete mode 100644 test/built-ins/Temporal/Duration/prototype/round/normalized-time-duration-to-days-loop-arbitrarily.js delete mode 100644 test/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-normalized-time-duration-to-days-range-errors.js delete mode 100644 test/built-ins/Temporal/Duration/prototype/round/throws-in-unbalance-duration-relative-when-sign-mismatched.js delete mode 100644 test/built-ins/Temporal/Duration/prototype/total/normalized-time-duration-to-days-loop-arbitrarily.js delete mode 100644 test/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-normalized-time-duration-to-days-range-errors.js delete mode 100644 test/built-ins/Temporal/PlainDate/prototype/since/calendar-dateadd-called-with-plaindate-instance.js delete mode 100644 test/built-ins/Temporal/PlainDate/prototype/until/calendar-dateadd-called-with-plaindate-instance.js delete mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/since/normalized-time-duration-to-days-loop-arbitrarily.js delete mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/since/normalized-time-duration-to-days-range-errors.js delete mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/until/normalized-time-duration-to-days-loop-arbitrarily.js delete mode 100644 test/built-ins/Temporal/ZonedDateTime/prototype/until/normalized-time-duration-to-days-range-errors.js diff --git a/test/built-ins/Temporal/Duration/prototype/round/calendar-dateadd-called-with-options-undefined.js b/test/built-ins/Temporal/Duration/prototype/round/calendar-dateadd-called-with-options-undefined.js index 56f26a8523..e6f94b6197 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/calendar-dateadd-called-with-options-undefined.js +++ b/test/built-ins/Temporal/Duration/prototype/round/calendar-dateadd-called-with-options-undefined.js @@ -17,41 +17,23 @@ const relativeTo = new Temporal.ZonedDateTime(0n, timeZone, calendar); // Rounding with smallestUnit a calendar unit. // The calls come from these paths: // Duration.round() -> -// RoundDuration -> -// MoveRelativeZonedDateTime -> AddZonedDateTime -> calendar.dateAdd() -// MoveRelativeDate -> calendar.dateAdd() -// BalanceDateDurationRelative -> calendar.dateAdd() +// AddZonedDateTime -> calendar.dateAdd() +// DifferenceZonedDateTimeWithRounding -> RoundRelativeDuration -> NudgeToCalendarUnit -> +// AddDateTime -> calendar.dateAdd() (2x) -const instance1 = new Temporal.Duration(1, 1, 1, 1, 1); -instance1.round({ smallestUnit: "weeks", relativeTo }); -assert.sameValue(calendar.dateAddCallCount, 4, "rounding with calendar smallestUnit"); - -// Rounding with a non-default largestUnit to cover the path in -// UnbalanceDurationRelative where larger units are converted into smaller -// units; and with a smallestUnit larger than days to cover the path in -// RoundDuration where days are converted into larger units. -// The calls come from these paths: -// Duration.round() -> -// UnbalanceDurationRelative -> MoveRelativeDate -> calendar.dateAdd() -// RoundDuration -> MoveRelativeDate -> calendar.dateAdd() (2x) -// BalanceDateDurationRelative -> calendar.dateAdd() -// MoveRelativeZonedDateTime -> AddZonedDateTime -> calendar.dateAdd() - -calendar.dateAddCallCount = 0; - -const instance2 = new Temporal.Duration(0, 1, 1, 1); -instance2.round({ largestUnit: "weeks", smallestUnit: "weeks", relativeTo }); -assert.sameValue(calendar.dateAddCallCount, 6, "rounding with non-default largestUnit and calendar smallestUnit"); +const instance = new Temporal.Duration(1, 1, 1, 1, 1); +instance.round({ smallestUnit: "weeks", relativeTo }); +assert.sameValue(calendar.dateAddCallCount, 3, "rounding with calendar smallestUnit"); // Rounding with smallestUnit days only. // The calls come from these paths: // Duration.round() -> -// RoundDuration -> -// MoveRelativeZonedDateTime -> AddZonedDateTime -> calendar.dateAdd() -// BalanceDateDurationRelative -> calendar.dateAdd() +// AddZonedDateTime -> calendar.dateAdd() +// DifferenceZonedDateTimeWithRounding -> +// RoundDuration -> MoveRelativeZonedDateTime -> AddZonedDateTime -> calendar.dateAdd() +// BalanceDateDurationRelative -> calendar.dateAdd() calendar.dateAddCallCount = 0; -const instance3 = new Temporal.Duration(1, 1, 1, 1, 1); -instance3.round({ smallestUnit: "days", relativeTo }); +instance.round({ smallestUnit: "days", relativeTo }); assert.sameValue(calendar.dateAddCallCount, 3, "rounding with days smallestUnit"); diff --git a/test/built-ins/Temporal/Duration/prototype/round/calendar-dateuntil-called-with-singular-largestunit.js b/test/built-ins/Temporal/Duration/prototype/round/calendar-dateuntil-called-with-singular-largestunit.js index 918c195129..5221df4af8 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/calendar-dateuntil-called-with-singular-largestunit.js +++ b/test/built-ins/Temporal/Duration/prototype/round/calendar-dateuntil-called-with-singular-largestunit.js @@ -3,69 +3,9 @@ /*--- esid: sec-temporal.duration.prototype.round -description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form -info: | - sec-temporal.duration.prototype.round steps 23–27: - 23. Let _unbalanceResult_ be ? UnbalanceDateDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _largestUnit_, _relativeTo_). - 24. Let _roundResult_ be (? RoundDuration(_unbalanceResult_.[[Years]], _unbalanceResult_.[[Months]], _unbalanceResult_.[[Weeks]], _unbalanceResult_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _relativeTo_)).[[DurationRecord]]. - 25. Let _adjustResult_ be ? AdjustRoundedDurationDays(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _roundResult_.[[Days]], _roundResult_.[[Hours]], _roundResult_.[[Minutes]], _roundResult_.[[Seconds]], _roundResult_.[[Milliseconds]], _roundResult_.[[Microseconds]], _roundResult_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _relativeTo_). - 26. Let _balanceResult_ be ? BalanceDuration(_adjustResult_.[[Days]], _adjustResult_.[[Hours]], _adjustResult_.[[Minutes]], _adjustResult_.[[Seconds]], _adjustResult_.[[Milliseconds]], _adjustResult_.[[Microseconds]], _adjustResult_.[[Nanoseconds]], _largestUnit_, _relativeTo_). - 27. Let _result_ be ? BalanceDurationRelative(_adjustResult_.[[Years]], _adjustResult_.[[Months]], _adjustResult_.[[Weeks]], _balanceResult_.[[Days]], _largestUnit_, _relativeTo_). - sec-temporal-unbalancedatedurationrelative step 3: - 3. If _largestUnit_ is *"month"*, then - ... - g. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*). - h. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"month"*). - i. Let _untilResult_ be ? CalendarDateUntil(_calendarRec_.[[Receiver]], _plainRelativeTo_, _later_, _untilOptions_, _calendarRec_.[[DateUntil]]). - sec-temporal-roundduration steps 5.d and 8.n–p: - 5. If _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then - ... - d. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _intermediate_). - ... - 8. If _unit_ is *"year"*, then - ... - n. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*). - o. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"year"*). - p. Let _timePassed_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _daysLater_, _untilOptions_) - sec-temporal-adjustroundeddurationdays steps 1 and 9: - 1. If _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot; or _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*; or _unit_ is *"nanosecond"* and _increment_ is 1, then - a. Return ... - ... - 9. 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_). - sec-temporal-addduration step 7.a–g: - a. Assert: _relativeTo_ has an [[IntializedTemporalZonedDateTime]] internal slot. - ... - f. If _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then - ... - g. Else, - i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_). - sec-temporal-balancedurationrelative steps 1, 9.m–o, and 9.q.vi–viii: - 1. If _largestUnit_ is not one of *"year"*, *"month"*, or *"week"*, or _years_, _months_, _weeks_, and _days_ are all 0, then - a. Return ... - ... - 9. If _largestUnit_ is *"year"*, then - ... - m. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*). - n. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"month"*). - o. Let _untilResult_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _newRelativeTo_, _untilOptions_, _dateUntil_). - p. ... - q. Repeat, while abs(_months_) ≥ abs(_oneYearMonths_), - ... - vi. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*). - vii. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"month"*). - viii. Let _untilResult_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _newRelativeTo_, _untilOptions_, _dateUntil_). - sec-temporal-balanceduration step 3.a: - 3. If _largestUnit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then - a. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _relativeTo_). - sec-temporal-differencezoneddatetime steps 7 and 11: - 7. 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]], _calendar_, _largestUnit_, _options_). - 11. Let _result_ be ? NanosecondsToDays(_timeRemainderNs_, _intermediate_). - sec-temporal-nanosecondstodays step 11: - 11. 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"*). - sec-temporal-differenceisodatetime steps 9–11: - 9. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_). - 10. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _dateLargestUnit_). - 11. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_). +description: > + The options object passed to calendar.dateUntil has a largestUnit property + with its value in the singular form includes: [compareArray.js, temporalHelpers.js] features: [Temporal] ---*/ @@ -99,9 +39,9 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( duration.round({ largestUnit, roundingIncrement: 2, roundingMode: 'ceil', relativeTo }); }, { - years: ["year", "year"], - months: ["month", "month"], - weeks: ["week", "week"], + years: ["year"], + months: ["month"], + weeks: ["week"], days: [], hours: [], minutes: [], @@ -123,7 +63,7 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( }, { years: ["year"], - months: ["month", "month"], + months: ["month"], weeks: ["week"], days: [], hours: [], diff --git a/test/built-ins/Temporal/Duration/prototype/round/date-and-time-durations-opposite-signs.js b/test/built-ins/Temporal/Duration/prototype/round/date-and-time-durations-opposite-signs.js index b57829c812..95c87a01f7 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/date-and-time-durations-opposite-signs.js +++ b/test/built-ins/Temporal/Duration/prototype/round/date-and-time-durations-opposite-signs.js @@ -20,14 +20,8 @@ features: [Temporal] // Based on a test case by André Bargull const calendar = new class extends Temporal.Calendar { - #dateUntil = 0; - dateUntil(one, two, options) { - let result = super.dateUntil(one, two, options); - if (++this.#dateUntil === 2) { - result = result.negated(); - } - return result; + return super.dateUntil(one, two, options).negated(); } }("iso8601"); diff --git a/test/built-ins/Temporal/Duration/prototype/round/dateuntil-field.js b/test/built-ins/Temporal/Duration/prototype/round/dateuntil-field.js index 7220d69aed..39c2c2e905 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/dateuntil-field.js +++ b/test/built-ins/Temporal/Duration/prototype/round/dateuntil-field.js @@ -28,8 +28,7 @@ const calendar = new CalendarDateUntilObservable("iso8601"); const relativeTo = new Temporal.PlainDate(2018, 10, 12, calendar); const expected = [ - "call dateUntil", // UnbalanceDateDurationRelative - "call dateUntil", // BalanceDateDurationRelative + "call dateUntil", // DifferencePlainDateTimeWithRounding -> DifferenceISODateTime ]; const years = new Temporal.Duration(2); diff --git a/test/built-ins/Temporal/Duration/prototype/round/dst-rounding-result.js b/test/built-ins/Temporal/Duration/prototype/round/dst-rounding-result.js index a2744257e2..589ea340c9 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/dst-rounding-result.js +++ b/test/built-ins/Temporal/Duration/prototype/round/dst-rounding-result.js @@ -15,7 +15,7 @@ const timeZone = TemporalHelpers.springForwardFallBackTimeZone(); { // Date part of duration lands on skipped DST hour, causing disambiguation - const duration = new Temporal.Duration(0, 1, 0, 15, 12); + const duration = new Temporal.Duration(0, 1, 0, 15, 11, 30); const relativeTo = new Temporal.ZonedDateTime( 950868000_000_000_000n /* = 2000-02-18T10Z */, timeZone); /* = 2000-02-18T02-08 in local time */ @@ -29,17 +29,35 @@ const timeZone = TemporalHelpers.springForwardFallBackTimeZone(); } { - // Month-only part of duration lands on skipped DST hour, should not cause - // disambiguation - const duration = new Temporal.Duration(0, 1, 0, 15); + // Month-only part of duration lands on skipped DST hour + const duration = new Temporal.Duration(0, 1, 0, 15, 0, 30); const relativeTo = new Temporal.ZonedDateTime( 951991200_000_000_000n /* = 2000-03-02T10Z */, timeZone); /* = 2000-03-02T02-08 in local time */ TemporalHelpers.assertDuration(duration.round({ smallestUnit: "months", relativeTo }), 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, - "1 month 15 days should be exactly 1.5 months, which rounds up to 2 months"); + "1 month 15 days 00:30 should be exactly 1.5 months, which rounds up to 2 months"); TemporalHelpers.assertDuration(duration.round({ smallestUnit: "months", roundingMode: 'halfTrunc', relativeTo }), 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - "1 month 15 days should be exactly 1.5 months, which rounds down to 1 month"); + "1 month 15 days 00:30 should be exactly 1.5 months, which rounds down to 1 month"); +} + +{ + // Day rounding + // DST spring-forward hour skipped at 2000-04-02T02:00 (23 hour day) + // 11.5 hours is 0.5 + const duration = new Temporal.Duration(0, 0, 0, 0, 11, 30); + const instant = timeZone.getPossibleInstantsFor(Temporal.PlainDateTime.from("2000-04-02T00:00:00"))[0]; + const relativeTo = instant.toZonedDateTimeISO(timeZone); + + TemporalHelpers.assertDuration( + duration.round({ relativeTo, smallestUnit: "days" }), + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + ); + + TemporalHelpers.assertDuration( + duration.round({ relativeTo, smallestUnit: "days", roundingMode: "halfTrunc" }), + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ); } diff --git a/test/built-ins/Temporal/Duration/prototype/round/normalized-time-duration-to-days-loop-arbitrarily.js b/test/built-ins/Temporal/Duration/prototype/round/normalized-time-duration-to-days-loop-arbitrarily.js deleted file mode 100644 index c07cd587f7..0000000000 --- a/test/built-ins/Temporal/Duration/prototype/round/normalized-time-duration-to-days-loop-arbitrarily.js +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (C) 2022 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-temporal.duration.prototype.round -description: > - NormalizedTimeDurationToDays should not be able to loop arbitrarily. -info: | - NormalizedTimeDurationToDays ( norm, zonedRelativeTo, timeZoneRec [ , precalculatedPlainDatetime ] ) - ... - 22. If NormalizedTimeDurationSign(_oneDayLess_) × _sign_ ≥ 0, then - a. Set _norm_ to _oneDayLess_. - b. Set _relativeResult_ to _oneDayFarther_. - c. Set _days_ to _days_ + _sign_. - d. Set _oneDayFarther_ to ? AddDaysToZonedDateTime(_relativeResult_.[[Instant]], _relativeResult_.[[DateTime]], _timeZoneRec_, _zonedRelativeTo_.[[Calendar]], _sign_). - e. Set dayLengthNs to NormalizedTimeDurationFromEpochNanosecondsDifference(_oneDayFarther.[[EpochNanoseconds]], relativeResult.[[EpochNanoseconds]]). - f. If NormalizedTimeDurationSign(? SubtractNormalizedTimeDuration(_norm_, _dayLengthNs_)) × _sign_ ≥ 0, then - i. Throw a *RangeError* exception. -features: [Temporal] ----*/ - -const duration = Temporal.Duration.from({ days: 1 }); - -const dayLengthNs = 86400000000000n; -const dayInstant = new Temporal.Instant(dayLengthNs); -let calls = 0; -const timeZone = new class extends Temporal.TimeZone { - getPossibleInstantsFor() { - calls++; - return [dayInstant]; - } -}("UTC"); - -const relativeTo = new Temporal.ZonedDateTime(0n, timeZone); - -assert.throws(RangeError, () => duration.round({ smallestUnit: "days", relativeTo }), "indefinite loop is prevented"); -assert.sameValue(calls, 5, "getPossibleInstantsFor is not called indefinitely"); - // Expected calls: - // RoundDuration -> MoveRelativeZonedDateTime -> AddZonedDateTime (1) - // BalanceTimeDurationRelative -> - // AddZonedDateTime (2) - // NormalizedTimeDurationToDays -> - // AddDaysToZonedDateTime (3, step 12) - // AddDaysToZonedDateTime (4, step 15) - // AddDaysToZonedDateTime (5, step 18.d) diff --git a/test/built-ins/Temporal/Duration/prototype/round/order-of-operations.js b/test/built-ins/Temporal/Duration/prototype/round/order-of-operations.js index dc62d661b2..47dfd67327 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/order-of-operations.js +++ b/test/built-ins/Temporal/Duration/prototype/round/order-of-operations.js @@ -122,25 +122,22 @@ actual.splice(0); // clear // code path through RoundDuration that rounds to the nearest year, with minimal calendar calls: const expectedMinimalOpsForYearRounding = expectedOpsForPlainRelativeTo.concat([ - // 7.e and 7.g not called because years, months, weeks are 0 - "call options.relativeTo.calendar.dateUntil", // 7.o - // 7.s not called because years, months, weeks are 0 - "call options.relativeTo.calendar.dateAdd", // 7.y MoveRelativeDate + // initial AddDate in Duration.p.round 39.c not called because no calendar units + "call options.relativeTo.calendar.dateUntil", // DifferencePlainDateTimeWithRounding → DifferenceISODateTime + "call options.relativeTo.calendar.dateAdd", ]); -instance.round(createOptionsObserver({ smallestUnit: "years", relativeTo: plainRelativeTo })); +const instanceMinimal = new Temporal.Duration(0, 0, 0, 0, /* hours = */ 100); +instanceMinimal.round(createOptionsObserver({ smallestUnit: "years", relativeTo: plainRelativeTo })); assert.compareArray(actual, expectedMinimalOpsForYearRounding, "order of operations with years = 0 and smallestUnit = years"); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest year: +// code path through Duration.prototype.round that rounds to the nearest year: const expectedOpsForYearRounding = expectedOpsForPlainRelativeTo.concat([ - "call options.relativeTo.calendar.dateAdd", // 12.d - "call options.relativeTo.calendar.dateAdd", // 12.f - "call options.relativeTo.calendar.dateUntil", // 12.n - "call options.relativeTo.calendar.dateAdd", // 12.r MoveRelativeDate - "call options.relativeTo.calendar.dateAdd", // 12.x MoveRelativeDate - // BalanceDateDurationRelative - "call options.relativeTo.calendar.dateAdd", // 9.c - "call options.relativeTo.calendar.dateUntil", // 9.d + "call options.relativeTo.calendar.dateAdd", // 39.c + "call options.relativeTo.calendar.dateUntil", // DifferencePlainDateTimeWithRounding → DifferenceISODateTime + // RoundRelativeDuration + "call options.relativeTo.calendar.dateAdd", + "call options.relativeTo.calendar.dateAdd", ]); const instanceYears = new Temporal.Duration(1, 12, 0, 0, /* hours = */ 2400); instanceYears.round(createOptionsObserver({ smallestUnit: "years", relativeTo: plainRelativeTo })); @@ -149,18 +146,11 @@ actual.splice(0); // clear // code path through Duration.prototype.round that rounds to the nearest month: const expectedOpsForMonthRounding = expectedOpsForPlainRelativeTo.concat([ - // UnbalanceDateDurationRelative - "call options.relativeTo.calendar.dateAdd", // 3.f - "call options.relativeTo.calendar.dateUntil", // 3.i - // RoundDuration - "call options.relativeTo.calendar.dateAdd", // 13.c - "call options.relativeTo.calendar.dateAdd", // 13.e - "call options.relativeTo.calendar.dateUntil", // 13.m - "call options.relativeTo.calendar.dateAdd", // 13.q MoveRelativeDate - "call options.relativeTo.calendar.dateAdd", // 13.w MoveRelativeDate - // BalanceDateDurationRelative - "call options.relativeTo.calendar.dateAdd", // 10.d - "call options.relativeTo.calendar.dateUntil", // 10.e + "call options.relativeTo.calendar.dateAdd", // 39.c + "call options.relativeTo.calendar.dateUntil", // DifferencePlainDateTimeWithRounding → DifferenceISODateTime + // RoundRelativeDuration + "call options.relativeTo.calendar.dateAdd", + "call options.relativeTo.calendar.dateAdd", ]); const instance2 = new Temporal.Duration(1, 0, 0, 62); instance2.round(createOptionsObserver({ largestUnit: "months", smallestUnit: "months", relativeTo: plainRelativeTo })); @@ -169,24 +159,21 @@ actual.splice(0); // clear // code path through Duration.prototype.round that rounds to the nearest week: const expectedOpsForWeekRounding = expectedOpsForPlainRelativeTo.concat([ - // UnbalanceDateDurationRelative - "call options.relativeTo.calendar.dateAdd", // 4.e - // RoundDuration - "call options.relativeTo.calendar.dateUntil", // 14.f - "call options.relativeTo.calendar.dateAdd", // 14.j MoveRelativeDate - "call options.relativeTo.calendar.dateAdd", // 14.p MoveRelativeDate - // BalanceDateDurationRelative - "call options.relativeTo.calendar.dateAdd", // 16 - "call options.relativeTo.calendar.dateUntil", // 17 + "call options.relativeTo.calendar.dateAdd", // 39.c + "call options.relativeTo.calendar.dateUntil", // DifferencePlainDateTimeWithRounding → DifferenceISODateTime + // RoundRelativeDuration + "call options.relativeTo.calendar.dateUntil", + "call options.relativeTo.calendar.dateAdd", + "call options.relativeTo.calendar.dateAdd", ]); const instance3 = new Temporal.Duration(1, 1, 0, 15); instance3.round(createOptionsObserver({ largestUnit: "weeks", smallestUnit: "weeks", relativeTo: plainRelativeTo })); assert.compareArray(actual, expectedOpsForWeekRounding, "order of operations with largestUnit = smallestUnit = weeks"); actual.splice(0); // clear -// code path through UnbalanceDurationRelative that rounds to the nearest day: +// code path through Duration.prototype.round that rounds to the nearest day: const expectedOpsForDayRounding = expectedOpsForPlainRelativeTo.concat([ - "call options.relativeTo.calendar.dateAdd", // 9 + "call options.relativeTo.calendar.dateAdd", // 39.c ]); const instance4 = new Temporal.Duration(1, 1, 1) instance4.round(createOptionsObserver({ largestUnit: "days", smallestUnit: "days", relativeTo: plainRelativeTo })); @@ -195,8 +182,8 @@ actual.splice(0); // clear // code path through BalanceDateDurationRelative balancing from days up to years: const expectedOpsForDayToYearBalancing = expectedOpsForPlainRelativeTo.concat([ - // BalanceDateDurationRelative - "call options.relativeTo.calendar.dateUntil", // 9.d + "call options.relativeTo.calendar.dateUntil", // DifferencePlainDateTimeWithRounding → DifferenceISODateTime + "call options.relativeTo.calendar.dateAdd", ]); const instance5 = new Temporal.Duration(0, 0, 0, 0, /* hours = */ 396 * 24); instance5.round(createOptionsObserver({ largestUnit: "years", smallestUnit: "days", relativeTo: plainRelativeTo })); @@ -205,13 +192,11 @@ actual.splice(0); // clear // code path through Duration.prototype.round balancing from months up to years: const expectedOpsForMonthToYearBalancing = expectedOpsForPlainRelativeTo.concat([ - // RoundDuration - "call options.relativeTo.calendar.dateAdd", // 13.c - "call options.relativeTo.calendar.dateAdd", // 13.e - "call options.relativeTo.calendar.dateAdd", // 13.w MoveRelativeDate - // BalanceDateDurationRelative - "call options.relativeTo.calendar.dateAdd", // 9.c - "call options.relativeTo.calendar.dateUntil", // 9.d + "call options.relativeTo.calendar.dateAdd", // 39.c + "call options.relativeTo.calendar.dateUntil", // DifferencePlainDateTimeWithRounding → DifferenceISODateTime + // RoundRelativeDuration + "call options.relativeTo.calendar.dateAdd", + "call options.relativeTo.calendar.dateAdd", ]); const instance6 = new Temporal.Duration(0, 12); instance6.round(createOptionsObserver({ largestUnit: "years", smallestUnit: "months", relativeTo: plainRelativeTo })); @@ -219,8 +204,7 @@ assert.compareArray(actual, expectedOpsForMonthToYearBalancing, "order of operat actual.splice(0); // clear const expectedOpsForDayToMonthBalancing = expectedOpsForPlainRelativeTo.concat([ - // BalanceDateDurationRelative - "call options.relativeTo.calendar.dateUntil", // 10.e + "call options.relativeTo.calendar.dateUntil", // DifferencePlainDateTimeWithRounding → DifferenceISODateTime ]); const instance7 = new Temporal.Duration(0, 0, 0, 0, /* hours = */ 32 * 24); instance7.round(createOptionsObserver({ largestUnit: "months", smallestUnit: "days", relativeTo: plainRelativeTo })); @@ -228,8 +212,7 @@ assert.compareArray(actual, expectedOpsForDayToMonthBalancing, "order of operati actual.splice(0); // clear const expectedOpsForDayToWeekBalancing = expectedOpsForPlainRelativeTo.concat([ - // BalanceDateDurationRelative - "call options.relativeTo.calendar.dateUntil", // 17 + "call options.relativeTo.calendar.dateUntil", // DifferencePlainDateTimeWithRounding → DifferenceISODateTime ]); const instance8 = new Temporal.Duration(0, 0, 0, 0, /* hours = */ 8 * 24); instance8.round(createOptionsObserver({ largestUnit: "weeks", smallestUnit: "days", relativeTo: plainRelativeTo })); @@ -351,18 +334,14 @@ const expectedOpsForMinimalYearRoundingZoned = expectedOpsForZonedRelativeTo.con // lookup in Duration.p.round "get options.relativeTo.calendar.dateAdd", "get options.relativeTo.calendar.dateUntil", - // NanosecondsToDays - "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 7. GetPlainDateTimeFor - "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 11. GetPlainDateTimeFor - // NanosecondsToDays → AddDaysToZonedDateTime + // DifferenceZonedDateTimeWithRounding → DifferenceZonedDateTime + "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 5 + "call options.relativeTo.timeZone.getPossibleInstantsFor", // 12.c + "call options.relativeTo.calendar.dateUntil", // 13.f + // RoundRelativeDuration + "call options.relativeTo.calendar.dateAdd", "call options.relativeTo.timeZone.getPossibleInstantsFor", - // NanosecondsToDays → AddDaysToZonedDateTime "call options.relativeTo.timeZone.getPossibleInstantsFor", - // RoundDuration - // 7.e and 7.g not called because years, months, weeks are 0 - "call options.relativeTo.calendar.dateUntil", // 7.o - // 7.s not called because years, months, weeks are 0 - "call options.relativeTo.calendar.dateAdd", // 7.y MoveRelativeDate ]); instance.round(createOptionsObserver({ smallestUnit: "years", relativeTo: zonedRelativeTo })); assert.compareArray( @@ -372,34 +351,25 @@ assert.compareArray( ); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest year: +// code path through Duration.p.round that rounds to the nearest year: const expectedOpsForYearRoundingZoned = expectedOpsForZonedRelativeTo.concat([ // ToTemporalDate "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // lookup in Duration.p.round "get options.relativeTo.calendar.dateAdd", "get options.relativeTo.calendar.dateUntil", - // MoveRelativeZonedDateTime → AddZonedDateTime + // AddZonedDateTime "call options.relativeTo.calendar.dateAdd", "call options.relativeTo.timeZone.getPossibleInstantsFor", - // NanosecondsToDays - "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 8. GetPlainDateTimeFor - "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 9. GetPlainDateTimeFor - // NanosecondsToDays → AddDaysToZonedDateTime - "call options.relativeTo.timeZone.getPossibleInstantsFor", - // NanosecondsToDays → AddDaysToZonedDateTime - "call options.relativeTo.timeZone.getPossibleInstantsFor", - "call options.relativeTo.calendar.dateAdd", // 12.d - "call options.relativeTo.calendar.dateAdd", // 12.f - "call options.relativeTo.calendar.dateUntil", // 12.n - "call options.relativeTo.calendar.dateAdd", // 12.r MoveRelativeDate - "call options.relativeTo.calendar.dateAdd", // 12.x MoveRelativeDate - // MoveRelativeZonedDateTime → AddZonedDateTime + // DifferenceZonedDateTimeWithRounding → DifferenceZonedDateTime + "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 5 + "call options.relativeTo.timeZone.getPossibleInstantsFor", // 12.c + "call options.relativeTo.calendar.dateUntil", // 13.f + // RoundRelativeDuration + "call options.relativeTo.calendar.dateAdd", "call options.relativeTo.calendar.dateAdd", "call options.relativeTo.timeZone.getPossibleInstantsFor", - // BalanceDateDurationRelative - "call options.relativeTo.calendar.dateAdd", // 9.c - "call options.relativeTo.calendar.dateUntil", // 9.d + "call options.relativeTo.timeZone.getPossibleInstantsFor", ]); instanceYears.round(createOptionsObserver({ smallestUnit: "years", relativeTo: zonedRelativeTo })); assert.compareArray( @@ -409,9 +379,8 @@ assert.compareArray( ); actual.splice(0); // clear -// code path that hits UnbalanceDateDurationRelative, RoundDuration, and -// BalanceDateDurationRelative -const expectedOpsForUnbalanceRoundBalance = expectedOpsForZonedRelativeTo.concat([ +// code path that hits the special weeks/years case in BalanceDateDurationRelative +const expectedOpsForYearsWeeksSpecialCase = expectedOpsForZonedRelativeTo.concat([ // ToTemporalDate "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // lookup in Duration.p.round @@ -421,26 +390,28 @@ const expectedOpsForUnbalanceRoundBalance = expectedOpsForZonedRelativeTo.concat // RoundDuration → MoveRelativeZonedDateTime → AddZonedDateTime "call options.relativeTo.calendar.dateAdd", "call options.relativeTo.timeZone.getPossibleInstantsFor", // 13. GetInstantFor - // RoundDuration - "call options.relativeTo.calendar.dateAdd", // 14.p MoveRelativeDate - // MoveRelativeZonedDateTime → AddZonedDateTime + // DifferenceZonedDateTimeWithRounding → DifferenceZonedDateTime + "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 5 + "call options.relativeTo.timeZone.getPossibleInstantsFor", // 12.c + "call options.relativeTo.calendar.dateUntil", // 13.f + // RoundRelativeDuration + "call options.relativeTo.calendar.dateUntil", + "call options.relativeTo.calendar.dateAdd", "call options.relativeTo.calendar.dateAdd", "call options.relativeTo.timeZone.getPossibleInstantsFor", - // BalanceDateDurationRelative - "call options.relativeTo.calendar.dateAdd", // 10.d - "call options.relativeTo.calendar.dateUntil", // 10.e + "call options.relativeTo.timeZone.getPossibleInstantsFor", ]); new Temporal.Duration(0, 1, 1).round(createOptionsObserver({ largestUnit: "years", smallestUnit: "weeks", relativeTo: zonedRelativeTo })); assert.compareArray( actual, - expectedOpsForUnbalanceRoundBalance, + expectedOpsForYearsWeeksSpecialCase, "order of operations with largestUnit = years, smallestUnit = weeks, and ZonedDateTime relativeTo" ); actual.splice(0); // clear // code path that skips user code calls in BalanceDateDurationRelative due to // special case for largestUnit months and smallestUnit weeks -const expectedOpsForWeeksSpecialCase = expectedOpsForZonedRelativeTo.concat([ +const expectedOpsForMonthsWeeksSpecialCase = expectedOpsForZonedRelativeTo.concat([ // ToTemporalDate "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // lookup in Duration.p.round @@ -449,16 +420,21 @@ const expectedOpsForWeeksSpecialCase = expectedOpsForZonedRelativeTo.concat([ // RoundDuration → MoveRelativeZonedDateTime → AddZonedDateTime "call options.relativeTo.calendar.dateAdd", "call options.relativeTo.timeZone.getPossibleInstantsFor", // 13. GetInstantFor - // RoundDuration - "call options.relativeTo.calendar.dateAdd", // 14.p MoveRelativeDate - // MoveRelativeZonedDateTime → AddZonedDateTime + // DifferenceZonedDateTimeWithRounding → DifferenceZonedDateTime + "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 5 + "call options.relativeTo.timeZone.getPossibleInstantsFor", // 12.c + "call options.relativeTo.calendar.dateUntil", // 13.f + // RoundRelativeDuration + "call options.relativeTo.calendar.dateUntil", "call options.relativeTo.calendar.dateAdd", + "call options.relativeTo.calendar.dateAdd", + "call options.relativeTo.timeZone.getPossibleInstantsFor", "call options.relativeTo.timeZone.getPossibleInstantsFor", ]); new Temporal.Duration(0, 1, 1).round(createOptionsObserver({ largestUnit: "months", smallestUnit: "weeks", relativeTo: zonedRelativeTo })); assert.compareArray( actual, - expectedOpsForWeeksSpecialCase, + expectedOpsForMonthsWeeksSpecialCase, "order of operations with largestUnit = months, smallestUnit = weeks, and ZonedDateTime relativeTo" ); actual.splice(0); // clear diff --git a/test/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-getpossibleinstantsfor-called-with-iso8601-calendar.js b/test/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-getpossibleinstantsfor-called-with-iso8601-calendar.js index 99ba61bb4b..1ef0125cb2 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-getpossibleinstantsfor-called-with-iso8601-calendar.js +++ b/test/built-ins/Temporal/Duration/prototype/round/relativeto-propertybag-getpossibleinstantsfor-called-with-iso8601-calendar.js @@ -53,4 +53,4 @@ const relativeTo = { year: 2000, month: 5, day: 2, timeZone, calendar: nonBuilti const instance = new Temporal.Duration(1, 0, 0, 0, 24); instance.round({ largestUnit: "years", relativeTo }); -assert.sameValue(timeZone.calls, 8, "getPossibleInstantsFor should have been called 8 times"); +assert.sameValue(timeZone.calls, 6, "getPossibleInstantsFor should have been called 6 times"); diff --git a/test/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-normalized-time-duration-to-days-range-errors.js b/test/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-normalized-time-duration-to-days-range-errors.js deleted file mode 100644 index 32552a2608..0000000000 --- a/test/built-ins/Temporal/Duration/prototype/round/relativeto-zoneddatetime-normalized-time-duration-to-days-range-errors.js +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (C) 2022 Igalia, S.L. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-temporal.duration.prototype.round -description: > - Abstract operation NormalizedTimeDurationToDays can throw four different - RangeErrors. -info: | - NormalizedTimeDurationToDays ( norm, zonedRelativeTo, timeZoneRec [ , precalculatedPlainDateTime ] ) - 23. If days < 0 and sign = 1, throw a RangeError exception. - 24. If days > 0 and sign = -1, throw a RangeError exception. - ... - 26. If NormalizedTimeDurationSign(_norm_) = 1 and sign = -1, throw a RangeError exception. - ... - 29. If dayLength ≥ 2⁵³, throw a RangeError exception. -features: [Temporal, BigInt] -includes: [temporalHelpers.js] ----*/ - -const oneNsDuration = Temporal.Duration.from({ nanoseconds: 1 }); -const negOneNsDuration = Temporal.Duration.from({ nanoseconds: -1 }); -const dayNs = 86_400_000_000_000; -const epochInstant = new Temporal.Instant(0n); - -function timeZoneSubstituteValues( - getPossibleInstantsFor, - getOffsetNanosecondsFor -) { - const tz = new Temporal.TimeZone("UTC"); - TemporalHelpers.substituteMethod( - tz, - "getPossibleInstantsFor", - getPossibleInstantsFor - ); - TemporalHelpers.substituteMethod( - tz, - "getOffsetNanosecondsFor", - getOffsetNanosecondsFor - ); - return tz; -} - -// Step 23: days < 0 and sign = 1 -let zdt = new Temporal.ZonedDateTime( - 0n, // Sets _startNs_ to 0 - timeZoneSubstituteValues( - [[epochInstant]], // Returned in step 16, setting _relativeResult_ - [ - TemporalHelpers.SUBSTITUTE_SKIP, // Pre-conversion in Duration.p.round - dayNs - 1, // Returned in step 8, setting _startDateTime_ - -dayNs + 1, // Returned in step 9, setting _endDateTime_ - ] - ) -); -assert.throws(RangeError, () => - // Using 1ns duration sets _nanoseconds_ to 1 and _sign_ to 1 - oneNsDuration.round({ - relativeTo: zdt, - smallestUnit: "days", - }), - "RangeError when days < 0 and sign = 1" -); - -// Step 24: days > 0 and sign = -1 -zdt = new Temporal.ZonedDateTime( - 0n, // Sets _startNs_ to 0 - timeZoneSubstituteValues( - [[epochInstant]], // Returned in step 16, setting _relativeResult_ - [ - TemporalHelpers.SUBSTITUTE_SKIP, // Pre-conversion in Duration.p.round - -dayNs + 1, // Returned in step 8, setting _startDateTime_ - dayNs - 1, // Returned in step 9, setting _endDateTime_ - ] - ) -); -assert.throws(RangeError, () => - // Using -1ns duration sets _nanoseconds_ to -1 and _sign_ to -1 - negOneNsDuration.round({ - relativeTo: zdt, - smallestUnit: "days", - }), - "RangeError when days > 0 and sign = -1" -); - -// Step 26: nanoseconds > 0 and sign = -1 -zdt = new Temporal.ZonedDateTime( - 0n, // Sets _startNs_ to 0 - timeZoneSubstituteValues( - [ - [new Temporal.Instant(-2n)], // Returned in step 16, setting _relativeResult_ - [new Temporal.Instant(-4n)], // Returned in step 19, setting _oneDayFarther_ - ], - [ - TemporalHelpers.SUBSTITUTE_SKIP, // Pre-conversion in Duration.p.round - dayNs - 1, // Returned in step 8, setting _startDateTime_ - -dayNs + 1, // Returned in step 9, setting _endDateTime_ - ] - ) -); -assert.throws(RangeError, () => - // Using -1ns duration sets _nanoseconds_ to -1 and _sign_ to -1 - negOneNsDuration.round({ - relativeTo: zdt, - smallestUnit: "days", - }), - "RangeError when nanoseconds > 0 and sign = -1" -); - -// Step 29: day length is an unsafe integer -zdt = new Temporal.ZonedDateTime( - 0n, - timeZoneSubstituteValues( - // Not called in step 16 because _days_ = 0 - // Returned in step 19, making _oneDayFarther_ 2^53 ns later than _relativeResult_ - [[new Temporal.Instant(2n ** 53n)]], - [] - ) -); -assert.throws(RangeError, () => - oneNsDuration.round({ - relativeTo: zdt, - smallestUnit: "days", - }), - "Should throw RangeError when time zone calculates an outrageous day length" -); diff --git a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-ceil.js b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-ceil.js index 27306ed1df..e12e1e442b 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-ceil.js +++ b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-ceil.js @@ -18,7 +18,7 @@ const relativeToBackwards = new Temporal.PlainDate(2020, 12, 1); const expected = [ ["years", [6], [-5]], ["months", [5, 8], [-5, -7]], - ["weeks", [5, 6, 9], [-5, -6, -8]], + ["weeks", [5, 7, 4], [-5, -7, -3]], ["days", [5, 7, 0, 28], [-5, -7, 0, -27]], ["hours", [5, 7, 0, 27, 17], [-5, -7, 0, -27, -16]], ["minutes", [5, 7, 0, 27, 16, 31], [-5, -7, 0, -27, -16, -30]], diff --git a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-expand.js b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-expand.js index 1119637349..65c336c168 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-expand.js +++ b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-expand.js @@ -18,7 +18,7 @@ const relativeToBackwards = new Temporal.PlainDate(2020, 12, 1); const expected = [ ["years", [6], [-6]], ["months", [5, 8], [-5, -8]], - ["weeks", [5, 6, 9], [-5, -6, -9]], + ["weeks", [5, 7, 4], [-5, -7, -4]], ["days", [5, 7, 0, 28], [-5, -7, 0, -28]], ["hours", [5, 7, 0, 27, 17], [-5, -7, 0, -27, -17]], ["minutes", [5, 7, 0, 27, 16, 31], [-5, -7, 0, -27, -16, -31]], diff --git a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-floor.js b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-floor.js index 7e875cc95c..aba4aada49 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-floor.js +++ b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-floor.js @@ -18,7 +18,7 @@ const relativeToBackwards = new Temporal.PlainDate(2020, 12, 1); const expected = [ ["years", [5], [-6]], ["months", [5, 7], [-5, -8]], - ["weeks", [5, 6, 8], [-5, -6, -9]], + ["weeks", [5, 7, 3], [-5, -7, -4]], ["days", [5, 7, 0, 27], [-5, -7, 0, -28]], ["hours", [5, 7, 0, 27, 16], [-5, -7, 0, -27, -17]], ["minutes", [5, 7, 0, 27, 16, 30], [-5, -7, 0, -27, -16, -31]], diff --git a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfCeil.js b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfCeil.js index 556638410c..f690237464 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfCeil.js +++ b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfCeil.js @@ -18,7 +18,7 @@ const relativeToBackwards = new Temporal.PlainDate(2020, 12, 1); const expected = [ ["years", [6], [-6]], ["months", [5, 8], [-5, -8]], - ["weeks", [5, 6, 8], [-5, -6, -8]], + ["weeks", [5, 7, 4], [-5, -7, -4]], ["days", [5, 7, 0, 28], [-5, -7, 0, -28]], ["hours", [5, 7, 0, 27, 17], [-5, -7, 0, -27, -17]], ["minutes", [5, 7, 0, 27, 16, 30], [-5, -7, 0, -27, -16, -30]], diff --git a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfEven.js b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfEven.js index 1facefa910..289a20cb55 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfEven.js +++ b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfEven.js @@ -18,7 +18,7 @@ const relativeToBackwards = new Temporal.PlainDate(2020, 12, 1); const expected = [ ["years", [6], [-6]], ["months", [5, 8], [-5, -8]], - ["weeks", [5, 6, 8], [-5, -6, -8]], + ["weeks", [5, 7, 4], [-5, -7, -4]], ["days", [5, 7, 0, 28], [-5, -7, 0, -28]], ["hours", [5, 7, 0, 27, 17], [-5, -7, 0, -27, -17]], ["minutes", [5, 7, 0, 27, 16, 30], [-5, -7, 0, -27, -16, -30]], diff --git a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfExpand.js b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfExpand.js index e5544b0e2b..e62dc933ca 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfExpand.js +++ b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfExpand.js @@ -18,7 +18,7 @@ const relativeToBackwards = new Temporal.PlainDate(2020, 12, 1); const expected = [ ["years", [6], [-6]], ["months", [5, 8], [-5, -8]], - ["weeks", [5, 6, 8], [-5, -6, -8]], + ["weeks", [5, 7, 4], [-5, -7, -4]], ["days", [5, 7, 0, 28], [-5, -7, 0, -28]], ["hours", [5, 7, 0, 27, 17], [-5, -7, 0, -27, -17]], ["minutes", [5, 7, 0, 27, 16, 30], [-5, -7, 0, -27, -16, -30]], diff --git a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfFloor.js b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfFloor.js index 452893743f..d38989e8f0 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfFloor.js +++ b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfFloor.js @@ -18,7 +18,7 @@ const relativeToBackwards = new Temporal.PlainDate(2020, 12, 1); const expected = [ ["years", [6], [-6]], ["months", [5, 8], [-5, -8]], - ["weeks", [5, 6, 8], [-5, -6, -8]], + ["weeks", [5, 7, 4], [-5, -7, -4]], ["days", [5, 7, 0, 28], [-5, -7, 0, -28]], ["hours", [5, 7, 0, 27, 17], [-5, -7, 0, -27, -17]], ["minutes", [5, 7, 0, 27, 16, 30], [-5, -7, 0, -27, -16, -30]], diff --git a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfTrunc.js b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfTrunc.js index 2fa6a810b8..c102efeea5 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfTrunc.js +++ b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-halfTrunc.js @@ -18,7 +18,7 @@ const relativeToBackwards = new Temporal.PlainDate(2020, 12, 1); const expected = [ ["years", [6], [-6]], ["months", [5, 8], [-5, -8]], - ["weeks", [5, 6, 8], [-5, -6, -8]], + ["weeks", [5, 7, 4], [-5, -7, -4]], ["days", [5, 7, 0, 28], [-5, -7, 0, -28]], ["hours", [5, 7, 0, 27, 17], [-5, -7, 0, -27, -17]], ["minutes", [5, 7, 0, 27, 16, 30], [-5, -7, 0, -27, -16, -30]], diff --git a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-trunc.js b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-trunc.js index ffe1beb00c..817545903d 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/roundingmode-trunc.js +++ b/test/built-ins/Temporal/Duration/prototype/round/roundingmode-trunc.js @@ -18,7 +18,7 @@ const relativeToBackwards = new Temporal.PlainDate(2020, 12, 1); const expected = [ ["years", [5], [-5]], ["months", [5, 7], [-5, -7]], - ["weeks", [5, 6, 8], [-5, -6, -8]], + ["weeks", [5, 7, 3], [-5, -7, -3]], ["days", [5, 7, 0, 27], [-5, -7, 0, -27]], ["hours", [5, 7, 0, 27, 16], [-5, -7, 0, -27, -16]], ["minutes", [5, 7, 0, 27, 16, 30], [-5, -7, 0, -27, -16, -30]], diff --git a/test/built-ins/Temporal/Duration/prototype/round/throws-in-unbalance-duration-relative-when-sign-mismatched.js b/test/built-ins/Temporal/Duration/prototype/round/throws-in-unbalance-duration-relative-when-sign-mismatched.js deleted file mode 100644 index 7e32ef0f49..0000000000 --- a/test/built-ins/Temporal/Duration/prototype/round/throws-in-unbalance-duration-relative-when-sign-mismatched.js +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2022 André Bargull. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.duration.prototype.round -description: > - UnbalanceDurationRelative throws a RangeError when duration signs don't match. -features: [Temporal] ----*/ - -var duration = Temporal.Duration.from({ - years: 1, - months: 0, - weeks: 1, -}); - -var cal = new class extends Temporal.Calendar { - called = 0; - dateUntil(one, two, options) { - ++this.called; - var result = super.dateUntil(one, two, options); - return this.called === 1 ? result.negated() : result; - } -}("iso8601"); - -var relativeTo = new Temporal.PlainDateTime(1970, 1, 1, 0, 0, 0, 0, 0, 0, cal); -assert.sameValue(relativeTo.getCalendar(), cal); - -var options = { - smallestUnit: "days", - largestUnit: "month", - relativeTo, -}; - -assert.throws(RangeError, () => duration.round(options)); diff --git a/test/built-ins/Temporal/Duration/prototype/round/timezone-getpossibleinstantsfor-iterable.js b/test/built-ins/Temporal/Duration/prototype/round/timezone-getpossibleinstantsfor-iterable.js index 26d685aba6..c88af71ceb 100644 --- a/test/built-ins/Temporal/Duration/prototype/round/timezone-getpossibleinstantsfor-iterable.js +++ b/test/built-ins/Temporal/Duration/prototype/round/timezone-getpossibleinstantsfor-iterable.js @@ -34,9 +34,10 @@ features: [Temporal] const expected = [ "2000-01-01T00:00:00", // called once on the input relativeTo object + "2001-02-09T00:00:00", // called once adding the duration to relativeTo "2001-02-09T00:00:00", // called once on relativeTo plus years, months, weeks, days from the receiver - "2001-02-10T00:00:00", // called once on the previous value plus the calendar days difference between that and the time part of the duration - "2001-02-01T00:00:00", // called once in the balancing step on intermediate relativeTo + "2001-02-01T00:00:00", // called to find the lower bound for months rounding + "2001-03-01T00:00:00", // called to find the upper bound for months rounding ]; TemporalHelpers.checkTimeZonePossibleInstantsIterable((timeZone) => { diff --git a/test/built-ins/Temporal/Duration/prototype/total/calendar-dateadd-called-with-options-undefined.js b/test/built-ins/Temporal/Duration/prototype/total/calendar-dateadd-called-with-options-undefined.js index c4f048640c..e5e173f65a 100644 --- a/test/built-ins/Temporal/Duration/prototype/total/calendar-dateadd-called-with-options-undefined.js +++ b/test/built-ins/Temporal/Duration/prototype/total/calendar-dateadd-called-with-options-undefined.js @@ -17,7 +17,7 @@ const relativeTo = new Temporal.ZonedDateTime(0n, timeZone, calendar); // Total of a calendar unit where larger calendar units have to be converted // down, to cover the path that goes through UnbalanceDateDurationRelative // The calls come from the path: -// Duration.total() -> UnbalanceDateDurationRelative -> calendar.dateAdd() +// Duration.total() -> AddZonedDateTime -> calendar.dateAdd() const instance1 = new Temporal.Duration(1, 1, 1, 1, 1); instance1.total({ unit: "days", relativeTo }); @@ -27,11 +27,9 @@ assert.sameValue(calendar.dateAddCallCount, 1, "converting larger calendar units // up, to cover the path that goes through MoveRelativeZonedDateTime // The calls come from these paths: // Duration.total() -> -// MoveRelativeZonedDateTime -> AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() -// BalanceDuration -> -// AddZonedDateTime -> BuiltinTimeZoneGetInstantFor -> calendar.dateAdd() -// RoundDuration -> -// MoveRelativeDate -> calendar.dateAdd() +// AddZonedDateTime -> calendar.dateAdd() +// DifferenceZonedDateTimeWithRounding -> RoundRelativeDuration -> NudgeToCalendarUnit -> +// AddDateTime -> calendar.dateAdd() (2x) calendar.dateAddCallCount = 0; diff --git a/test/built-ins/Temporal/Duration/prototype/total/calendar-dateuntil-called-with-singular-largestunit.js b/test/built-ins/Temporal/Duration/prototype/total/calendar-dateuntil-called-with-singular-largestunit.js index d7f0a65ad3..2c185bb638 100644 --- a/test/built-ins/Temporal/Duration/prototype/total/calendar-dateuntil-called-with-singular-largestunit.js +++ b/test/built-ins/Temporal/Duration/prototype/total/calendar-dateuntil-called-with-singular-largestunit.js @@ -3,38 +3,9 @@ /*--- esid: sec-temporal.duration.prototype.total -description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form -info: | - sec-temporal.duration.prototype.total steps 7–11: - 7. Let _unbalanceResult_ be ? UnbalanceDateDurationRelative(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _unit_, _relativeTo_). - ... - 10. Let _balanceResult_ be ? BalanceDuration(_unbalanceResult_.[[Days]], _unbalanceResult_.[[Hours]], _unbalanceResult_.[[Minutes]], _unbalanceResult_.[[Seconds]], _unbalanceResult_.[[Milliseconds]], _unbalanceResult_.[[Microseconds]], _unbalanceResult_.[[Nanoseconds]], _unit_, _intermediate_). - 11. Let _roundResult_ 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_). - sec-temporal-unbalancedatedurationrelative step 3: - 3. If _largestUnit_ is *"month"*, then - ... - g. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*). - h. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"month"*). - i. Let _untilResult_ be ? CalendarDateUntil(_calendarRec_.[[Receiver]], _plainRelativeTo_, _later_, _untilOptions_, _calendarRec_.[[DateUntil]]). - sec-temporal-balanceduration step 3.a: - 3. If _largestUnit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then - a. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _relativeTo_). - sec-temporal-roundduration steps 5.d and 8.n–p: - 5. If _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then - ... - d. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _intermediate_). - ... - 8. If _unit_ is *"year"*, then - ... - n. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*). - o. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"year"*). - p. Let _timePassed_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _daysLater_, _untilOptions_) - sec-temporal-nanosecondstodays step 11: - 11. 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"*). - sec-temporal-differenceisodatetime steps 9–11: - 9. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_). - 10. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _dateLargestUnit_). - 11. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_). +description: > + The options object passed to calendar.dateUntil has a largestUnit property + with its value in the singular form includes: [compareArray.js, temporalHelpers.js] features: [Temporal] ---*/ @@ -53,7 +24,7 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( { years: ["year"], months: ["month"], - weeks: ["week"], + weeks: ["week", "week"], days: [], hours: [], minutes: [], diff --git a/test/built-ins/Temporal/Duration/prototype/total/dst-rounding-result.js b/test/built-ins/Temporal/Duration/prototype/total/dst-rounding-result.js index 47e1d3de75..d0d8773a0a 100644 --- a/test/built-ins/Temporal/Duration/prototype/total/dst-rounding-result.js +++ b/test/built-ins/Temporal/Duration/prototype/total/dst-rounding-result.js @@ -15,23 +15,23 @@ const timeZone = TemporalHelpers.springForwardFallBackTimeZone(); { // Date part of duration lands on skipped DST hour, causing disambiguation - const duration = new Temporal.Duration(0, 1, 0, 15, 12); + const duration = new Temporal.Duration(0, 1, 0, 15, 11, 30); const relativeTo = new Temporal.ZonedDateTime( 950868000_000_000_000n /* = 2000-02-18T10Z */, timeZone); /* = 2000-02-18T02-08 in local time */ assert.sameValue(duration.total({ unit: "months", relativeTo }), 1.5, - "1 month 15 days 12 hours should be exactly 1.5 months"); + "1 month 15 days 11:30 should be exactly 1.5 months"); } { // Month-only part of duration lands on skipped DST hour, should not cause // disambiguation - const duration = new Temporal.Duration(0, 1, 0, 15); + const duration = new Temporal.Duration(0, 1, 0, 15, 0, 30); const relativeTo = new Temporal.ZonedDateTime( 951991200_000_000_000n /* = 2000-03-02T10Z */, timeZone); /* = 2000-03-02T02-08 in local time */ assert.sameValue(duration.total({ unit: "months", relativeTo }), 1.5, - "1 month 15 days should be exactly 1.5 months"); + "1 month 15 days 00:30 should be exactly 1.5 months"); } diff --git a/test/built-ins/Temporal/Duration/prototype/total/normalized-time-duration-to-days-loop-arbitrarily.js b/test/built-ins/Temporal/Duration/prototype/total/normalized-time-duration-to-days-loop-arbitrarily.js deleted file mode 100644 index 4e61345b59..0000000000 --- a/test/built-ins/Temporal/Duration/prototype/total/normalized-time-duration-to-days-loop-arbitrarily.js +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2022 Igalia, S.L. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.duration.prototype.total -description: > - NormalizedTimeDurationToDays should not be able to loop arbitrarily. -info: | - NormalizedTimeDurationToDays ( norm, zonedRelativeTo, timeZoneRec [ , precalculatedPlainDatetime ] ) - ... - 22. If NormalizedTimeDurationSign(_oneDayLess_) × _sign_ ≥ 0, then - a. Set _norm_ to _oneDayLess_. - b. Set _relativeResult_ to _oneDayFarther_. - c. Set _days_ to _days_ + _sign_. - d. Set _oneDayFarther_ to ? AddDaysToZonedDateTime(_relativeResult_.[[Instant]], _relativeResult_.[[DateTime]], _timeZoneRec_, _zonedRelativeTo_.[[Calendar]], _sign_). - e. Set dayLengthNs to NormalizedTimeDurationFromEpochNanosecondsDifference(_oneDayFarther.[[EpochNanoseconds]], relativeResult.[[EpochNanoseconds]]). - f. If NormalizedTimeDurationSign(? SubtractNormalizedTimeDuration(_norm_, _dayLengthNs_)) × _sign_ ≥ 0, then - i. Throw a *RangeError* exception. -features: [Temporal] ----*/ - -const duration = Temporal.Duration.from({ days: 1 }); - -const dayLengthNs = 86400000000000n; -const dayInstant = new Temporal.Instant(dayLengthNs); -let calls = 0; -const timeZone = new class extends Temporal.TimeZone { - getPossibleInstantsFor() { - calls++; - return [dayInstant]; - } -}("UTC"); - -const relativeTo = new Temporal.ZonedDateTime(0n, timeZone); - -assert.throws(RangeError, () => duration.total({ unit: "days", relativeTo }), "indefinite loop is prevented"); -assert.sameValue(calls, 4, "getPossibleInstantsFor is not called indefinitely"); - // Expected calls: - // AddZonedDateTime (1) - // NormalizedTimeDurationToDays -> - // AddDaysToZonedDateTime (2, step 12) - // AddDaysToZonedDateTime (3, step 15) - // AddDaysToZonedDateTime (4, step 18.d) diff --git a/test/built-ins/Temporal/Duration/prototype/total/order-of-operations.js b/test/built-ins/Temporal/Duration/prototype/total/order-of-operations.js index cafaaae372..f2393ee742 100644 --- a/test/built-ins/Temporal/Duration/prototype/total/order-of-operations.js +++ b/test/built-ins/Temporal/Duration/prototype/total/order-of-operations.js @@ -105,22 +105,22 @@ actual.splice(0); // clear // code path through RoundDuration that rounds to the nearest year with minimal calendar calls: const expectedOpsForMinimalYearRounding = expectedOpsForPlainRelativeTo.concat([ - // 12.d and 12.f not called because years, months, weeks are 0 - "call options.relativeTo.calendar.dateUntil", // 12.n - // 12.r not called because years, months, weeks are 0 - "call options.relativeTo.calendar.dateAdd", // 12.x MoveRelativeDate + // DifferencePlainDateTimeWithRounding -> DifferenceISODateTime + "call options.relativeTo.calendar.dateUntil", + "call options.relativeTo.calendar.dateAdd", ]); instance.total(createOptionsObserver({ unit: "years", relativeTo: plainRelativeTo })); assert.compareArray(actual, expectedOpsForMinimalYearRounding, "order of operations with years = 0 and unit = years"); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest year: +// code path through Duration.p.total that rounds to the nearest year: const expectedOpsForYearRounding = expectedOpsForPlainRelativeTo.concat([ - "call options.relativeTo.calendar.dateAdd", // 12.d - "call options.relativeTo.calendar.dateAdd", // 12.f - "call options.relativeTo.calendar.dateUntil", // 12.n - "call options.relativeTo.calendar.dateAdd", // 12.r MoveRelativeDate - "call options.relativeTo.calendar.dateAdd", // 12.x MoveRelativeDate + "call options.relativeTo.calendar.dateAdd", // Duration.p.total 19.c + // DifferencePlainDateTimeWithRounding + "call options.relativeTo.calendar.dateUntil", // 5 + // RoundRelativeDuration + "call options.relativeTo.calendar.dateAdd", + "call options.relativeTo.calendar.dateAdd", ]); const instanceYears = new Temporal.Duration(1, 12, 0, 0, /* hours = */ 2400); instanceYears.total(createOptionsObserver({ unit: "years", relativeTo: plainRelativeTo })); @@ -129,15 +129,12 @@ actual.splice(0); // clear // code path through Duration.prototype.total that rounds to the nearest month: const expectedOpsForMonthRounding = expectedOpsForPlainRelativeTo.concat([ - // UnbalanceDateDurationRelative - "call options.relativeTo.calendar.dateAdd", // 3.f - "call options.relativeTo.calendar.dateUntil", // 3.i - // RoundDuration - "call options.relativeTo.calendar.dateAdd", // 13.c - "call options.relativeTo.calendar.dateAdd", // 13.e - "call options.relativeTo.calendar.dateUntil", // 13.m - "call options.relativeTo.calendar.dateAdd", // 13.q MoveRelativeDate - "call options.relativeTo.calendar.dateAdd", // 13.w MoveRelativeDate + "call options.relativeTo.calendar.dateAdd", // Duration.p.total 19.c + // DifferencePlainDateTimeWithRounding + "call options.relativeTo.calendar.dateUntil", // 5 + // RoundRelativeDuration + "call options.relativeTo.calendar.dateAdd", + "call options.relativeTo.calendar.dateAdd", ]); const instance2 = new Temporal.Duration(1, 0, 0, 62); instance2.total(createOptionsObserver({ unit: "months", relativeTo: plainRelativeTo })); @@ -146,12 +143,13 @@ actual.splice(0); // clear // code path through Duration.prototype.total that rounds to the nearest week: const expectedOpsForWeekRounding = expectedOpsForPlainRelativeTo.concat([ - // UnbalanceDateDurationRelative - "call options.relativeTo.calendar.dateAdd", // 4.e - // RoundDuration - "call options.relativeTo.calendar.dateUntil", // 14.f - "call options.relativeTo.calendar.dateAdd", // 14.j MoveRelativeDate - "call options.relativeTo.calendar.dateAdd", // 14.p MoveRelativeDate + "call options.relativeTo.calendar.dateAdd", // Duration.p.total 19.c + // DifferencePlainDateTimeWithRounding + "call options.relativeTo.calendar.dateUntil", // 5 + // RoundRelativeDuration + "call options.relativeTo.calendar.dateUntil", + "call options.relativeTo.calendar.dateAdd", + "call options.relativeTo.calendar.dateAdd", ]); const instance3 = new Temporal.Duration(1, 1, 0, 15); instance3.total(createOptionsObserver({ unit: "weeks", relativeTo: plainRelativeTo })); @@ -268,28 +266,22 @@ assert.compareArray(actual, expectedOpsForZonedRelativeTo.concat([ ]), "order of operations for ZonedDateTime relativeTo"); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest year with minimal calendar operations: +// code path through Duration.p.total that rounds to the nearest year with +// minimal calendar operations: const expectedOpsForMinimalYearRoundingZoned = expectedOpsForZonedRelativeTo.concat([ // ToTemporalDate "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // lookup in Duration.p.total "get options.relativeTo.calendar.dateAdd", "get options.relativeTo.calendar.dateUntil", - // BalancePossiblyInfiniteDuration → NanosecondsToDays - "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 7. GetPlainDateTimeFor - "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 11. GetPlainDateTimeFor - // BalancePossiblyInfiniteDuration → NanosecondsToDays → AddDaysToZonedDateTime + // DifferenceZonedDateTimeWithRounding → DifferenceZonedDateTime + "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 5 + "call options.relativeTo.timeZone.getPossibleInstantsFor", // 12.c + "call options.relativeTo.calendar.dateUntil", // 13.f + // RoundRelativeDuration + "call options.relativeTo.calendar.dateAdd", "call options.relativeTo.timeZone.getPossibleInstantsFor", - // BalancePossiblyInfiniteDuration → NanosecondsToDays → AddDaysToZonedDateTime "call options.relativeTo.timeZone.getPossibleInstantsFor", -], [ - // code path through RoundDuration that rounds to the nearest year: - // MoveRelativeZonedDateTime → AddDaysToZonedDateTime - "call options.relativeTo.timeZone.getPossibleInstantsFor", - // 12.d and 12.f not called because years, months, weeks are 0 - "call options.relativeTo.calendar.dateUntil", // 12.n - // 12.r not called because years, months, weeks are 0 - "call options.relativeTo.calendar.dateAdd", // 12.x MoveRelativeDate ]); instance.total(createOptionsObserver({ unit: "years", relativeTo: zonedRelativeTo })); assert.compareArray( @@ -299,32 +291,25 @@ assert.compareArray( ); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest year: +// code path through Duration.p.total that rounds to years: const expectedOpsForYearRoundingZoned = expectedOpsForZonedRelativeTo.concat([ // ToTemporalDate "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // lookup in Duration.p.total "get options.relativeTo.calendar.dateAdd", "get options.relativeTo.calendar.dateUntil", - // MoveRelativeZonedDateTime → AddZonedDateTime + // 18.c AddZonedDateTime + "call options.relativeTo.calendar.dateAdd", + "call options.relativeTo.timeZone.getPossibleInstantsFor", // 13. GetInstantFor + // DifferenceZonedDateTimeWithRounding → DifferenceZonedDateTime + "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 5 + "call options.relativeTo.timeZone.getPossibleInstantsFor", // 12.c + "call options.relativeTo.calendar.dateUntil", // 13.f + // RoundRelativeDuration + "call options.relativeTo.calendar.dateAdd", "call options.relativeTo.calendar.dateAdd", "call options.relativeTo.timeZone.getPossibleInstantsFor", - // BalancePossiblyInfiniteTimeDurationRelative → NanosecondsToDays - "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 8. GetPlainDateTimeFor - "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 9. GetPlainDateTimeFor - // BalancePossiblyInfiniteTimeDurationRelative → NanosecondsToDays → AddDaysToZonedDateTime "call options.relativeTo.timeZone.getPossibleInstantsFor", - // BalancePossiblyInfiniteTimeDurationRelative → NanosecondsToDays → AddDaysToZonedDateTime - "call options.relativeTo.timeZone.getPossibleInstantsFor", - // RoundDuration → MoveRelativeZonedDateTime → AddZonedDateTime - "call options.relativeTo.calendar.dateAdd", - "call options.relativeTo.timeZone.getPossibleInstantsFor", - // RoundDuration - "call options.relativeTo.calendar.dateAdd", // 12.d - "call options.relativeTo.calendar.dateAdd", // 12.f - "call options.relativeTo.calendar.dateUntil", // 12.n - "call options.relativeTo.calendar.dateAdd", // 12.r MoveRelativeDate - "call options.relativeTo.calendar.dateAdd", // 12.x MoveRelativeDate ]); instanceYears.total(createOptionsObserver({ unit: "years", relativeTo: zonedRelativeTo })); assert.compareArray( @@ -334,60 +319,58 @@ assert.compareArray( ); actual.splice(0); // clear -// code path that hits UnbalanceDateDurationRelative and RoundDuration -const expectedOpsForUnbalanceRound = expectedOpsForZonedRelativeTo.concat([ +// code path through Duration.p.total that rounds to months: +const expectedOpsForMonthsRoundingZoned = expectedOpsForZonedRelativeTo.concat([ // ToTemporalDate "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // lookup in Duration.p.total "get options.relativeTo.calendar.dateAdd", "get options.relativeTo.calendar.dateUntil", - // No user code calls in UnbalanceDateDurationRelative - // MoveRelativeZonedDateTime → AddZonedDateTime + // 18.c AddZonedDateTime "call options.relativeTo.calendar.dateAdd", "call options.relativeTo.timeZone.getPossibleInstantsFor", // 13. GetInstantFor - // RoundDuration → MoveRelativeZonedDateTime → AddZonedDateTime + // DifferenceZonedDateTimeWithRounding → DifferenceZonedDateTime + "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 5 + "call options.relativeTo.timeZone.getPossibleInstantsFor", // 12.c + "call options.relativeTo.calendar.dateUntil", // 13.f + // RoundRelativeDuration "call options.relativeTo.calendar.dateAdd", - "call options.relativeTo.timeZone.getPossibleInstantsFor", // 13. GetInstantFor - // RoundDuration - "call options.relativeTo.calendar.dateAdd", // 13.c - "call options.relativeTo.calendar.dateAdd", // 13.e - "call options.relativeTo.calendar.dateUntil", // 13.m - "call options.relativeTo.calendar.dateAdd", // 13.w MoveRelativeDate + "call options.relativeTo.calendar.dateAdd", + "call options.relativeTo.timeZone.getPossibleInstantsFor", + "call options.relativeTo.timeZone.getPossibleInstantsFor", ]); new Temporal.Duration(0, 1, 1).total(createOptionsObserver({ unit: "months", relativeTo: zonedRelativeTo })); assert.compareArray( actual, - expectedOpsForUnbalanceRound, + expectedOpsForMonthsRoundingZoned, "order of operations with unit = months and ZonedDateTime relativeTo" ); actual.splice(0); // clear -// code path that avoids converting Zoned twice in BalanceTimeDurationRelative -const expectedOpsForBalanceRound = expectedOpsForZonedRelativeTo.concat([ +// code path through Duration.p.total that rounds to weeks: +const expectedOpsForWeeksRoundingZoned = expectedOpsForZonedRelativeTo.concat([ // ToTemporalDate "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // lookup in Duration.p.total "get options.relativeTo.calendar.dateAdd", "get options.relativeTo.calendar.dateUntil", - // No user code calls in UnbalanceDateDurationRelative - // No user code calls in AddZonedDateTime (years, months, weeks = 0) - // BalanceTimeDurationRelative - "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 4.a - "call options.relativeTo.timeZone.getPossibleInstantsFor", // 4.b - "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // NanosecondsToDays 9 - "call options.relativeTo.timeZone.getPossibleInstantsFor", // NanosecondsToDays 26 - "call options.relativeTo.timeZone.getPossibleInstantsFor", // NanosecondsToDays 31.a - // RoundDuration → MoveRelativeZonedDateTime → AddZonedDateTime - "call options.relativeTo.timeZone.getPossibleInstantsFor", // 10. GetInstantFor - // RoundDuration - "call options.relativeTo.calendar.dateUntil", // 14.f - "call options.relativeTo.calendar.dateAdd", // 14.j MoveRelativeDate - "call options.relativeTo.calendar.dateAdd", // 14.p MoveRelativeDate + // 18.c AddZonedDateTime + "call options.relativeTo.timeZone.getPossibleInstantsFor", // 13. GetInstantFor + // DifferenceZonedDateTimeWithRounding → DifferenceZonedDateTime + "call options.relativeTo.timeZone.getOffsetNanosecondsFor", // 5 + "call options.relativeTo.timeZone.getPossibleInstantsFor", // 12.c + "call options.relativeTo.calendar.dateUntil", // 13.f + // RoundRelativeDuration + "call options.relativeTo.calendar.dateUntil", + "call options.relativeTo.calendar.dateAdd", + "call options.relativeTo.calendar.dateAdd", + "call options.relativeTo.timeZone.getPossibleInstantsFor", + "call options.relativeTo.timeZone.getPossibleInstantsFor", ]); new Temporal.Duration(0, 0, 0, 1, 240).total(createOptionsObserver({ unit: "weeks", relativeTo: zonedRelativeTo })); assert.compareArray( actual, - expectedOpsForBalanceRound, + expectedOpsForWeeksRoundingZoned, "order of operations with unit = weeks and no calendar units" ); actual.splice(0); // clear diff --git a/test/built-ins/Temporal/Duration/prototype/total/precision-exact-mathematical-values-3.js b/test/built-ins/Temporal/Duration/prototype/total/precision-exact-mathematical-values-3.js index 0e0bb8b961..9dfb40d1d2 100644 --- a/test/built-ins/Temporal/Duration/prototype/total/precision-exact-mathematical-values-3.js +++ b/test/built-ins/Temporal/Duration/prototype/total/precision-exact-mathematical-values-3.js @@ -25,7 +25,7 @@ info: | 12. If _unit_ is *"week"*, then ... s. Let _fractionalWeeks_ be _weeks_ + _fractionalDays_ / abs(_oneWeekDays_). -includes: [compareArray.js] +includes: [compareArray.js, temporalHelpers.js] features: [Temporal] ---*/ @@ -68,51 +68,48 @@ function f64Repr(f) { // ============ -const tz = new (class extends Temporal.TimeZone { - getPossibleInstantsFor() { - // Called in NormalizedTimeDurationToDays 19 from RoundDuration 7.b. - // Sets _result_.[[DayLength]] to 2⁵³ - 1 ns, its largest possible value - return [new Temporal.Instant(-86400_0000_0000_000_000_000n + 2n ** 53n - 1n)]; - } -})("UTC"); +function createTimeZone() { + const tz = new Temporal.TimeZone("UTC"); + TemporalHelpers.substituteMethod(tz, "getPossibleInstantsFor", [ + TemporalHelpers.SUBSTITUTE_SKIP, + [new Temporal.Instant(-86400_0000_0000_000_000_000n)], + [new Temporal.Instant(86400_0000_0000_000_000_000n - 100_000_000n)], + ]); + return tz; +} -const cal = new (class extends Temporal.Calendar { - dateAdd() { - // Called in MoveRelativeDate from RoundDuration 10.x, 11.x, or 12.q. - // Sets _oneYearDays_, _oneMonthDays_, or _oneWeekDays_ respectively to - // 200_000_000, its largest possible value. - return new Temporal.PlainDate(275760, 9, 13); - } -})("iso8601"); +function createRelativeTo() { + return new Temporal.ZonedDateTime(-86400_0000_0000_000_000_000n, createTimeZone()); +} -const relativeTo = new Temporal.ZonedDateTime(-86400_0000_0000_000_000_000n, tz, cal); const d = new Temporal.Duration(0, 0, 0, 0, 0, 0, 0, 0, 0, /* nanoseconds = */ 1); -/* - * RoundDuration step 7: - * ii. result = { [[Days]] = 0, [[Remainder]] = normalized time duration of 1 ns, - * [[DayLength]] = Number.MAX_SAFE_INTEGER } - * iii. fractionalDays = 0 + 0 + 1 / Number.MAX_SAFE_INTEGER - * step 10: - * y. oneYearDays = 200_000_000 - * z. fractionalYears = 0 + (1 / Number.MAX_SAFE_INTEGER) / 200_000_000 - */ +// NS_MAX_INSTANT = 86400 × 1e8 × 1e9 +// startEpochNs = -NS_MAX_INSTANT +// destEpochNs = -NS_MAX_INSTANT + 1 +// endEpochNs = NS_MAX_INSTANT - 1e8 +// progress = (destEpochNs - startEpochNs) / (endEpochNs - startEpochNs) +// = 1 / (2 × NS_MAX_INSTANT - 1e8) +// total = startDuration.years + progress = 0 + 1 / (2 × NS_MAX_INSTANT - 1e8) +// // Calculated with Python's Decimal module to 50 decimal places -const expected = 5.55111512312578_3318415740544369642963189519987393e-25; +const expected = 5.7870370370370_705268347050756396228860247432848547e-23; +// This is float 5.7870370370370_6998177e-23 +// Note: if calculated using floating point arithmetic, this will give the less +// precise value 5.7870370370370_7115726e-23 // Check that we are not accidentally losing precision in our expected value: - -assert.sameValue(expected, 5.55111512312578_373662e-25, "the float representation of the result is 5.55111512312578373662e-25"); +assert.sameValue(expected, 5.7870370370370_6998177e-23, "the float representation of the result is 5.7870370370370_6998177e-23"); assert.compareArray( f64Repr(expected), - [0x3a, 0xe5, 0x79, 0x8e, 0xe2, 0x30, 0x8c, 0x3b], - "the bit representation of the result is 0x3ae5798ee2308c3b" + [0x3b, 0x51, 0x7d, 0x80, 0xc6, 0xf1, 0x14, 0xa8], + "the bit representation of the result is 0x3b517d80c6f114a8" ); // The next Number in direction -Infinity is less precise. -assert.sameValue(nextDown(expected), 5.55111512312578_281826e-25, "the next Number in direction -Infinity is less precise"); +assert.sameValue(nextDown(expected), 5.7870370370370_6880628e-23, "the next Number in direction -Infinity is less precise"); // The next Number in direction +Infinity is less precise. -assert.sameValue(nextUp(expected), 5.55111512312578_465497e-25, "the next Number in direction +Infinity is less precise"); +assert.sameValue(nextUp(expected), 5.7870370370370_7115727e-23, "the next Number in direction +Infinity is less precise"); -assert.sameValue(d.total({ unit: "years", relativeTo }), expected, "Correct division by large number in years total"); -assert.sameValue(d.total({ unit: "months", relativeTo }), expected, "Correct division by large number in months total"); -assert.sameValue(d.total({ unit: "weeks", relativeTo }), expected, "Correct division by large number in weeks total"); +assert.sameValue(d.total({ unit: "years", relativeTo: createRelativeTo() }), expected, "Correct division by large number in years total"); +assert.sameValue(d.total({ unit: "months", relativeTo: createRelativeTo() }), expected, "Correct division by large number in months total"); +assert.sameValue(d.total({ unit: "weeks", relativeTo: createRelativeTo() }), expected, "Correct division by large number in weeks total"); diff --git a/test/built-ins/Temporal/Duration/prototype/total/precision-exact-mathematical-values-4.js b/test/built-ins/Temporal/Duration/prototype/total/precision-exact-mathematical-values-4.js index 7514ac9853..02e4512c4a 100644 --- a/test/built-ins/Temporal/Duration/prototype/total/precision-exact-mathematical-values-4.js +++ b/test/built-ins/Temporal/Duration/prototype/total/precision-exact-mathematical-values-4.js @@ -67,86 +67,57 @@ function f64Repr(f) { } // ============ -// Set up contrived custom time zone and calendar to give dayLengthNs, -// oneYearDays, oneMonthDays, and oneWeekDays their largest possible values +// Set up contrived custom time zone to give the denominator of the fraction its +// largest possible value function createTimeZone() { const tz = new Temporal.TimeZone("UTC"); TemporalHelpers.substituteMethod(tz, "getPossibleInstantsFor", [ - TemporalHelpers.SUBSTITUTE_SKIP, // Duration.total step 19.a MoveRelativeZonedDateTime → AddZonedDateTime - TemporalHelpers.SUBSTITUTE_SKIP, // Duration.total step 19.e.ii AddDaysToZonedDateTime - TemporalHelpers.SUBSTITUTE_SKIP, // Duration.total step 19.i.ii NormalizedTimeDurationToDays step 16 - TemporalHelpers.SUBSTITUTE_SKIP, // Duration.total step 19.i.ii NormalizedTimeDurationToDays step 19 - [new Temporal.Instant(-86400_0000_0000_000_000_000n)], // RoundDuration step 7.a.i MoveRelativeZonedDateTime → AddZonedDateTime - [new Temporal.Instant(-86400_0000_0000_000_000_000n + 2n ** 53n - 1n)], // RoundDuration step 7.a.ii NormalizedTimeDurationToDays step 19 - // sets dayLengthNs to Number.MAX_SAFE_INTEGER + TemporalHelpers.SUBSTITUTE_SKIP, // Duration.total step 18.c AddZonedDateTime + TemporalHelpers.SUBSTITUTE_SKIP, // DifferenceZonedDateTimeWithRounding → DifferenceZonedDateTime → AddZonedDateTime + [new Temporal.Instant(-86400_0000_0000_000_000_000n)], + [new Temporal.Instant(86400_0000_0000_000_000_000n)], ]); return tz; } -function createCalendar() { - const cal = new Temporal.Calendar("iso8601"); - TemporalHelpers.substituteMethod(cal, "dateAdd", [ - TemporalHelpers.SUBSTITUTE_SKIP, // Duration.total step 19.a MoveRelativeZonedDateTime → AddZonedDateTime - TemporalHelpers.SUBSTITUTE_SKIP, // RoundDuration step 7.a.i MoveRelativeZonedDateTime → AddZonedDateTime - new Temporal.PlainDate(-271821, 4, 20), // RoundDuration step 10.d/11.d AddDate - new Temporal.PlainDate(-271821, 4, 20), // RoundDuration step 10.f/11.f AddDate - new Temporal.PlainDate(275760, 9, 13), // RoundDuration step 10.r/11.r MoveRelativeDate - // sets one{Year,Month,Week}Days to 200_000_000 - ]); - return cal; +function createRelativeTo() { + return new Temporal.ZonedDateTime(-86400_0000_0000_000_000_000n, createTimeZone()); } // ============ -// We will calculate the total years/months/weeks of durations with: -// 1 year/month/week, 1 day, 0.199000001 s +// We will calculate the total years of a duration of 1 year, 0.009254648 s -// RoundDuration step 7: -// ii. result = { [[Days]] = 1, [[Remainder]] = normalized time duration of 199_000_001 ns, -// [[DayLength]] = Number.MAX_SAFE_INTEGER } -// iii. fractionalDays = 1 + 0 + 199_000_001 / Number.MAX_SAFE_INTEGER -// step 10: (similar for steps 11 and 12 in the case of months/weeks) -// y. oneYearDays = 200_000_000 -// z. fractionalYears = 1 + (1 + 199_000_001 / Number.MAX_SAFE_INTEGER) / 200_000_000 +// NS_MAX_INSTANT = 86400 × 1e8 × 1e9 +// startEpochNs = -NS_MAX_INSTANT +// destEpochNs = -NS_MAX_INSTANT + 366 * 86400 * 1e9 + 9254648 +// endEpochNs = NS_MAX_INSTANT +// progress = (destEpochNs - startEpochNs) / (endEpochNs - startEpochNs) +// = (366 * 86400 * 1e9 + 9254648) / (2 × NS_MAX_INSTANT) +// total = startDuration.years + progress +// = 1 + (366 * 86400 * 1e9 + 9254648) / (2 × NS_MAX_INSTANT) // -// Note: if calculated as 1 + 1/200_000_000 + 199_000_001 / Number.MAX_SAFE_INTEGER / 200_000_000 -// this will lose precision and give the result 1.000000005. - // Calculated with Python's Decimal module to 50 decimal places -const expected = 1.000000005000000_1104671915053146003490515686745299; +const expected = 1.000001830000000_5355699074074074074074074074074074; +// This is float 1.000001830000000_64659 +// Note: if calculated using floating point arithmetic, this will give the less +// precise value 1.000001830000000_42454 // Check that we are not accidentally losing precision in our expected value: -assert.sameValue(expected, 1.000000005000000_2, "the float representation of the result is 1.0000000050000002"); +assert.sameValue(expected, 1.000001830000000_64659, "the float representation of the result is 1.00000183000000064659"); assert.compareArray( f64Repr(expected), - [0x3f, 0xf0, 0x00, 0x00, 0x01, 0x57, 0x98, 0xef], - "the bit representation of the result is 0x3ff00000015798ef" + [0x3f, 0xf0, 0x00, 0x01, 0xeb, 0x3c, 0xa4, 0x79], + "the bit representation of the result is 0x3ff00001eb3ca479" ); // The next Number in direction -Infinity is less precise. -assert.sameValue(nextDown(expected), 1.000000004999999_96961, "the next Number in direction -Infinity is less precise"); +assert.sameValue(nextDown(expected), 1.000001830000000_42455, "the next Number in direction -Infinity is less precise"); // The next Number in direction +Infinity is less precise. -assert.sameValue(nextUp(expected), 1.000000005000000_4137, "the next Number in direction +Infinity is less precise"); +assert.sameValue(nextUp(expected), 1.000001830000000_86864, "the next Number in direction +Infinity is less precise"); // ============ -let relativeTo = new Temporal.ZonedDateTime(-86400_0000_0000_000_000_000n, createTimeZone(), createCalendar()); -const dYears = new Temporal.Duration(/* years = */ 1, 0, 0, /* days = */ 1, 0, 0, 0, /* milliseconds = */ 199, 0, /* nanoseconds = */ 1); -assert.sameValue(dYears.total({ unit: "years", relativeTo }), expected, "Correct division by large number in years total"); - -relativeTo = new Temporal.ZonedDateTime(-86400_0000_0000_000_000_000n, createTimeZone(), createCalendar()); -const dMonths = new Temporal.Duration(0, /* months = */ 1, 0, /* days = */ 1, 0, 0, 0, /* milliseconds = */ 199, 0, /* nanoseconds = */ 1); -assert.sameValue(dMonths.total({ unit: "months", relativeTo }), expected, "Correct division by large number in months total"); - -// Weeks calculation doesn't have the AddDate calls to convert months/weeks to days -const weeksCal = new Temporal.Calendar("iso8601"); -TemporalHelpers.substituteMethod(weeksCal, "dateAdd", [ - TemporalHelpers.SUBSTITUTE_SKIP, // Duration.total step 19.a MoveRelativeZonedDateTime → AddZonedDateTime - TemporalHelpers.SUBSTITUTE_SKIP, // RoundDuration step 7.a.i MoveRelativeZonedDateTime → AddZonedDateTime - new Temporal.PlainDate(275760, 9, 13), // RoundDuration step 12.q MoveRelativeDate - // sets one{Year,Month,Week}Days to 200_000_000 -]); -relativeTo = new Temporal.ZonedDateTime(-86400_0000_0000_000_000_000n, createTimeZone(), weeksCal); -const dWeeks = new Temporal.Duration(0, 0, /* weejs = */ 1, /* days = */ 1, 0, 0, 0, /* milliseconds = */ 199, 0, /* nanoseconds = */ 1); -assert.sameValue(dWeeks.total({ unit: "weeks", relativeTo }), expected, "Correct division by large number in weeks total"); +const duration = new Temporal.Duration(/* years = */ 1, 0, 0, 0, 0, 0, 0, 9, 254, 648); +assert.sameValue(duration.total({ unit: "years", relativeTo: createRelativeTo() }), expected, "Correct division by large number in years total"); diff --git a/test/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-normalized-time-duration-to-days-range-errors.js b/test/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-normalized-time-duration-to-days-range-errors.js deleted file mode 100644 index 20e696f340..0000000000 --- a/test/built-ins/Temporal/Duration/prototype/total/relativeto-zoneddatetime-normalized-time-duration-to-days-range-errors.js +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (C) 2022 Igalia, S.L. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-temporal.duration.prototype.total -description: > - Abstract operation NormalizedTimeDurationToDays can throw four different - RangeErrors. -info: | - NormalizedTimeDurationToDays ( norm, zonedRelativeTo, timeZoneRec [ , precalculatedPlainDateTime ] ) - 23. If days < 0 and sign = 1, throw a RangeError exception. - 24. If days > 0 and sign = -1, throw a RangeError exception. - ... - 26. If NormalizedTimeDurationSign(_norm_) = 1 and sign = -1, throw a RangeError exception. - ... - 29. If dayLength ≥ 2⁵³, throw a RangeError exception. -features: [Temporal, BigInt] -includes: [temporalHelpers.js] ----*/ - -const oneNsDuration = Temporal.Duration.from({ nanoseconds: 1 }); -const negOneNsDuration = Temporal.Duration.from({ nanoseconds: -1 }); -const dayNs = 86_400_000_000_000; -const epochInstant = new Temporal.Instant(0n); - -function timeZoneSubstituteValues( - getPossibleInstantsFor, - getOffsetNanosecondsFor -) { - const tz = new Temporal.TimeZone("UTC"); - TemporalHelpers.substituteMethod( - tz, - "getPossibleInstantsFor", - getPossibleInstantsFor - ); - TemporalHelpers.substituteMethod( - tz, - "getOffsetNanosecondsFor", - getOffsetNanosecondsFor - ); - return tz; -} - -// Step 23: days < 0 and sign = 1 -let zdt = new Temporal.ZonedDateTime( - 0n, // Sets _startNs_ to 0 - timeZoneSubstituteValues( - [[epochInstant]], // Returned in step 16, setting _relativeResult_ - [ - TemporalHelpers.SUBSTITUTE_SKIP, // Pre-conversion in Duration.p.total - dayNs - 1, // Returned in step 8, setting _startDateTime_ - -dayNs + 1, // Returned in step 9, setting _endDateTime_ - ] - ) -); -assert.throws(RangeError, () => - // Using 1ns duration _nanoseconds_ to 1 and _sign_ to 1 - oneNsDuration.total({ - relativeTo: zdt, - unit: "day", - }), - "RangeError when days < 0 and sign = 1" -); - -// Step 24: days > 0 and sign = -1 -zdt = new Temporal.ZonedDateTime( - 0n, // Sets _startNs_ to 0 - timeZoneSubstituteValues( - [[epochInstant]], // Returned in step 16, setting _relativeResult_ - [ - TemporalHelpers.SUBSTITUTE_SKIP, // Pre-conversion in Duration.p.total - -dayNs + 1, // Returned in step 8, setting _startDateTime_ - dayNs - 1, // Returned in step 9, setting _endDateTime_ - ] - ) -); -assert.throws(RangeError, () => - // Using -1ns duration sets _nanoseconds_ to -1 and _sign_ to -1 - negOneNsDuration.total({ - relativeTo: zdt, - unit: "day", - }), - "RangeError when days > 0 and sign = -1" -); - -// Step 26: nanoseconds > 0 and sign = -1 -zdt = new Temporal.ZonedDateTime( - 0n, // Sets _startNs_ to 0 - timeZoneSubstituteValues( - [ - [new Temporal.Instant(-2n)], // Returned in step 16, setting _relativeResult_ - [new Temporal.Instant(-4n)], // Returned in step 19, setting _oneDayFarther_ - ], - [ - TemporalHelpers.SUBSTITUTE_SKIP, // pre-conversion in Duration.p.total - dayNs - 1, // Returned in step 8, setting _startDateTime_ - -dayNs + 1, // Returned in step 9, setting _endDateTime_ - ] - ) -); -assert.throws(RangeError, () => - // Using -1ns duration sets _nanoseconds_ to -1 and _sign_ to -1 - negOneNsDuration.total({ - relativeTo: zdt, - unit: "day", - }), - "RangeError when nanoseconds > 0 and sign = -1" -); - -// Step 29: day length is an unsafe integer -zdt = new Temporal.ZonedDateTime( - 0n, - timeZoneSubstituteValues( - // Not called in step 16 because _days_ = 0 - // Returned in step 19, making _oneDayFarther_ 2^53 ns later than _relativeResult_ - [[new Temporal.Instant(2n ** 53n)]], - [] - ) -); -assert.throws(RangeError, () => - oneNsDuration.total({ - relativeTo: zdt, - unit: "days", - }), - "Should throw RangeError when time zone calculates an outrageous day length" -); diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/calendar-dateadd-called-with-plaindate-instance.js b/test/built-ins/Temporal/PlainDate/prototype/since/calendar-dateadd-called-with-plaindate-instance.js deleted file mode 100644 index 7b5bcf3ca3..0000000000 --- a/test/built-ins/Temporal/PlainDate/prototype/since/calendar-dateadd-called-with-plaindate-instance.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (C) 2021 Igalia, S.L. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.plaindate.prototype.since -description: > - relativeTo parameters that are not ZonedDateTime or undefined, are always - converted to PlainDate for observable calendar calls -includes: [temporalHelpers.js] -features: [Temporal] ----*/ - -const calendar = TemporalHelpers.calendarDateAddPlainDateInstance(); -const instance = new Temporal.PlainDate(1970, 1, 1, calendar); -calendar.specificPlainDate = instance; -instance.since(new Temporal.PlainDate(2000, 5, 2, calendar), { smallestUnit: "month" }); -assert(calendar.dateAddCallCount > 0, "assertions in calendar.dateAdd() should have been tested"); diff --git a/test/built-ins/Temporal/PlainDate/prototype/since/order-of-operations.js b/test/built-ins/Temporal/PlainDate/prototype/since/order-of-operations.js index 885b9420f0..3dcf5f262a 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/since/order-of-operations.js +++ b/test/built-ins/Temporal/PlainDate/prototype/since/order-of-operations.js @@ -125,22 +125,16 @@ instance.since(identicalPropertyBag, createOptionsObserver()); assert.compareArray(actual, expected, "order of operations with identical dates"); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest year: +// code path through RoundRelativeDuration that rounds to the nearest year: const expectedOpsForYearRounding = expected.concat([ // lookup "get this.calendar.dateAdd", "get this.calendar.dateUntil", // CalendarDateUntil "call this.calendar.dateUntil", - // RoundDuration - "call this.calendar.dateAdd", // 12.d - "call this.calendar.dateAdd", // 12.f - "call this.calendar.dateUntil", // 12.n - "call this.calendar.dateAdd", // 12.x MoveRelativeDate - // (12.r not called because other units can't add up to >1 year at this point) - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 9.c - "call this.calendar.dateUntil" // 9.d + // RoundRelativeDuration + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.since(otherDatePropertyBag, createOptionsObserver({ smallestUnit: "years" })); assert.compareArray(actual, expectedOpsForYearRounding, "order of operations with smallestUnit = years"); @@ -160,14 +154,9 @@ const expectedOpsForYearRoundingSameMonth = expected.concat([ "get this.calendar.dateUntil", // CalendarDateUntil "call this.calendar.dateUntil", - // RoundDuration - "call this.calendar.dateAdd", // 12.d - "call this.calendar.dateAdd", // 12.f - "call this.calendar.dateAdd", // 12.x MoveRelativeDate - // (12.n not called because months and weeks == 0) - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 9.c - "call this.calendar.dateUntil" // 9.d + // RoundRelativeDuration + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.since(otherDatePropertyBagSameMonth, createOptionsObserver({ smallestUnit: "years" })); assert.compareArray(actual, expectedOpsForYearRoundingSameMonth, "order of operations with smallestUnit = years and no excess months/weeks"); @@ -180,13 +169,9 @@ const expectedOpsForMonthRounding = expected.concat([ "get this.calendar.dateUntil", // CalendarDateUntil "call this.calendar.dateUntil", - // RoundDuration - "call this.calendar.dateAdd", // 13.c - "call this.calendar.dateAdd", // 13.e - "call this.calendar.dateAdd", // 13.w MoveRelativeDate - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 10.d - "call this.calendar.dateUntil" // 10.e + // RoundRelativeDuration + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.since(otherDatePropertyBag, createOptionsObserver({ smallestUnit: "months" })); assert.compareArray(actual, expectedOpsForMonthRounding, "order of operations with smallestUnit = months"); @@ -199,12 +184,10 @@ const expectedOpsForWeekRounding = expected.concat([ "get this.calendar.dateUntil", // CalendarDateUntil "call this.calendar.dateUntil", - // RoundDuration - "call this.calendar.dateUntil", // 14.f - "call this.calendar.dateAdd", // 14.p MoveRelativeDate - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 16 - "call this.calendar.dateUntil" // 17 + // RoundRelativeDuration + "call this.calendar.dateUntil", + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.since(otherDatePropertyBag, createOptionsObserver({ smallestUnit: "weeks" })); assert.compareArray(actual, expectedOpsForWeekRounding, "order of operations with smallestUnit = weeks"); diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/calendar-dateadd-called-with-plaindate-instance.js b/test/built-ins/Temporal/PlainDate/prototype/until/calendar-dateadd-called-with-plaindate-instance.js deleted file mode 100644 index e6e56e2b31..0000000000 --- a/test/built-ins/Temporal/PlainDate/prototype/until/calendar-dateadd-called-with-plaindate-instance.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (C) 2021 Igalia, S.L. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.plaindate.prototype.until -description: > - relativeTo parameters that are not ZonedDateTime or undefined, are always - converted to PlainDate for observable calendar calls -includes: [temporalHelpers.js] -features: [Temporal] ----*/ - -const calendar = TemporalHelpers.calendarDateAddPlainDateInstance(); -const instance = new Temporal.PlainDate(1970, 1, 1, calendar); -calendar.specificPlainDate = instance; -instance.until(new Temporal.PlainDate(2000, 5, 2, calendar), { smallestUnit: "month" }); -assert(calendar.dateAddCallCount > 0, "assertions in calendar.dateAdd() should have been tested"); diff --git a/test/built-ins/Temporal/PlainDate/prototype/until/order-of-operations.js b/test/built-ins/Temporal/PlainDate/prototype/until/order-of-operations.js index 3ee157cf6a..0807b344d8 100644 --- a/test/built-ins/Temporal/PlainDate/prototype/until/order-of-operations.js +++ b/test/built-ins/Temporal/PlainDate/prototype/until/order-of-operations.js @@ -133,15 +133,9 @@ const expectedOpsForYearRounding = expected.concat([ "get this.calendar.dateUntil", // CalendarDateUntil "call this.calendar.dateUntil", - // RoundDuration - "call this.calendar.dateAdd", // 12.d - "call this.calendar.dateAdd", // 12.f - "call this.calendar.dateUntil", // 12.n - "call this.calendar.dateAdd", // 12.x MoveRelativeDate - // (12.r not called because other units can't add up to >1 year at this point) - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 9.c - "call this.calendar.dateUntil" // 9.d + // RoundRelativeDuration + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.until(otherDatePropertyBag, createOptionsObserver({ smallestUnit: "years" })); assert.compareArray(actual, expectedOpsForYearRounding, "order of operations with smallestUnit = years"); @@ -161,14 +155,9 @@ const expectedOpsForYearRoundingSameMonth = expected.concat([ "get this.calendar.dateUntil", // CalendarDateUntil "call this.calendar.dateUntil", - // RoundDuration - "call this.calendar.dateAdd", // 12.d - "call this.calendar.dateAdd", // 12.f - "call this.calendar.dateAdd", // 12.x MoveRelativeDate - // (12.n not called because months and weeks == 0) - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 9.c - "call this.calendar.dateUntil" // 9.d + // RoundRelativeDuration + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.until(otherDatePropertyBagSameMonth, createOptionsObserver({ smallestUnit: "years" })); assert.compareArray(actual, expectedOpsForYearRoundingSameMonth, "order of operations with smallestUnit = years and no excess months/weeks"); @@ -181,13 +170,9 @@ const expectedOpsForMonthRounding = expected.concat([ "get this.calendar.dateUntil", // CalendarDateUntil "call this.calendar.dateUntil", - // RoundDuration - "call this.calendar.dateAdd", // 13.c - "call this.calendar.dateAdd", // 13.e - "call this.calendar.dateAdd", // 13.w MoveRelativeDate - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 10.d - "call this.calendar.dateUntil" // 10.e + // RoundRelativeDuration + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.until(otherDatePropertyBag, createOptionsObserver({ smallestUnit: "months" })); assert.compareArray(actual, expectedOpsForMonthRounding, "order of operations with smallestUnit = months"); @@ -200,12 +185,10 @@ const expectedOpsForWeekRounding = expected.concat([ "get this.calendar.dateUntil", // CalendarDateUntil "call this.calendar.dateUntil", - // RoundDuration - "call this.calendar.dateUntil", // 14.f - "call this.calendar.dateAdd", // 14.p MoveRelativeDate - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 16 - "call this.calendar.dateUntil" // 17 + // RoundRelativeDuration + "call this.calendar.dateUntil", + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.until(otherDatePropertyBag, createOptionsObserver({ smallestUnit: "weeks" })); assert.compareArray(actual, expectedOpsForWeekRounding, "order of operations with smallestUnit = weeks"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/since/order-of-operations.js b/test/built-ins/Temporal/PlainDateTime/prototype/since/order-of-operations.js index ec024268f8..df0236e7cc 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/since/order-of-operations.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/since/order-of-operations.js @@ -162,15 +162,9 @@ const expectedOpsForYearRounding = expected.concat([ "get this.calendar.dateUntil", // CalendarDateUntil "call this.calendar.dateUntil", - // RoundDuration - "call this.calendar.dateAdd", // 12.d - "call this.calendar.dateAdd", // 12.f - "call this.calendar.dateUntil", // 12.n - "call this.calendar.dateAdd", // 12.x MoveRelativeDate - // (12.r not called because other units can't add up to >1 year at this point) - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 9.c - "call this.calendar.dateUntil" // 9.d + // RoundRelativeDuration + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.since(otherDateTimePropertyBag, createOptionsObserver({ smallestUnit: "years" })); assert.compareArray(actual, expectedOpsForYearRounding, "order of operations with smallestUnit = years"); @@ -196,14 +190,9 @@ const expectedOpsForYearRoundingSameMonth = expected.concat([ "get this.calendar.dateUntil", // CalendarDateUntil "call this.calendar.dateUntil", - // RoundDuration - "call this.calendar.dateAdd", // 12.d - "call this.calendar.dateAdd", // 12.f - "call this.calendar.dateAdd", // 12.x MoveRelativeDate - // (12.n not called because months and weeks == 0) - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 9.c - "call this.calendar.dateUntil" // 9.d + // RoundRelativeDuration + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.until(otherDatePropertyBagSameMonth, createOptionsObserver({ smallestUnit: "years" })); assert.compareArray(actual, expectedOpsForYearRoundingSameMonth, "order of operations with smallestUnit = years and no excess months/weeks"); @@ -216,14 +205,9 @@ const expectedOpsForMonthRounding = expected.concat([ "get this.calendar.dateUntil", // CalendarDateUntil "call this.calendar.dateUntil", - // RoundDuration - "call this.calendar.dateAdd", // 13.c - "call this.calendar.dateAdd", // 13.e - "call this.calendar.dateUntil", // 13.m - "call this.calendar.dateAdd", // 13.w MoveRelativeDate - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 10.d - "call this.calendar.dateUntil", // 10.e + // RoundRelativeDuration + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.since(otherDateTimePropertyBag, createOptionsObserver({ smallestUnit: "months" })); assert.compareArray(actual, expectedOpsForMonthRounding, "order of operations with smallestUnit = months"); @@ -236,12 +220,10 @@ const expectedOpsForWeekRounding = expected.concat([ "get this.calendar.dateUntil", // CalendarDateUntil "call this.calendar.dateUntil", - // RoundDuration - "call this.calendar.dateUntil", // 14.f - "call this.calendar.dateAdd", // 14.p MoveRelativeDate - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 16 - "call this.calendar.dateUntil", // 17 + // RoundRelativeDuration + "call this.calendar.dateUntil", + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.since(otherDateTimePropertyBag, createOptionsObserver({ smallestUnit: "weeks" })); assert.compareArray(actual, expectedOpsForWeekRounding, "order of operations with smallestUnit = weeks"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/since/result-mixed-sign.js b/test/built-ins/Temporal/PlainDateTime/prototype/since/result-mixed-sign.js index f3ad9710e6..40961725d7 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/since/result-mixed-sign.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/since/result-mixed-sign.js @@ -12,8 +12,8 @@ features: [Temporal] // Test case provided by André Bargull const cal = new (class extends Temporal.Calendar { - dateAdd(date, duration, options) { - return super.dateAdd(date, duration.negated(), options); + dateUntil(date, duration, options) { + return super.dateUntil(date, duration, options).negated(); } })("iso8601"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/order-of-operations.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/order-of-operations.js index 10eb6ca7e6..d75480f4cd 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/until/order-of-operations.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/order-of-operations.js @@ -162,15 +162,9 @@ const expectedOpsForYearRounding = expected.concat([ "get this.calendar.dateUntil", // CalendarDateUntil "call this.calendar.dateUntil", - // RoundDuration - "call this.calendar.dateAdd", // 12.d - "call this.calendar.dateAdd", // 12.f - "call this.calendar.dateUntil", // 12.n - "call this.calendar.dateAdd", // 12.x MoveRelativeDate - // (12.r not called because other units can't add up to >1 year at this point) - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 9.c - "call this.calendar.dateUntil" // 9.d + // RoundRelativeDuration + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.until(otherDateTimePropertyBag, createOptionsObserver({ smallestUnit: "years" })); assert.compareArray(actual, expectedOpsForYearRounding, "order of operations with smallestUnit = years"); @@ -196,14 +190,9 @@ const expectedOpsForYearRoundingSameMonth = expected.concat([ "get this.calendar.dateUntil", // CalendarDateUntil "call this.calendar.dateUntil", - // RoundDuration - "call this.calendar.dateAdd", // 12.d - "call this.calendar.dateAdd", // 12.f - "call this.calendar.dateAdd", // 12.x MoveRelativeDate - // (12.n not called because months and weeks == 0) - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 9.c - "call this.calendar.dateUntil" // 9.d + // RoundRelativeDuration + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.until(otherDatePropertyBagSameMonth, createOptionsObserver({ smallestUnit: "years" })); assert.compareArray(actual, expectedOpsForYearRoundingSameMonth, "order of operations with smallestUnit = years and no excess months/weeks"); @@ -216,14 +205,9 @@ const expectedOpsForMonthRounding = expected.concat([ "get this.calendar.dateUntil", // CalendarDateUntil "call this.calendar.dateUntil", - // RoundDuration - "call this.calendar.dateAdd", // 13.c - "call this.calendar.dateAdd", // 13.e - "call this.calendar.dateUntil", // 13.m - "call this.calendar.dateAdd", // 13.w MoveRelativeDate - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 10.d - "call this.calendar.dateUntil" // 10.e + // RoundRelativeDuration + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.until(otherDateTimePropertyBag, createOptionsObserver({ smallestUnit: "months" })); assert.compareArray(actual, expectedOpsForMonthRounding, "order of operations with smallestUnit = years"); @@ -236,12 +220,10 @@ const expectedOpsForWeekRounding = expected.concat([ "get this.calendar.dateUntil", // CalendarDateUntil "call this.calendar.dateUntil", - // RoundDuration - "call this.calendar.dateUntil", // 14.f - "call this.calendar.dateAdd", // 14.p MoveRelativeDate - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 16 - "call this.calendar.dateUntil" // 17 + // RoundRelativeDuration + "call this.calendar.dateUntil", + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.until(otherDateTimePropertyBag, createOptionsObserver({ smallestUnit: "weeks" })); assert.compareArray(actual, expectedOpsForWeekRounding, "order of operations with smallestUnit = weeks"); diff --git a/test/built-ins/Temporal/PlainDateTime/prototype/until/result-mixed-sign.js b/test/built-ins/Temporal/PlainDateTime/prototype/until/result-mixed-sign.js index a0a00d0723..1df299a3c2 100644 --- a/test/built-ins/Temporal/PlainDateTime/prototype/until/result-mixed-sign.js +++ b/test/built-ins/Temporal/PlainDateTime/prototype/until/result-mixed-sign.js @@ -12,8 +12,8 @@ features: [Temporal] // Test case provided by André Bargull const cal = new (class extends Temporal.Calendar { - dateAdd(date, duration, options) { - return super.dateAdd(date, duration.negated(), options); + dateUntil(date, duration, options) { + return super.dateUntil(date, duration, options).negated(); } })("iso8601"); diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/since/order-of-operations.js b/test/built-ins/Temporal/PlainYearMonth/prototype/since/order-of-operations.js index 7fe8b2b133..1ffc7cc9ae 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/since/order-of-operations.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/since/order-of-operations.js @@ -138,23 +138,16 @@ instance.since(identicalPropertyBag, createOptionsObserver()); assert.compareArray(actual, expectedMinimal, "order of operations with identical year-months"); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest year: +// code path through RoundRelativeDuration that rounds to the nearest year: const expectedOpsForYearRounding = expected.concat([ - // RoundDuration - "call this.calendar.dateAdd", // 7.e - "call this.calendar.dateAdd", // 7.g - "call this.calendar.dateUntil", // 7.o - "call this.calendar.dateAdd", // 7.y MoveRelativeDate - // (7.s not called because other units can't add up to >1 year at this point) - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 9.c - "call this.calendar.dateUntil" // 9.d + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.since(otherYearMonthPropertyBag, createOptionsObserver({ smallestUnit: "years" })); assert.compareArray(actual, expectedOpsForYearRounding, "order of operations with smallestUnit = years"); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest year and skips a DateUntil call +// code path through RoundRelativeDuration that rounds to the nearest year and skips a DateUntil call const otherYearMonthPropertyBagSameMonth = TemporalHelpers.propertyBagObserver(actual, { year: 2001, month: 5, @@ -162,28 +155,18 @@ const otherYearMonthPropertyBagSameMonth = TemporalHelpers.propertyBagObserver(a calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), }, "other"); const expectedOpsForYearRoundingSameMonth = expected.concat([ - "call this.calendar.dateAdd", // 7.e - "call this.calendar.dateAdd", // 7.g - "call this.calendar.dateAdd", // 7.y MoveRelativeDate - // (7.o not called because months and weeks == 0) - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 9.c - "call this.calendar.dateUntil" // 9.d + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.since(otherYearMonthPropertyBagSameMonth, createOptionsObserver({ smallestUnit: "years" })); assert.compareArray(actual, expectedOpsForYearRoundingSameMonth, "order of operations with smallestUnit = years and no excess months"); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest month: +// code path through RoundRelativeDuration that rounds to the nearest month: const expectedOpsForMonthRounding = expected.concat([ - // RoundDuration - "call this.calendar.dateAdd", // 10.c - "call this.calendar.dateAdd", // 10.e - "call this.calendar.dateAdd", // 10.k MoveRelativeDate - // (10.n.iii MoveRelativeDate not called because weeks == 0) - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 10.d - "call this.calendar.dateUntil" // 10.e + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", // BubbleRelativeDuration ]); instance.since(otherYearMonthPropertyBag, createOptionsObserver({ smallestUnit: "months", roundingIncrement: 2 })); assert.compareArray(actual, expectedOpsForMonthRounding, "order of operations with smallestUnit = months"); diff --git a/test/built-ins/Temporal/PlainYearMonth/prototype/until/order-of-operations.js b/test/built-ins/Temporal/PlainYearMonth/prototype/until/order-of-operations.js index 693a381a2b..a3d8084584 100644 --- a/test/built-ins/Temporal/PlainYearMonth/prototype/until/order-of-operations.js +++ b/test/built-ins/Temporal/PlainYearMonth/prototype/until/order-of-operations.js @@ -138,23 +138,16 @@ instance.until(identicalPropertyBag, createOptionsObserver()); assert.compareArray(actual, expectedMinimal, "order of operations with identical year-months"); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest year: +// code path through RoundRelativeDuration that rounds to the nearest year: const expectedOpsForYearRounding = expected.concat([ - // RoundDuration - "call this.calendar.dateAdd", // 7.e - "call this.calendar.dateAdd", // 7.g - "call this.calendar.dateUntil", // 7.o - "call this.calendar.dateAdd", // 7.y MoveRelativeDate - // (7.s not called because other units can't add up to >1 year at this point) - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 9.c - "call this.calendar.dateUntil" // 9.d + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.until(otherYearMonthPropertyBag, createOptionsObserver({ smallestUnit: "years" })); assert.compareArray(actual, expectedOpsForYearRounding, "order of operations with smallestUnit = years"); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest year and skips a DateUntil call +// code path through RoundRelativeDuration that rounds to the nearest year and skips a DateUntil call const otherYearMonthPropertyBagSameMonth = TemporalHelpers.propertyBagObserver(actual, { year: 2001, month: 5, @@ -162,28 +155,18 @@ const otherYearMonthPropertyBagSameMonth = TemporalHelpers.propertyBagObserver(a calendar: TemporalHelpers.calendarObserver(actual, "other.calendar"), }, "other"); const expectedOpsForYearRoundingSameMonth = expected.concat([ - "call this.calendar.dateAdd", // 7.e - "call this.calendar.dateAdd", // 7.g - "call this.calendar.dateAdd", // 7.y MoveRelativeDate - // (7.o not called because months and weeks == 0) - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 9.c - "call this.calendar.dateUntil" // 9.d + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", ]); instance.until(otherYearMonthPropertyBagSameMonth, createOptionsObserver({ smallestUnit: "years" })); assert.compareArray(actual, expectedOpsForYearRoundingSameMonth, "order of operations with smallestUnit = years and no excess months"); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest month: +// code path through RoundRelativeDuration that rounds to the nearest month: const expectedOpsForMonthRounding = expected.concat([ - // RoundDuration - "call this.calendar.dateAdd", // 10.c - "call this.calendar.dateAdd", // 10.e - "call this.calendar.dateAdd", // 10.k MoveRelativeDate - // (10.n.iii MoveRelativeDate not called because weeks == 0) - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 10.d - "call this.calendar.dateUntil" // 10.e + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", // BubbleRelativeDuration ]); instance.until(otherYearMonthPropertyBag, createOptionsObserver({ smallestUnit: "months", roundingIncrement: 2 })); assert.compareArray(actual, expectedOpsForMonthRounding, "order of operations with smallestUnit = months"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateadd-called-with-options-undefined.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateadd-called-with-options-undefined.js index 5f5aba3bab..0ad19e91ea 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateadd-called-with-options-undefined.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateadd-called-with-options-undefined.js @@ -17,11 +17,8 @@ const later = new Temporal.ZonedDateTime(1_213_200_000_000_000n, timeZone, calen // Difference with rounding, with smallestUnit a calendar unit. // The calls come from these paths: -// ZonedDateTime.since() -> -// RoundDuration -> -// MoveRelativeZonedDateTime -> AddZonedDateTime -> calendar.dateAdd() -// MoveRelativeDate -> calendar.dateAdd() -// BalanceDurationRelative -> MoveRelativeDate -> calendar.dateAdd() +// ZonedDateTime.since() -> DifferenceZonedDateTimeWithRounding -> RoundRelativeDuration -> NudgeToCalendarUnit -> +// AddDateTime -> calendar.dateAdd() later.since(earlier, { smallestUnit: "weeks" }); -assert.sameValue(calendar.dateAddCallCount, 3, "rounding difference with calendar smallestUnit"); +assert.sameValue(calendar.dateAddCallCount, 2, "rounding difference with calendar smallestUnit"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js index d446bdcdf9..812b1f2b67 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/since/calendar-dateuntil-called-with-singular-largestunit.js @@ -3,47 +3,9 @@ /*--- esid: sec-temporal.zoneddatetime.prototype.since -description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form -info: | - sec-temporal.zoneddatetime.prototype.since steps 14–18: - 14. If _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then - ... - c. Return ... - 15. ... - 16. Let _difference_ be ? DifferenceZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _other_.[[Nanoseconds]], _zonedDateTime_.[[TimeZone]], _zonedDateTime_.[[Calendar]], _largestUnit_). - 17. Let _roundResult_ be ? RoundDuration(_difference_.[[Years]], _difference_.[[Months]], _difference_.[[Weeks]], _difference_.[[Days]], _difference_.[[Hours]], _difference_.[[Minutes]], _difference_.[[Seconds]], _difference_.[[Milliseconds]], _difference_.[[Microseconds]], _difference_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _zonedDateTime_). - 18. Let _result_ be ? AdjustRoundedDurationDays(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _roundResult_.[[Days]], _roundResult_.[[Hours]], _roundResult_.[[Minutes]], _roundResult_.[[Seconds]], _roundResult_.[[Milliseconds]], _roundResult_.[[Microseconds]], _roundResult_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _zonedDateTime_). - sec-temporal-differencezoneddatetime steps 7 and 11: - 7. 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]], _calendar_, _largestUnit_, _options_). - 11. Let _result_ be ? NanosecondsToDays(_timeRemainderNs_, _intermediate_). - sec-temporal-roundduration steps 5.d and 8.n–p: - 5. If _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then - ... - d. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _intermediate_). - ... - 8. If _unit_ is *"year"*, then - ... - n. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*). - o. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"year"*). - p. Let _timePassed_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _daysLater_, _untilOptions_) - sec-temporal-adjustroundeddurationdays steps 1 and 9: - 1. If _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot; or _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*; or _unit_ is *"nanosecond"* and _increment_ is 1, then - a. Return ... - ... - 9. 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_). - sec-temporal-addduration step 7.a–g: - a. Assert: _relativeTo_ has an [[IntializedTemporalZonedDateTime]] internal slot. - ... - f. If _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then - ... - g. Else, - i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_). - sec-temporal-nanosecondstodays step 11: - 11. 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"*). - sec-temporal-differenceisodatetime steps 9–11: - 9. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_). - 10. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _dateLargestUnit_). - 11. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_). +description: > + The options object passed to calendar.dateUntil has a largestUnit property + with its value in the singular form includes: [compareArray.js, temporalHelpers.js] features: [Temporal] ---*/ @@ -77,9 +39,9 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( later.since(earlier, { largestUnit, roundingIncrement: 2, roundingMode: 'ceil' }); }, { - years: ["year", "year", "year"], - months: ["month", "month", "month"], - weeks: ["week", "week", "week"], + years: ["year"], + months: ["month"], + weeks: ["week"], days: [], hours: [], minutes: [], @@ -100,9 +62,9 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( later.since(earlier, { smallestUnit }); }, { - years: ["year", "year", "year"], - months: ["month", "month", "month"], - weeks: ["week", "week", "week"], + years: ["year"], + months: ["month"], + weeks: ["week", "week"], days: [], hours: [], minutes: [], diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/date-and-time-durations-opposite-signs.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/date-and-time-durations-opposite-signs.js index 5924c804ad..5db16682f1 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/since/date-and-time-durations-opposite-signs.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/since/date-and-time-durations-opposite-signs.js @@ -23,14 +23,8 @@ features: [Temporal] // Based on a test case by André Bargull const calendar = new class extends Temporal.Calendar { - #dateUntil = 0; - dateUntil(one, two, options) { - let result = super.dateUntil(one, two, options); - if (++this.#dateUntil === 2) { - result = result.negated(); - } - return result; + return super.dateUntil(one, two, options).negated(); } }("iso8601"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/normalized-time-duration-to-days-loop-arbitrarily.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/normalized-time-duration-to-days-loop-arbitrarily.js deleted file mode 100644 index e8ecae39bc..0000000000 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/since/normalized-time-duration-to-days-loop-arbitrarily.js +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2022 Igalia, S.L. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.zoneddatetime.prototype.since -description: > - NormalizedTimeDurationToDays should not be able to loop arbitrarily. -info: | - NormalizedTimeDurationToDays ( norm, zonedRelativeTo, timeZoneRec [ , precalculatedPlainDatetime ] ) - ... - 22. If NormalizedTimeDurationSign(_oneDayLess_) × _sign_ ≥ 0, then - a. Set _norm_ to _oneDayLess_. - b. Set _relativeResult_ to _oneDayFarther_. - c. Set _days_ to _days_ + _sign_. - d. Set _oneDayFarther_ to ? AddDaysToZonedDateTime(_relativeResult_.[[Instant]], _relativeResult_.[[DateTime]], _timeZoneRec_, _zonedRelativeTo_.[[Calendar]], _sign_). - e. Set dayLengthNs to NormalizedTimeDurationFromEpochNanosecondsDifference(_oneDayFarther.[[EpochNanoseconds]], relativeResult.[[EpochNanoseconds]]). - f. If NormalizedTimeDurationSign(? SubtractNormalizedTimeDuration(_norm_, _dayLengthNs_)) × _sign_ ≥ 0, then - i. Throw a *RangeError* exception. -features: [Temporal] ----*/ - -const dayLengthNs = 86400000000000n; -const dayInstant = new Temporal.Instant(dayLengthNs); -let calls = 0; -const timeZone = new class extends Temporal.TimeZone { - getPossibleInstantsFor() { - calls++; - return [dayInstant]; - } -}("UTC"); - -const zdt = new Temporal.ZonedDateTime(0n, timeZone); -const other = new Temporal.ZonedDateTime(dayLengthNs * 2n, "UTC", "iso8601"); - -assert.throws(RangeError, () => zdt.since(other, { largestUnit: "day", smallestUnit: "second" }), "indefinite loop is prevented"); -assert.sameValue(calls, 4, "getPossibleInstantsFor is not called indefinitely"); - // Expected calls: - // DifferenceTemporalZonedDateTime -> - // DifferenceZonedDateTime -> GetInstantFor (1) - // NormalizedTimeDurationToDays -> - // AddDaysToZonedDateTime (2, step 12) - // AddDaysToZonedDateTime (3, step 15) - // AddDaysToZonedDateTime (4, step 18.d) diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/normalized-time-duration-to-days-range-errors.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/normalized-time-duration-to-days-range-errors.js deleted file mode 100644 index b579a2e2d6..0000000000 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/since/normalized-time-duration-to-days-range-errors.js +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (C) 2022 Igalia, S.L. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-temporal.zoneddatetime.prototype.since -description: > - Abstract operation NormalizedTimeDurationToDays can throw four different - RangeErrors. -info: | - NormalizedTimeDurationToDays ( norm, zonedRelativeTo, timeZoneRec [ , precalculatedPlainDateTime ] ) - 23. If days < 0 and sign = 1, throw a RangeError exception. - 24. If days > 0 and sign = -1, throw a RangeError exception. - ... - 26. If NormalizedTimeDurationSign(_norm_) = 1 and sign = -1, throw a RangeError exception. - ... - 29. If dayLength ≥ 2⁵³, throw a RangeError exception. -features: [Temporal, BigInt] -includes: [temporalHelpers.js] ----*/ - -function timeZoneSubstituteValues( - getPossibleInstantsFor, - getOffsetNanosecondsFor -) { - const tz = new Temporal.TimeZone("UTC"); - TemporalHelpers.substituteMethod( - tz, - "getPossibleInstantsFor", - getPossibleInstantsFor - ); - TemporalHelpers.substituteMethod( - tz, - "getOffsetNanosecondsFor", - getOffsetNanosecondsFor - ); - return tz; -} - -const dayNs = 86_400_000_000_000; -const zeroZDT = new Temporal.ZonedDateTime(0n, "UTC"); -const oneZDT = new Temporal.ZonedDateTime(1n, "UTC"); -const epochInstant = new Temporal.Instant(0n); -const options = { largestUnit: "days", smallestUnit: "seconds", roundingMode: "expand" }; - -// Step 23: days < 0 and sign = 1 -let start = new Temporal.ZonedDateTime( - 0n, // Sets DifferenceZonedDateTime _ns1_ - timeZoneSubstituteValues( - [ - TemporalHelpers.SUBSTITUTE_SKIP, // Behave normally in DifferenceZonedDateTime - [epochInstant], // Returned in step 16, setting _relativeResult_ - ], - [ - // Behave normally in 2 calls made prior to NormalizedTimeDurationToDays - TemporalHelpers.SUBSTITUTE_SKIP, - TemporalHelpers.SUBSTITUTE_SKIP, - dayNs - 1, // Returned in step 8, setting _startDateTime_ - -dayNs + 1, // Returned in step 9, setting _endDateTime_ - ] - ) -); -assert.throws(RangeError, () => - start.since( - oneZDT, // Sets DifferenceZonedDateTime _ns2_ - options - ), - "days < 0 and sign = 1" -); - -// Step 24: days > 0 and sign = -1 -start = new Temporal.ZonedDateTime( - 1n, // Sets DifferenceZonedDateTime _ns1_ - timeZoneSubstituteValues( - [ - TemporalHelpers.SUBSTITUTE_SKIP, // Behave normally in DifferenceZonedDateTime - [epochInstant], // Returned in step 16, setting _relativeResult_ - ], - [ - // Behave normally in 2 calls made prior to NormalizedTimeDurationToDays - TemporalHelpers.SUBSTITUTE_SKIP, - TemporalHelpers.SUBSTITUTE_SKIP, - -dayNs + 1, // Returned in step 8, setting _startDateTime_ - dayNs - 1, // Returned in step 9, setting _endDateTime_ - ] - ) -); -assert.throws(RangeError, () => - start.since( - zeroZDT, // Sets DifferenceZonedDateTime _ns2_ - options - ), - "days > 0 and sign = -1" -); - -// Step 26: nanoseconds > 0 and sign = -1 -start = new Temporal.ZonedDateTime( - 1n, // Sets DifferenceZonedDateTime _ns1_ - timeZoneSubstituteValues( - [ - TemporalHelpers.SUBSTITUTE_SKIP, // Behave normally in DifferenceZonedDateTime - [new Temporal.Instant(-2_000_000_000n)], // Returned in step 16, setting _relativeResult_ - ], - [ - // Behave normally in 2 calls made prior to NormalizedTimeDurationToDays - TemporalHelpers.SUBSTITUTE_SKIP, - TemporalHelpers.SUBSTITUTE_SKIP, - dayNs - 1, // Returned in step 8, setting _startDateTime_ - -dayNs + 1, // Returned in step 9, setting _endDateTime_ - ] - ) -); -assert.throws(RangeError, () => - start.since( - zeroZDT, // Sets DifferenceZonedDateTime _ns2_ - options - ), - "norm > 0 and sign = -1" -); - -// Step 29: day length is an unsafe integer -start = new Temporal.ZonedDateTime( - 0n, - timeZoneSubstituteValues( - [ - TemporalHelpers.SUBSTITUTE_SKIP, // Behave normally in DifferenceZonedDateTime - // Not called in step 16 because _days_ = 0 - // Returned in step 19, making _oneDayFarther_ 2^53 ns later than _relativeResult_ - [new Temporal.Instant(2n ** 53n)], - ], - [] - ) -); -assert.throws(RangeError, () => - start.since( - oneZDT, - options - ), - "Should throw RangeError when time zone calculates an outrageous day length" -); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/order-of-operations.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/order-of-operations.js index 6449ae7195..e9552231bc 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/since/order-of-operations.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/since/order-of-operations.js @@ -327,64 +327,39 @@ const expectedOpsForCalendarDifference = [ "call this.calendar.dateUntil", ]; -const expectedOpsForCalendarRounding = [ - // RoundDuration → MoveRelativeZonedDateTime → AddZonedDateTime +const expectedOpsForCalendarRounding = expected.concat(expectedOpsForCalendarDifference, [ + // RoundRelativeDuration + "call this.calendar.dateAdd", "call this.calendar.dateAdd", "call this.timeZone.getPossibleInstantsFor", - // RoundDuration → NanosecondsToDays - "call this.timeZone.getOffsetNanosecondsFor", - "call this.timeZone.getOffsetNanosecondsFor", - // RoundDuration → NanosecondsToDays → AddDaysToZonedDateTime "call this.timeZone.getPossibleInstantsFor", -]; +]); -// code path that skips RoundDuration: +// code path that skips RoundRelativeDuration: instance.since(otherDateTimePropertyBag, createOptionsObserver({ largestUnit: "years", smallestUnit: "nanoseconds", roundingIncrement: 1 })); assert.compareArray(actual, expected.concat(expectedOpsForCalendarDifference), "order of operations with largestUnit years and no rounding"); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest year: -const expectedOpsForYearRounding = expected.concat(expectedOpsForCalendarDifference, expectedOpsForCalendarRounding, [ - // RoundDuration - "call this.calendar.dateAdd", // 12.d - "call this.calendar.dateAdd", // 12.f - "call this.calendar.dateUntil", // 12.n - "call this.calendar.dateAdd", // 12.x MoveRelativeDate - // (12.r not called because other units can't add up to >1 year at this point) - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 9.c - "call this.calendar.dateUntil" // 9.d -]); +// code path through RoundRelativeDuration that rounds to the nearest year: instance.since(otherDateTimePropertyBag, createOptionsObserver({ smallestUnit: "years" })); -assert.compareArray(actual, expectedOpsForYearRounding, "order of operations with smallestUnit = years"); +assert.compareArray(actual, expectedOpsForCalendarRounding, "order of operations with smallestUnit = years"); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest month: -const expectedOpsForMonthRounding = expected.concat(expectedOpsForCalendarDifference, expectedOpsForCalendarRounding, [ - // RoundDuration - "call this.calendar.dateAdd", // 13.c - "call this.calendar.dateAdd", // 13.e - "call this.calendar.dateUntil", // 13.m - "call this.calendar.dateAdd", // 13.w MoveRelativeDate - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 10.d - "call this.calendar.dateUntil", // 10.e -]); +// code path through RoundRelativeDuration that rounds to the nearest month: instance.since(otherDateTimePropertyBag, createOptionsObserver({ smallestUnit: "months" })); -assert.compareArray(actual, expectedOpsForMonthRounding, "order of operations with smallestUnit = months"); +assert.compareArray(actual, expectedOpsForCalendarRounding, "order of operations with smallestUnit = months"); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest week: -const expectedOpsForWeekRounding = expected.concat(expectedOpsForCalendarDifference, expectedOpsForCalendarRounding, [ - // RoundDuration - "call this.calendar.dateUntil", // 14.f - "call this.calendar.dateAdd", // 14.p MoveRelativeDate - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 16 - "call this.calendar.dateUntil", // 17 -]); +// code path through RoundRelativeDuration that rounds to the nearest week: instance.since(otherDateTimePropertyBag, createOptionsObserver({ smallestUnit: "weeks" })); -assert.compareArray(actual, expectedOpsForWeekRounding, "order of operations with smallestUnit = weeks"); +assert.compareArray(actual, expected.concat(expectedOpsForCalendarDifference, [ + // RoundRelativeDuration + "call this.calendar.dateUntil", + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", + "call this.timeZone.getPossibleInstantsFor", + "call this.timeZone.getPossibleInstantsFor", +]), "order of operations with smallestUnit = weeks"); actual.splice(0); // clear instance.since(otherDateTimePropertyBag, createOptionsObserver({ largestUnit: "hours" })); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-non-integer.js b/test/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-non-integer.js index 5c31c391ae..6c2205b3a9 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-non-integer.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/since/roundingincrement-non-integer.js @@ -20,5 +20,3 @@ const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); const later = new Temporal.ZonedDateTime(1_000_000_000_000_000_005n, "UTC"); const result = later.since(earlier, { roundingIncrement: 2.5, roundingMode: "trunc" }); TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, "roundingIncrement 2.5 truncates to 2"); -const result2 = later.since(earlier, { smallestUnit: "days", roundingIncrement: 1e9 + 0.5, roundingMode: "expand" }); -TemporalHelpers.assertDuration(result2, 0, 0, 0, 1e9, 0, 0, 0, 0, 0, 0, "roundingIncrement 1e9 + 0.5 truncates to 1e9"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateadd-called-with-options-undefined.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateadd-called-with-options-undefined.js index 145a22b4d1..0d6d51dea3 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateadd-called-with-options-undefined.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateadd-called-with-options-undefined.js @@ -17,11 +17,8 @@ const later = new Temporal.ZonedDateTime(1_213_200_000_000_000n, timeZone, calen // Difference with rounding, with smallestUnit a calendar unit. // The calls come from these paths: -// ZonedDateTime.until() -> -// RoundDuration -> -// MoveRelativeZonedDateTime -> AddZonedDateTime -> calendar.dateAdd() -// MoveRelativeDate -> calendar.dateAdd() -// BalanceDurationRelative -> MoveRelativeDate -> calendar.dateAdd() +// ZonedDateTime.until() -> DifferenceZonedDateTimeWithRounding -> RoundRelativeDuration -> NudgeToCalendarUnit -> +// AddDateTime -> calendar.dateAdd() (2x) earlier.until(later, { smallestUnit: "weeks" }); -assert.sameValue(calendar.dateAddCallCount, 3, "rounding difference with calendar smallestUnit"); +assert.sameValue(calendar.dateAddCallCount, 2, "rounding difference with calendar smallestUnit"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js index 56a709cb59..5d47242037 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/until/calendar-dateuntil-called-with-singular-largestunit.js @@ -3,47 +3,9 @@ /*--- esid: sec-temporal.zoneddatetime.prototype.until -description: The options object passed to calendar.dateUntil has a largestUnit property with its value in the singular form -info: | - sec-temporal.zoneddatetime.prototype.until steps 13–17: - 13. If _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then - ... - c. Return ... - 14. ... - 15. Let _difference_ be ? DifferenceZonedDateTime(_zonedDateTime_.[[Nanoseconds]], _other_.[[Nanoseconds]], _zonedDateTime_.[[TimeZone]], _zonedDateTime_.[[Calendar]], _largestUnit_). - 16. Let _roundResult_ be ? RoundDuration(_difference_.[[Years]], _difference_.[[Months]], _difference_.[[Weeks]], _difference_.[[Days]], _difference_.[[Hours]], _difference_.[[Minutes]], _difference_.[[Seconds]], _difference_.[[Milliseconds]], _difference_.[[Microseconds]], _difference_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _zonedDateTime_). - 17. Let _result_ be ? AdjustRoundedDurationDays(_roundResult_.[[Years]], _roundResult_.[[Months]], _roundResult_.[[Weeks]], _roundResult_.[[Days]], _roundResult_.[[Hours]], _roundResult_.[[Minutes]], _roundResult_.[[Seconds]], _roundResult_.[[Milliseconds]], _roundResult_.[[Microseconds]], _roundResult_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_, _zonedDateTime_). - sec-temporal-differencezoneddatetime steps 7 and 11: - 7. 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]], _calendar_, _largestUnit_, _options_). - 11. Let _result_ be ? NanosecondsToDays(_timeRemainderNs_, _intermediate_). - sec-temporal-roundduration steps 5.d and 8.n–p: - 5. If _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*, then - ... - d. Let _result_ be ? NanosecondsToDays(_nanoseconds_, _intermediate_). - ... - 8. If _unit_ is *"year"*, then - ... - n. Let _untilOptions_ be ! OrdinaryObjectCreate(*null*). - o. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"year"*). - p. Let _timePassed_ be ? CalendarDateUntil(_calendar_, _relativeTo_, _daysLater_, _untilOptions_) - sec-temporal-adjustroundeddurationdays steps 1 and 9: - 1. If _relativeTo_ does not have an [[InitializedTemporalZonedDateTime]] internal slot; or _unit_ is one of *"year"*, *"month"*, *"week"*, or *"day"*; or _unit_ is *"nanosecond"* and _increment_ is 1, then - a. Return ... - ... - 9. 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_). - sec-temporal-addduration step 7.a–g: - a. Assert: _relativeTo_ has an [[IntializedTemporalZonedDateTime]] internal slot. - ... - f. If _largestUnit_ is not one of *"year"*, *"month"*, *"week"*, or *"day"*, then - ... - g. Else, - i. Let _result_ be ? DifferenceZonedDateTime(_relativeTo_.[[Nanoseconds]], _endNs_, _timeZone_, _calendar_, _largestUnit_). - sec-temporal-nanosecondstodays step 11: - 11. 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"*). - sec-temporal-differenceisodatetime steps 9–11: - 9. Let _dateLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _largestUnit_). - 10. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _dateLargestUnit_). - 11. Let _dateDifference_ be ? CalendarDateUntil(_calendar_, _date1_, _date2_, _untilOptions_). +description: > + The options object passed to calendar.dateUntil has a largestUnit property + with its value in the singular form includes: [compareArray.js, temporalHelpers.js] features: [Temporal] ---*/ @@ -77,9 +39,9 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( earlier.until(later, { largestUnit, roundingIncrement: 2, roundingMode: 'ceil' }); }, { - years: ["year", "year", "year"], - months: ["month", "month", "month"], - weeks: ["week", "week", "week"], + years: ["year"], + months: ["month"], + weeks: ["week"], days: [], hours: [], minutes: [], @@ -100,9 +62,9 @@ TemporalHelpers.checkCalendarDateUntilLargestUnitSingular( earlier.until(later, { smallestUnit }); }, { - years: ["year", "year", "year"], - months: ["month", "month", "month"], - weeks: ["week", "week", "week"], + years: ["year"], + months: ["month"], + weeks: ["week", "week"], days: [], hours: [], minutes: [], diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/date-and-time-durations-opposite-signs.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/date-and-time-durations-opposite-signs.js index 53d5d64240..7e46afae63 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/until/date-and-time-durations-opposite-signs.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/until/date-and-time-durations-opposite-signs.js @@ -23,14 +23,8 @@ features: [Temporal] // Based on a test case by André Bargull const calendar = new class extends Temporal.Calendar { - #dateUntil = 0; - dateUntil(one, two, options) { - let result = super.dateUntil(one, two, options); - if (++this.#dateUntil === 2) { - result = result.negated(); - } - return result; + return super.dateUntil(one, two, options).negated(); } }("iso8601"); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/normalized-time-duration-to-days-loop-arbitrarily.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/normalized-time-duration-to-days-loop-arbitrarily.js deleted file mode 100644 index 5f38d19ed4..0000000000 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/until/normalized-time-duration-to-days-loop-arbitrarily.js +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2022 Igalia, S.L. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-temporal.zoneddatetime.prototype.until -description: > - NormalizedTimeDurationToDays should not be able to loop arbitrarily. -info: | - NormalizedTimeDurationToDays ( norm, zonedRelativeTo, timeZoneRec [ , precalculatedPlainDatetime ] ) - ... - 22. If NormalizedTimeDurationSign(_oneDayLess_) × _sign_ ≥ 0, then - a. Set _norm_ to _oneDayLess_. - b. Set _relativeResult_ to _oneDayFarther_. - c. Set _days_ to _days_ + _sign_. - d. Set _oneDayFarther_ to ? AddDaysToZonedDateTime(_relativeResult_.[[Instant]], _relativeResult_.[[DateTime]], _timeZoneRec_, _zonedRelativeTo_.[[Calendar]], _sign_). - e. Set dayLengthNs to NormalizedTimeDurationFromEpochNanosecondsDifference(_oneDayFarther.[[EpochNanoseconds]], relativeResult.[[EpochNanoseconds]]). - f. If NormalizedTimeDurationSign(? SubtractNormalizedTimeDuration(_norm_, _dayLengthNs_)) × _sign_ ≥ 0, then - i. Throw a *RangeError* exception. -features: [Temporal] ----*/ - -const dayLengthNs = 86400000000000n; -const dayInstant = new Temporal.Instant(dayLengthNs); -let calls = 0; -const timeZone = new class extends Temporal.TimeZone { - getPossibleInstantsFor() { - calls++; - return [dayInstant]; - } -}("UTC"); - -const zdt = new Temporal.ZonedDateTime(0n, timeZone); -const other = new Temporal.ZonedDateTime(dayLengthNs * 2n, "UTC", "iso8601"); - -assert.throws(RangeError, () => zdt.until(other, { largestUnit: "day", smallestUnit: "second" }), "indefinite loop is prevented"); -assert.sameValue(calls, 4, "getPossibleInstantsFor is not called indefinitely"); - // Expected calls: - // DifferenceTemporalZonedDateTime -> - // DifferenceZonedDateTime -> GetInstantFor (1) - // NormalizedTimeDurationToDays -> - // AddDaysToZonedDateTime (2, step 12) - // AddDaysToZonedDateTime (3, step 15) - // AddDaysToZonedDateTime (4, step 18.d) diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/normalized-time-duration-to-days-range-errors.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/normalized-time-duration-to-days-range-errors.js deleted file mode 100644 index e96491630f..0000000000 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/until/normalized-time-duration-to-days-range-errors.js +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (C) 2022 Igalia, S.L. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. -/*--- -esid: sec-temporal.zoneddatetime.prototype.until -description: > - Abstract operation NormalizedTimeDurationToDays can throw four different - RangeErrors. -info: | - NormalizedTimeDurationToDays ( norm, zonedRelativeTo, timeZoneRec [ , precalculatedPlainDateTime ] ) - 23. If days < 0 and sign = 1, throw a RangeError exception. - 24. If days > 0 and sign = -1, throw a RangeError exception. - ... - 26. If NormalizedTimeDurationSign(_norm_) = 1 and sign = -1, throw a RangeError exception. - ... - 29. If dayLength ≥ 2⁵³, throw a RangeError exception. -features: [Temporal, BigInt] -includes: [temporalHelpers.js] ----*/ - -function timeZoneSubstituteValues( - getPossibleInstantsFor, - getOffsetNanosecondsFor -) { - const tz = new Temporal.TimeZone("UTC"); - TemporalHelpers.substituteMethod( - tz, - "getPossibleInstantsFor", - getPossibleInstantsFor - ); - TemporalHelpers.substituteMethod( - tz, - "getOffsetNanosecondsFor", - getOffsetNanosecondsFor - ); - return tz; -} - -const dayNs = 86_400_000_000_000; -const zeroZDT = new Temporal.ZonedDateTime(0n, "UTC"); -const oneZDT = new Temporal.ZonedDateTime(1n, "UTC"); -const epochInstant = new Temporal.Instant(0n); -const options = { largestUnit: "days", smallestUnit: "seconds", roundingMode: "expand" }; - -// Step 23: days < 0 and sign = 1 -let start = new Temporal.ZonedDateTime( - 0n, // Sets DifferenceZonedDateTime _ns1_ - timeZoneSubstituteValues( - [ - TemporalHelpers.SUBSTITUTE_SKIP, // Behave normally in DifferenceZonedDateTime - [epochInstant], // Returned in step 16, setting _relativeResult_ - ], - [ - // Behave normally in 2 calls made prior to NormalizedTimeDurationToDays - TemporalHelpers.SUBSTITUTE_SKIP, - TemporalHelpers.SUBSTITUTE_SKIP, - dayNs - 1, // Returned in step 8, setting _startDateTime_ - -dayNs + 1, // Returned in step 9, setting _endDateTime_ - ] - ) -); -assert.throws(RangeError, () => - start.until( - oneZDT, // Sets DifferenceZonedDateTime _ns2_ - options - ), - "days < 0 and sign = 1" -); - -// Step 24: days > 0 and sign = -1 -start = new Temporal.ZonedDateTime( - 1n, // Sets DifferenceZonedDateTime _ns1_ - timeZoneSubstituteValues( - [ - TemporalHelpers.SUBSTITUTE_SKIP, // Behave normally in DifferenceZonedDateTime - [epochInstant], // Returned in step 16, setting _relativeResult_ - ], - [ - // Behave normally in 2 calls made prior to NormalizedTimeDurationToDays - TemporalHelpers.SUBSTITUTE_SKIP, - TemporalHelpers.SUBSTITUTE_SKIP, - -dayNs + 1, // Returned in step 8, setting _startDateTime_ - dayNs - 1, // Returned in step 9, setting _endDateTime_ - ] - ) -); -assert.throws(RangeError, () => - start.until( - zeroZDT, // Sets DifferenceZonedDateTime _ns2_ - options - ), - "days > 0 and sign = -1" -); - -// Step 26: nanoseconds > 0 and sign = -1 -start = new Temporal.ZonedDateTime( - 1n, // Sets DifferenceZonedDateTime _ns1_ - timeZoneSubstituteValues( - [ - TemporalHelpers.SUBSTITUTE_SKIP, // Behave normally in DifferenceZonedDateTime - [new Temporal.Instant(-2_000_000_000n)], // Returned in step 16, setting _relativeResult_ - ], - [ - // Behave normally in 2 calls made prior to NormalizedTimeDurationToDays - TemporalHelpers.SUBSTITUTE_SKIP, - TemporalHelpers.SUBSTITUTE_SKIP, - dayNs - 1, // Returned in step 8, setting _startDateTime_ - -dayNs + 1, // Returned in step 9, setting _endDateTime_ - ] - ) -); -assert.throws(RangeError, () => - start.until( - zeroZDT, // Sets DifferenceZonedDateTime _ns2_ - options - ), - "norm > 0 and sign = -1" -); - -// Step 29: day length is an unsafe integer -start = new Temporal.ZonedDateTime( - 0n, - timeZoneSubstituteValues( - [ - TemporalHelpers.SUBSTITUTE_SKIP, // Behave normally in DifferenceZonedDateTime - // Not called in step 16 because _days_ = 0 - // Returned in step 19, making _oneDayFarther_ 2^53 ns later than _relativeResult_ - [new Temporal.Instant(2n ** 53n)], - ], - [] - ) -); -assert.throws(RangeError, () => - start.until( - oneZDT, - options - ), - "Should throw RangeError when time zone calculates an outrageous day length" -); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/order-of-operations.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/order-of-operations.js index 502fa13eb6..db70d40485 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/until/order-of-operations.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/until/order-of-operations.js @@ -327,64 +327,39 @@ const expectedOpsForCalendarDifference = [ "call this.calendar.dateUntil", ]; -const expectedOpsForCalendarRounding = [ - // RoundDuration → MoveRelativeZonedDateTime → AddZonedDateTime +const expectedOpsForCalendarRounding = expected.concat(expectedOpsForCalendarDifference, [ + // RoundRelativeDuration + "call this.calendar.dateAdd", "call this.calendar.dateAdd", "call this.timeZone.getPossibleInstantsFor", - // RoundDuration → NanosecondsToDays - "call this.timeZone.getOffsetNanosecondsFor", - "call this.timeZone.getOffsetNanosecondsFor", - // RoundDuration → NanosecondsToDays → AddDaysToZonedDateTime "call this.timeZone.getPossibleInstantsFor", -]; +]); -// code path that skips RoundDuration: +// code path that skips RoundRelativeDuration: instance.until(otherDateTimePropertyBag, createOptionsObserver({ largestUnit: "years", smallestUnit: "nanoseconds", roundingIncrement: 1 })); assert.compareArray(actual, expected.concat(expectedOpsForCalendarDifference), "order of operations with largestUnit years and no rounding"); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest year: -const expectedOpsForYearRounding = expected.concat(expectedOpsForCalendarDifference, expectedOpsForCalendarRounding, [ - // RoundDuration - "call this.calendar.dateAdd", // 12.d - "call this.calendar.dateAdd", // 12.f - "call this.calendar.dateUntil", // 12.n - "call this.calendar.dateAdd", // 12.x MoveRelativeDate - // (12.r not called because other units can't add up to >1 year at this point) - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 9.c - "call this.calendar.dateUntil" // 9.d -]); +// code path through RoundRelativeDuration that rounds to the nearest year: instance.until(otherDateTimePropertyBag, createOptionsObserver({ smallestUnit: "years" })); -assert.compareArray(actual, expectedOpsForYearRounding, "order of operations with smallestUnit = years"); +assert.compareArray(actual, expectedOpsForCalendarRounding, "order of operations with smallestUnit = years"); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest month: -const expectedOpsForMonthRounding = expected.concat(expectedOpsForCalendarDifference, expectedOpsForCalendarRounding, [ - // RoundDuration - "call this.calendar.dateAdd", // 13.c - "call this.calendar.dateAdd", // 13.e - "call this.calendar.dateUntil", // 13.m - "call this.calendar.dateAdd", // 13.w MoveRelativeDate - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 10.d - "call this.calendar.dateUntil", // 10.e -]); +// code path through RoundRelativeDuration that rounds to the nearest month: instance.until(otherDateTimePropertyBag, createOptionsObserver({ smallestUnit: "months" })); -assert.compareArray(actual, expectedOpsForMonthRounding, "order of operations with smallestUnit = months"); +assert.compareArray(actual, expectedOpsForCalendarRounding, "order of operations with smallestUnit = months"); actual.splice(0); // clear -// code path through RoundDuration that rounds to the nearest week: -const expectedOpsForWeekRounding = expected.concat(expectedOpsForCalendarDifference, expectedOpsForCalendarRounding, [ - // RoundDuration - "call this.calendar.dateUntil", // 14.f - "call this.calendar.dateAdd", // 14.p MoveRelativeDate - // BalanceDateDurationRelative - "call this.calendar.dateAdd", // 16 - "call this.calendar.dateUntil", // 17 -]); +// code path through RoundRelativeDuration that rounds to the nearest week: instance.until(otherDateTimePropertyBag, createOptionsObserver({ smallestUnit: "weeks" })); -assert.compareArray(actual, expectedOpsForWeekRounding, "order of operations with smallestUnit = weeks"); +assert.compareArray(actual, expected.concat(expectedOpsForCalendarDifference, [ + // RoundRelativeDuration + "call this.calendar.dateUntil", + "call this.calendar.dateAdd", + "call this.calendar.dateAdd", + "call this.timeZone.getPossibleInstantsFor", + "call this.timeZone.getPossibleInstantsFor", +]), "order of operations with smallestUnit = weeks"); actual.splice(0); // clear instance.until(otherDateTimePropertyBag, createOptionsObserver({ largestUnit: "hours" })); diff --git a/test/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-non-integer.js b/test/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-non-integer.js index eacbc18066..01335cdaee 100644 --- a/test/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-non-integer.js +++ b/test/built-ins/Temporal/ZonedDateTime/prototype/until/roundingincrement-non-integer.js @@ -20,5 +20,3 @@ const earlier = new Temporal.ZonedDateTime(1_000_000_000_000_000_000n, "UTC"); const later = new Temporal.ZonedDateTime(1_000_000_000_000_000_005n, "UTC"); const result = earlier.until(later, { roundingIncrement: 2.5, roundingMode: "trunc" }); TemporalHelpers.assertDuration(result, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, "roundingIncrement 2.5 truncates to 2"); -const result2 = earlier.until(later, { smallestUnit: "days", roundingIncrement: 1e9 + 0.5, roundingMode: "expand" }); -TemporalHelpers.assertDuration(result2, 0, 0, 0, 1e9, 0, 0, 0, 0, 0, 0, "roundingIncrement 1e9 + 0.5 truncates to 1e9"); diff --git a/test/staging/Temporal/Duration/old/round.js b/test/staging/Temporal/Duration/old/round.js index 5bc92fb56a..2a4c379f84 100644 --- a/test/staging/Temporal/Duration/old/round.js +++ b/test/staging/Temporal/Duration/old/round.js @@ -324,7 +324,7 @@ var roundAndBalanceResults = { years: { years: "P6Y", months: "P5Y6M", - weeks: "P5Y5M6W", + weeks: "P5Y6M1W", days: "P5Y6M10D", hours: "P5Y6M10DT5H", minutes: "P5Y6M10DT5H5M", @@ -335,7 +335,7 @@ var roundAndBalanceResults = { }, months: { months: "P66M", - weeks: "P65M6W", + weeks: "P66M1W", days: "P66M10D", hours: "P66M10DT5H", minutes: "P66M10DT5H5M", diff --git a/test/staging/Temporal/Duration/old/total.js b/test/staging/Temporal/Duration/old/total.js index 31216e0999..f12f767aa5 100644 --- a/test/staging/Temporal/Duration/old/total.js +++ b/test/staging/Temporal/Duration/old/total.js @@ -286,7 +286,7 @@ var totalDays = hours25.total({ unit: "days", relativeTo }); -assert(Math.abs(totalDays - (1 + 1 / 24)) < Number.EPSILON); +assert(Math.abs(totalDays - (1 + 1 / 23)) < Number.EPSILON); assert.sameValue(oneDay.total({ unit: "hours", relativeTo