From f6ad8083e4e89004a8aa2ec45b3eed1d9032a990 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Fri, 3 May 2024 14:19:10 -0700 Subject: [PATCH] WIP: Spec text --- spec/duration.html | 356 +++++++++++++++++++++++++--------------- spec/instant.html | 2 +- spec/zoneddatetime.html | 70 -------- 3 files changed, 227 insertions(+), 201 deletions(-) diff --git a/spec/duration.html b/spec/duration.html index c2ee1bac7..faa49807d 100644 --- a/spec/duration.html +++ b/spec/duration.html @@ -473,7 +473,7 @@

Temporal.Duration.prototype.round ( _roundTo_ )

1. Let _relativeEpochNs_ be _zonedRelativeTo_.[[Nanoseconds]]. 1. Let _relativeInstant_ be ! CreateTemporalInstant(_relativeEpochNs_). 1. Let _targetEpochNs_ be ? AddZonedDateTime(_relativeInstant_, _timeZoneRec_, _calendarRec_, _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _norm_, _precalculatedPlainDateTime_). - 1. Let _roundRecord_ be ? DifferenceZonedDateTimeWithRounding(_relativeEpochNs_, _targetEpochNs_, _plainRelativeTo_, _calendarRec_, _zonedRelativeTo_, _timeZoneRec_, _precalculatedPlainDateTime_, _emptyOptions_, _largestUnit_, _roundingIncrement_, _smallestUnit_, _roundingMode_). + 1. Let _roundRecord_ be ? DifferenceZonedDateTimeWithRounding(_relativeEpochNs_, _targetEpochNs_, _calendarRec_, _timeZoneRec_, _precalculatedPlainDateTime_, _emptyOptions_, _largestUnit_, _roundingIncrement_, _smallestUnit_, _roundingMode_). 1. Let _roundResult_ be _roundRecord_.[[DurationRecord]]. 1. Else if _plainRelativeTo_ is not *undefined*, then 1. Let _targetTime_ be AddTime(0, 0, 0, 0, 0, 0, _norm_). @@ -483,7 +483,7 @@

Temporal.Duration.prototype.round ( _roundTo_ )

1. Let _roundResult_ be _roundRecord_.[[DurationRecord]]. 1. Else, 1. If _calendarUnitsPresent_ is *true*, or IsCalendarUnit(_largestUnit_) is *true*, or IsCalendarUnit(_smallestUnit_) is *true*, throw a *RangeError* exception. - 1. Let _roundRecord_ be ? RoundDuration(0, 0, 0, _duration_.[[Days]], _norm_, _roundingIncrement_, _smallestUnit_, _roundingMode_). + 1. Let _roundRecord_ be ? RoundDuration(_duration_.[[Days]], _norm_, _roundingIncrement_, _smallestUnit_, _roundingMode_). 1. Let _normWithDays_ be ? Add24HourDaysToNormalizedTimeDuration(_roundRecord_.[[NormalizedDuration]].[[Days]], _roundRecord_.[[NormalizedDuration]].[[NormalizedTime]]). 1. Let _balanceResult_ be BalanceTimeDuration(_normWithDays_, _largestUnit_). 1. Let _roundResult_ be CreateDurationRecord(0, 0, 0, _balanceResult_.[[Days]], _balanceResult_.[[Hours]], _balanceResult_.[[Minutes]], _balanceResult_.[[Seconds]], _balanceResult_.[[Milliseconds]], _balanceResult_.[[Microseconds]], _balanceResult_.[[Nanoseconds]]). @@ -526,7 +526,7 @@

Temporal.Duration.prototype.total ( _totalOf_ )

1. Let _relativeEpochNs_ be _zonedRelativeTo_.[[Nanoseconds]]. 1. Let _relativeInstant_ be ! CreateTemporalInstant(_relativeEpochNs_). 1. Let _targetEpochNs_ be ? AddZonedDateTime(_relativeInstant_, _timeZoneRec_, _calendarRec_, _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _norm_, _precalculatedPlainDateTime_). - 1. Let _roundRecord_ be ? DifferenceZonedDateTimeWithRounding(_relativeEpochNs_, _targetEpochNs_, _plainRelativeTo_, _calendarRec_, _zonedRelativeTo_, _timeZoneRec_, _precalculatedPlainDateTime_, _emptyOptions_, _unit_, 1, _unit_, *"trunc"*). + 1. Let _roundRecord_ be ? DifferenceZonedDateTimeWithRounding(_relativeEpochNs_, _targetEpochNs_, _calendarRec_, _timeZoneRec_, _precalculatedPlainDateTime_, _emptyOptions_, _unit_, 1, _unit_, *"trunc"*). 1. Else if _plainRelativeTo_ is not *undefined*, then 1. Let _targetTime_ be AddTime(0, 0, 0, 0, 0, 0, _norm_). 1. Let _dateDuration_ be ? CreateTemporalDuration(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]] + _targetTime_.[[Days]], 0, 0, 0, 0, 0, 0). @@ -535,7 +535,8 @@

Temporal.Duration.prototype.total ( _totalOf_ )

1. Else, 1. If _duration_.[[Years]] ≠ 0, or _duration_.[[Months]] ≠ 0, or _duration_.[[Weeks]] ≠ 0, or IsCalendarUnit(_unit_) is *true*, throw a *RangeError* exception. 1. Let _normWithDays_ be ? Add24HourDaysToNormalizedTimeDuration(_duration_.[[Days]], _norm_). - 1. Let _roundRecord_ be ? RoundDuration(0, 0, 0, 0, _normWithDays_, 1, _unit_, *"trunc"*). + 1. Let _roundRecord_ be ? RoundDuration(0, _normWithDays_, 1, _unit_, *"trunc"*). + 1. Assert: _roundRecord_.[[Total]] is not ~unset~. 1. Return 𝔽(_roundRecord_.[[Total]]). @@ -558,7 +559,7 @@

Temporal.Duration.prototype.toString ( [ _options_ ] )

1. If _precision_.[[Unit]] is not *"nanosecond"* or _precision_.[[Increment]] ≠ 1, then 1. Let _norm_ be NormalizeTimeDuration(_duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]]). 1. Let _largestUnit_ be DefaultTemporalLargestUnit(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]]). - 1. Let _roundRecord_ be ? RoundDuration(0, 0, 0, 0, _norm_, _precision_.[[Increment]], _precision_.[[Unit]], _roundingMode_). + 1. Let _roundRecord_ be ? RoundDuration(0, _norm_, _precision_.[[Increment]], _precision_.[[Unit]], _roundingMode_). 1. Set _norm_ to _roundRecord_.[[NormalizedDuration]].[[NormalizedTime]]. 1. Let _result_ be BalanceTimeDuration(_norm_, LargerOfTwoTemporalUnits(_largestUnit_, *"second"*)). 1. Set _result_ to CreateDurationRecord(_duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]] + _result_.[[Days]], _result_.[[Hours]], _result_.[[Minutes]], _result_.[[Seconds]], _result_.[[Milliseconds]], _result_.[[Microseconds]], _result_.[[Nanoseconds]]). @@ -1673,48 +1674,6 @@

- -

- BalanceTimeDurationRelative ( - _days_: an integer, - _norm_: a Normalized Time Duration Record, - _largestUnit_: a String, - _zonedRelativeTo_: a Temporal.ZonedDateTime, - _timeZoneRec_: a Time Zone Methods Record, - _precalculatedPlainDateTime_: a Temporal.PlainDateTime or *undefined*, - ): either a normal completion containing a Time Duration Record or a throw completion -

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

- This operation observably calls time zone and calendar methods. -

- - 1. Let _startNs_ be _zonedRelativeTo_.[[Nanoseconds]]. - 1. Let _startInstant_ be ! CreateTemporalInstant(_startNs_). - 1. Let _intermediateNs_ be _startNs_. - 1. If _days_ ≠ 0, then - 1. If _precalculatedPlainDateTime_ is *undefined*, set _precalculatedPlainDateTime_ to ? GetPlainDateTimeFor(_timeZoneRec_, _startInstant_, *"iso8601"*). - 1. Let _intermediateResult_ be ? AddDaysToZonedDateTime(_startInstant_, _precalculatedPlainDateTime_, _timeZoneRec_, *"iso8601"*, _days_). - 1. Set _intermediateNs_ to _intermediateResult_.[[EpochNanoseconds]]. - 1. Let _endNs_ be ? AddInstant(_intermediateNs_, _norm_). - 1. Set _norm_ to NormalizedTimeDurationFromEpochNanosecondsDifference(_endNs_, _startNs_). - 1. If NormalizedTimeDurationIsZero(_norm_) is *true*, return CreateTimeDurationRecord(0, 0, 0, 0, 0, 0, 0). - 1. If IsCalendarUnit(_largestUnit_) is *true* or _largestUnit_ is *"day"*, then - 1. If _precalculatedPlainDateTime_ is *undefined*, set _precalculatedPlainDateTime_ to ? GetPlainDateTimeFor(_timeZoneRec_, _startInstant_, *"iso8601"*). - 1. Let _result_ be ? NormalizedTimeDurationToDays(_norm_, _zonedRelativeTo_, _timeZoneRec_, _precalculatedPlainDateTime_). - 1. Set _days_ to _result_.[[Days]]. - 1. Set _norm_ to _result_.[[NormalizedTime]]. - 1. Set _largestUnit_ to *"hour"*. - 1. Else, - 1. Set _days_ to 0. - 1. Let _balanceResult_ be BalanceTimeDuration(_norm_, _largestUnit_). - 1. Return CreateTimeDurationRecord(_days_, _balanceResult_.[[Hours]], _balanceResult_.[[Minutes]], _balanceResult_.[[Seconds]], _balanceResult_.[[Milliseconds]], _balanceResult_.[[Microseconds]], _balanceResult_.[[Nanoseconds]]). - -
-

UnbalanceDateDurationRelative ( @@ -1740,62 +1699,6 @@

- -

- BalanceDateDurationRelative ( - _years_: an integer, - _months_: an integer, - _weeks_: an integer, - _days_: an integer, - _largestUnit_: a String, - _smallestUnit_: a String, - _plainRelativeTo_: a Temporal.PlainDate, - _calendarRec_: a Calendar Methods Record, - ): either a normal completion containing a Date Duration Record or a throw completion -

-
-
description
-
It converts the calendar units of a duration into a form where lower units are converted into higher units as much as possible, up to _largestUnit_ and not lower than _smallestUnit_, and returns the result as a Date Duration Record.
-
- - 1. Let _allZero_ be *false*. - 1. If _years_ = 0, and _months_ = 0, and _weeks_ = 0, and _days_ = 0, set _allZero_ to *true*. - 1. If _largestUnit_ is not one of *"year"*, *"month"*, or *"week"*, or _allZero_ is *true*, then - 1. Return ! CreateDateDurationRecord(_years_, _months_, _weeks_, _days_). - 1. Assert: CalendarMethodsRecordHasLookedUp(_calendarRec_, ~date-add~) is *true*. - 1. Assert: CalendarMethodsRecordHasLookedUp(_calendarRec_, ~date-until~) is *true*. - 1. Let _untilOptions_ be OrdinaryObjectCreate(*null*). - 1. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, _largestUnit_). - 1. If _largestUnit_ is *"year"*, then - 1. If _smallestUnit_ is *"week"*, then - 1. Assert: _days_ = 0. - 1. Let _yearsMonthsDuration_ be ! CreateTemporalDuration(_years_, _months_, 0, 0, 0, 0, 0, 0, 0, 0). - 1. Let _later_ be ? AddDate(_calendarRec_, _plainRelativeTo_, _yearsMonthsDuration_). - 1. Let _untilResult_ be ? CalendarDateUntil(_calendarRec_, _plainRelativeTo_, _later_, _untilOptions_). - 1. Return ? CreateDateDurationRecord(_untilResult_.[[Years]], _untilResult_.[[Months]], _weeks_, 0). - 1. Let _yearsMonthsWeeksDaysDuration_ be ! CreateTemporalDuration(_years_, _months_, _weeks_, _days_, 0, 0, 0, 0, 0, 0). - 1. Let _later_ be ? AddDate(_calendarRec_, _plainRelativeTo_, _yearsMonthsWeeksDaysDuration_). - 1. Let _untilResult_ be ? CalendarDateUntil(_calendarRec_, _plainRelativeTo_, _later_, _untilOptions_). - 1. Return ! CreateDateDurationRecord(_untilResult_.[[Years]], _untilResult_.[[Months]], _untilResult_.[[Weeks]], _untilResult_.[[Days]]). - 1. If _largestUnit_ is *"month"*, then - 1. Assert: _years_ = 0. - 1. If _smallestUnit_ is *"week"*, then - 1. Assert: _days_ = 0. - 1. Return ! CreateDateDurationRecord(0, _months_, _weeks_, 0). - 1. Let _monthsWeeksDaysDuration_ be ! CreateTemporalDuration(0, _months_, _weeks_, _days_, 0, 0, 0, 0, 0, 0). - 1. Let _later_ be ? AddDate(_calendarRec_, _plainRelativeTo_, _monthsWeeksDaysDuration_). - 1. Let _untilResult_ be ? CalendarDateUntil(_calendarRec_, _plainRelativeTo_, _later_, _untilOptions_). - 1. Return ! CreateDateDurationRecord(0, _untilResult_.[[Months]], _untilResult_.[[Weeks]], _untilResult_.[[Days]]). - 1. Assert: _largestUnit_ is *"week"*. - 1. Assert: _years_ = 0. - 1. Assert: _months_ = 0. - 1. Let _weeksDaysDuration_ be ! CreateTemporalDuration(0, 0, _weeks_, _days_, 0, 0, 0, 0, 0, 0). - 1. Let _later_ be ? AddDate(_calendarRec_, _plainRelativeTo_, _weeksDaysDuration_). - 1. Let _untilResult_ be ? CalendarDateUntil(_calendarRec_, _plainRelativeTo_, _later_, _untilOptions_). - 1. Return ! CreateDateDurationRecord(0, 0, _untilResult_.[[Weeks]], _untilResult_.[[Days]]). - -
-

AddDuration ( @@ -2091,47 +1994,240 @@

- +

- AdjustRoundedDurationDays ( - _years_: an integer, + NudgeToCalendarUnit ( + _sign_: -1 or 1, + _years_: an integer FIXME use Date Duration Record, + _months_: an integer, + _weeks_: an integer, + _days_: an integer, + _plainDateTime_: a Temporal.PlainDateTime instance / an ISO Date-Time Record FIXME, + _calendarRec_: a Calendar Method Record, + _timeZoneRec_: a Time Zone Method Record or ~unset~, + _destEpochNs_: a BigInt, + _increment_: an integer, + _unit_: a String from the "Singular" column of , + _roundingMode_: a String from the "Identifier" column of , + ): either a normal completion containing a Record with fields [[DateDuration]] (a Date Duration Record), [[Total]] (a mathematical value), [[NudgedEpochNs]] (a BigInt), and [[DidExpandCalendarUnit]] (a Boolean), or a throw completion +

+
+
description
+
+ It implements rounding a duration to an increment of a calendar unit, relative to a starting point, by calculating the upper and lower bounds of the starting point added to the duration in epoch nanoseconds, and rounding according to which one is closer to _destEpochNs_. +
+
+ + 1. If _unit_ is *"year"*, then + 1. Set _years_ to RoundNumberToIncrement(_years_, _increment_, *"trunc"*). + 1. Let _r1_ be _years_. + 1. Let _r2_ be _years_ + _increment_ × _sign_. + 1. Let _startDuration_ be ? CreateDateDurationRecord(_r1_, 0, 0, 0). + 1. Let _endDuration_ be ? CreateDateDurationRecord(_r2_, 0, 0, 0). + 1. Else if _unit_ is *"month"*, then + 1. Set _months_ to RoundNumberToIncrement(_months_, _increment_, *"trunc"*). + 1. Let _r1_ be _months_. + 1. Let _r2_ be _months_ + _increment_ × _sign_. + 1. Let _startDuration_ be ? CreateDateDurationRecord(_years_, _r1_, 0, 0). + 1. Let _endDuration_ be ? CreateDateDurationRecord(_years_, _r2_, 0, 0). + 1. Else if _unit_ is *"week"*, then + 1. Let _isoResult1_ be BalanceISODate(_plainDateTime_.[[ISOYear]] + _years_, _plainDateTime_.[[ISOMonth]] + _months_, _plainDateTime_.[[ISODay]]). + 1. Let _isoResult2_ be BalanceISODate(_plainDateTime_.[[ISOYear]] + _years_, _plainDateTime_.[[ISOMonth]] + _months_, _plainDateTime_.[[ISODay]] + _days_). + 1. Let _weeksStart_ be ! CreateTemporalDate(_isoResult1_.[[Year]], _isoResult1_.[[Month]], _isoResult1_.[[Day]], _calendarRec_.[[Receiver]]). + 1. Let _weeksEnd_ be ! CreateTemporalDate(_isoResult2_.[[Year]], _isoResult2_.[[Month]], _isoResult2_.[[Day]], _calendarRec_.[[Receiver]]). + 1. Let _untilOptions_ be OrdinaryObjectCreate(*null*). + 1. Perform ! CreateDataPropertyOrThrow(_untilOptions_, *"largestUnit"*, *"week"*). + 1. Let _untilResult_ be ? DifferenceDate(_calendarRec_, _weeksStart_, _weeksEnd_, _untilOptions_). + 1. Set _weeks_ to _weeks_ + _untilResult_.[[Weeks]]. + 1. Set _weeks_ to RoundNumberToIncrement(_weeks_, _increment_, *"trunc"*). + 1. Let _r1_ be _weeks_. + 1. Let _r2_ be _weeks_ + _increment_ × _sign_. + 1. Let _startDuration_ be ? CreateDateDurationRecord(_years_, _months_, _r1_, 0). + 1. Let _endDuration_ be ? CreateDateDurationRecord(_years_, _months_, _r2_, 0). + 1. Else, + 1. Assert: _unit_ is *"day"*. + 1. Set _days_ to RoundNumberToIncrement(_days_, _increment_, *"trunc"*). + 1. Let _r1_ be _days_. + 1. Let _r2_ be _days_ + _increment_ × _sign_. + 1. Let _startDuration_ be ? CreateDateDurationRecord(_years_, _months_, _weeks_, _r1_). + 1. Let _endDuration_ be ? CreateDateDurationRecord(_years_, _months_, _weeks_, _r2_). + 1. Let _start_ be ? AddDateTime(_plainDateTime_.[[ISOYear]], _plainDateTime_.[[ISOMonth], _plainDateTime_.[[ISODay]], _plainDateTime_.[[ISOHour]], _plainDateTime_.[[ISOMinute]], _plainDateTime_.[[ISOSecond]], _plainDateTime_.[[ISOMillisecond]], _plainDateTime_.[[ISOMicrosecond]], _plainDateTime_.[[ISONanosecond]], _calendarRec_, _startDuration_.[[Years]], _startDuration_.[[Months]], _startDuration_.[[Weeks]], _startDuration_.[[Days]], ZeroTimeDuration(), *undefined*). + 1. Let _end_ be ? AddDateTime(_plainDateTime_.[[ISOYear]], _plainDateTime_.[[ISOMonth], _plainDateTime_.[[ISODay]], _plainDateTime_.[[ISOHour]], _plainDateTime_.[[ISOMinute]], _plainDateTime_.[[ISOSecond]], _plainDateTime_.[[ISOMillisecond]], _plainDateTime_.[[ISOMicrosecond]], _plainDateTime_.[[ISONanosecond]], _calendarRec_, _endDuration_.[[Years]], _endDuration_.[[Months]], _endDuration_.[[Weeks]], _endDuration_.[[Days]], ZeroTimeDuration(), *undefined*). + 1. If _timeZoneRec_ is ~unset~, then + 1. Let _startEpochNs_ be GetUTCEpochNanoseconds(_start_.[[Year]], _start_.[[Month]], _start_.[[Day]], _start_.[[Hour]], _start_.[[Minute]], _start_.[[Second]], _start_.[[Millisecond]], _start_.[[Microsecond]], _start_.[[Nanosecond]]). + 1. Let _endEpochNs_ be GetUTCEpochNanoseconds(_end_.[[Year]], _end_.[[Month]], _end_.[[Day]], _end_.[[Hour]], _end_.[[Minute]], _end_.[[Second]], _end_.[[Millisecond]], _end_.[[Microsecond]], _end_.[[Nanosecond]]). + 1. Else, + 1. Let _startDateTime_ be ! CreateTemporalDateTime(_start_.[[Year]], _start_.[[Month]], _start_.[[Day]], _start_.[[Hour]], _start_.[[Minute]], _start_.[[Second]], _start_.[[Millisecond]], _start_.[[Microsecond]], _start_.[[Nanosecond]], _calendarRec_.[[Receiver]]). + 1. Let _startInstant_ be ? GetInstantFor(_timeZoneRec_, _startDateTime_, *"compatible"*). + 1. Let _startEpochNs_ be _startInstant_.[[Nanoseconds]]. + 1. Let _endDateTime_ be ! CreateTemporalDateTime(_end_.[[Year]], _end_.[[Month]], _end_.[[Day]], _end_.[[Hour]], _end_.[[Minute]], _end_.[[Second]], _end_.[[Millisecond]], _end_.[[Microsecond]], _end_.[[Nanosecond]], _calendarRec_.[[Receiver]]). + 1. Let _endInstant_ be ? GetInstantFor(_timeZoneRec_, _endDateTime_, *"compatible"*). + 1. Let _endEpochNs_ be _endInstant_.[[Nanoseconds]]. + 1. If _endEpochNs_ = _startEpochNs_, throw a *RangeError* exception. + 1. If _sign_ < 0, let _isNegative_ be ~negative~; else let _isNegative_ be ~positive~. + 1. Let _unsignedRoundingMode_ be GetUnsignedRoundingMode(_roundingMode_, _isNegative_). + 1. Let _progress_ be (_destEpochNs_ - _startEpochNs_) / (_endEpochNs_ - _startEpochNs_). + 1. Let _total_ be _r1_ + _progress_ × _increment_ × _sign_. + 1. NOTE: The above two steps cannot be implemented directly using floating-point arithmetic. FIXME suggestion for how to do it. + 1. Let _roundedUnit_ be ApplyUnsignedRoundingMode(_total_, _r1_, _r2_, _unsignedRoundingMode_). + 1. If _roundedUnit_ - _total_ < 0, let _roundedSign_ be -1; else let _roundedSign_ be 1. + 1. If _roundedSign_ = _sign_, then + 1. Let _didExpandCalendarUnit_ be *true*. + 1. Let _resultDuration_ be _endDuration_. + 1. Let _nudgedEpochNs_ be _endEpochNs_. + 1. Else, + 1. Let _didExpandCalendarUnit_ be *false*. + 1. Let _resultDuration_ be _startDuration_. + 1. Let _nudgedEpochNs_ be _startEpochNs_. + 1. Return the Record { [[DateDuration]]: _resultDuration_, [[Total]]: _total_, [[NudgedEpochNs]]: _nudgedEpochNs_, [[DidExpandCalendarUnit]]: _didExpandCalendarUnit_ }. + +
+ + +

+ NudgeToZonedTime ( + _sign_: -1 or 1, + _years_: an integer FIXME use Normalized Duration Record, _months_: an integer, _weeks_: an integer, _days_: an integer, _norm_: a Normalized Time Duration Record, + _plainDateTime_: a Temporal.PlainDateTime instance / an ISO Date-Time Record FIXME, + _calendarRec_: a Calendar Method Record, + _timeZoneRec_: a Time Zone Method Record, _increment_: an integer, - _unit_: a String, + _unit_: a String from the "Singular" column of FIXME, _roundingMode_: a String from the "Identifier" column of , - _zonedRelativeTo_: a Temporal.ZonedDateTime, - _calendarRec_: a Calendar Methods Record, - _timeZoneRec_: a Time Zone Methods Record, - _precalculatedPlainDateTime_: a Temporal.PlainDateTime or *undefined*, - ): either a normal completion containing a Normalized Duration Record or a throw completion + ): either a normal completion containing a Record with fields [[Duration]] (a Normalized Duration Record), [[NudgedEpochNs]] (a BigInt), and [[DidExpandCalendarUnit]] (a Boolean), or a throw completion +

+
+
description
+
+ It implements rounding a duration to an increment of a time unit, relative to a `Temporal.ZonedDateTime` starting point, accounting for the case where the rounding causes the time to exceed the total time within a day, which may be influenced by UTC offset changes in the time zone. +
+
+ + 1. Let _start_ be ? AddDateTime(_plainDateTime_.[[ISOYear]], _plainDateTime_.[[ISOMonth], _plainDateTime_.[[ISODay]], _plainDateTime_.[[ISOHour]], _plainDateTime_.[[ISOMinute]], _plainDateTime_.[[ISOSecond]], _plainDateTime_.[[ISOMillisecond]], _plainDateTime_.[[ISOMicrosecond]], _plainDateTime_.[[ISONanosecond]], _calendarRec_, _years_, _months_, _weeks_, _days_, _norm_, *undefined*). + 1. Let _startDateTime_ be ! CreateTemporalDateTime(_start_.[[Year]], _start_.[[Month]], _start_.[[Day]], _start_.[[Hour]], _start_.[[Minute]], _start_.[[Second]], _start_.[[Millisecond]], _start_.[[Microsecond]], _start_.[[Nanosecond]], _calendarRec_.[[Receiver]]). + 1. Let _endDate_ be BalanceISODate(_start_.[[Year]], _start_.[[Month]], _start_.[[Day]] + _sign_). + 1. Let _endDateTime_ be ? CreateTemporalDateTime(_endDate_.[[Year]], _endDate_.[[Month]], _endDate_.[[Day]], _start_.[[Hour]], _start_.[[Minute]], _start_.[[Second]], _start_.[[Millisecond]], _start_.[[Microsecond]], _start_.[[Nanosecond]], _calendarRec_.[[Receiver]]). + 1. Let _startInstant_ be ? GetInstantFor(_timeZoneRec_, _startDateTime_, *"compatible"*). + 1. Let _startEpochNs_ be _startInstant_.[[Nanoseconds]]. + 1. Let _endInstant_ be ? GetInstantFor(_timeZoneRec_, _endDateTime_, *"compatible"*). + 1. Let _endEpochNs_ be _endInstant_.[[Nanoseconds]]. + 1. Let _daySpan_ be NormalizedTimeDurationFromEpochNanosecondsDifference(_endEpochNs_, _startEpochNs_). + 1. Assert: NormalizedTimeDurationSign(_daySpan_) = _sign_. + 1. Let _unitLength_ be the value in the "Length in Nanoseconds" column of the row of whose "Singular" column contains _unit_. + 1. Let _roundedNorm_ be ? RoundNormalizedTimeDurationToIncrement(_norm_, _increment_ × _unitLength_, _roundingMode_). + 1. Let _beyondDaySpan_ be ? SubtractNormalizedTimeDuration(_roundedNorm_, _daySpan_). + 1. If NormalizedTimeDurationSign(_beyondDaySpan_) &neq; -_sign_, then + 1. Let _didRoundBeyondDay_ be *true*. + 1. Let _dayDelta_ be _sign_. + 1. Set _roundedNorm_ to ? RoundNormalizedTimeDurationToIncrement(_beyondDaySpan_, _increment_ × _unitLength_, _roundingMode_). + 1. Let _nudgedEpochNs_ be AddNormalizedTimeDurationToEpochNanoseconds(_roundedNorm_, _endEpochNs_). + 1. Else, + 1. Let _didRoundBeyondDay_ be *false*. + 1. Let _dayDelta_ be 0. + 1. Let _nudgedEpochNs_ be AddNormalizedTimeDurationToEpochNanoseconds(_roundedNorm_, _startEpochNs_). + 1. Let _resultDuration_ be ? CreateNormalizedDurationRecord(_years_, _months_, _weeks_, _days_ + _dayDelta_, _roundedNorm_). + 1. Return the Record { [[Duration]]: _resultDuration_, [[NudgedEpochNs]]: _nudgedEpochNs_, [[DidExpandCalendarUnit]]: _didRoundBeyondDay_ }. + +
+ + +

+ NudgeToDayOrTime ( + _days_: an integer, + _norm_: a Normalized Time Duration Record, + _destEpochNs_: a BigInt, + _increment_: an integer, + _unit_: a String from the "Singular" column of FIXME, + _roundingMode_: a String from the "Identifier" column of , + ): either a normal completion containing a Record with fields [[Days]] (an integer), [[Norm]] (a Normalized Time Duration Record), [[Total]] (a mathematical value), [[NudgedEpochNs]] (a BigInt), and [[DidExpandCalendarUnit]] (a Boolean), or a throw completion +

+
+
description
+
+ It implements rounding a duration to an increment of a time unit, in cases unaffected by the calendar or time zone. +
+
+ + 1. Set _norm_ to ! Add24HourDaysToNormalizedTimeDuration(_norm_, _days_). + 1. Set _days_ to 0. + 1. Let _unitLength_ be the value in the "Length in Nanoseconds" column of the row of whose "Singular" column contains _unit_. + 1. Let _total_ be DivideNormalizedTimeDuration(_norm_, _unitLength_). + 1. Let _roundedNorm_ be ? RoundNormalizedTimeDurationToIncrement(_norm_, _unitLength_ × _increment_, _roundingMode_). + 1. Let _diffNorm_ be ! SubtractNormalizedTimeDuration(_roundedNorm_, _norm_). + 1. Let _wholeDays_ be truncate(DivideNormalizedTimeDuration(_norm_, nsPerDay)). + 1. Let _roundedWholeDays_ be truncate(DivideNormalizedTimeDuration(_roundedNorm_, nsPerDay)). + 1. Let _dayDelta_ be _roundedWholeDays_ - _wholeDays_. + 1. If _dayDelta_ < 0, let _dayDeltaSign_ be -1; else if _dayDelta_ > 0, let _dayDeltaSign_ be 1; else let _dayDeltaSign_ be 0. + 1. If _dayDeltaSign_ = NormalizedTimeDurationSign(_norm_), let _didExpandDays_ be *true*; else let _didExpandDays_ be *false*. + 1. Let _nudgedEpochNs_ be AddNormalizedTimeDurationToEpochNanoseconds(_diffNorm_, _destEpochNs_). + 1. Return the Record { [[Days]]: _days_, [[Norm]]: _roundedNorm_, [[Total]]: _total_, [[NudgedEpochNs]]: _nudgedEpochNs_, [[DidExpandCalendarUnit]]: _didExpandDays_ }. + +
+ + +

+ BubbleRelativeDuration ( + _sign_: -1 or 1, + _years_: an integer FIXME use Normalized Duration Record, + _months_: an integer, + _weeks_: an integer, + _days_: an integer, + _norm_: a Normalized Time Duration Record, + _nudgedEpochNs_: a BigInt, + _plainDateTime_: a Temporal.PlainDateTime instance / an ISO Date-Time Record FIXME, + _calendarRec_: a Calendar Method Record, + _timeZoneRec_: a Time Zone Method Record or ~unset~, + _largestUnit_: a String from the "Singular" column of FIXME, + _smallestUnit_: a String from the "Singular" column of FIXME, + ): either a normal completion containing a Record with fields [[Duration]] (a Normalized Duration Record), [[NudgedEpochNs]] (a BigInt), and [[DidExpandCalendarUnit]] (a Boolean), or a throw completion

description
- It adjusts, if necessary, a duration that was rounded to a unit of hours or lower relative to a Temporal.ZonedDateTime, and returns the result. - On a calendar day that is not 24 hours in length due to time zone offset changes, it is possible for a duration's time units to round up to exceed the day's length. - In this case, the days part of the duration is adjusted by one, and the time part is re-rounded. + Given a duration that has potentially been made bottom-heavy by rounding in NudgeToCalendarUnit, NudgeToZonedTime, or NudgeToDayOrTime, it bubbles up smaller units to larger units.
- 1. If IsCalendarUnit(_unit_) is *true*; or _unit_ is *"day"*; or _unit_ is *"nanosecond"* and _increment_ is 1, then - 1. Return ! CreateNormalizedDurationRecord(_years_, _months_, _weeks_, _days_, _norm_). - 1. Assert: _precalculatedPlainDateTime_ is not *undefined*. - 1. Let _direction_ be NormalizedTimeDurationSign(_norm_). - 1. Let _dayStart_ be ? AddZonedDateTime(_zonedRelativeTo_.[[Nanoseconds]], _timeZoneRec_, _calendarRec_, _years_, _months_, _weeks_, _days_, ZeroTimeDuration(), _precalculatedPlainDateTime_). - 1. Let _dayStartInstant_ be ! CreateTemporalInstant(_dayStart_). - 1. Let _dayStartDateTime_ be ? GetPlainDateTimeFor(_timeZoneRec_, _dayStartInstant_, _zonedRelativeTo_.[[Calendar]]). - 1. Let _dayEnd_ be ? AddDaysToZonedDateTime(_dayStartInstant_, _dayStartDateTime_, _timeZoneRec_, _zonedRelativeTo_.[[Calendar]], _direction_).[[EpochNanoseconds]]. - 1. Let _dayLengthNs_ be NormalizedTimeDurationFromEpochNanosecondsDifference(_dayEnd_, _dayStart_). - 1. Let _oneDayLess_ be ? SubtractNormalizedTimeDuration(_norm_, _dayLengthNs_). - 1. If NormalizedTimeDurationSign(_oneDayLess_) × _direction_ < 0, then - 1. Return ! CreateNormalizedDurationRecord(_years_, _months_, _weeks_, _days_, _norm_). - 1. Let _adjustedDateDuration_ be ? AddDuration(_years_, _months_, _weeks_, _days_, 0, 0, 0, 0, 0, 0, 0, 0, 0, _direction_, 0, 0, 0, 0, 0, 0, *undefined*, _zonedRelativeTo_, _calendarRec_, _timeZoneRec_, _precalculatedPlainDateTime_). - 1. Let _roundRecord_ be ? RoundDuration(0, 0, 0, 0, _oneDayLess_, _increment_, _unit_, _roundingMode_). - 1. Return ? CombineDateAndNormalizedTimeDuration(_adjustedDateDuration_, _roundRecord_.[[NormalizedDuration]].[[NormalizedTime]]). + 1. If _smallestUnit_ is *"year"*, return ! CombineDateAndNormalizedTimeDuration(_years_, _months_, _weeks_, _days_, _norm_). + 1. Let _largestUnitIndex_ be the ordinal index of the row of whose "Singular" column contains _largestUnit_. + 1. Let _smallestUnitIndex_ be the ordinal index of the row of whose "Singular" column contains _smallestUnit_. + 1. Let _unitIndex_ be _smallestUnitIndex_ - 1. + 1. Let _done_ be *false*. + 1. Repeat, while _unitIndex_ ≤ _largestUnitIndex_ and _done_ is *false*, + 1. Let _unit_ be the value in the "Singular" column of in the row whose ordinal index is _unitIndex_. + 1. If _unit_ is not *"week"*, or _largestUnit_ is *"week"*, then + 1. If _unit_ is *"year"*, then + 1. Let _endDuration_ be ? CreateDateDurationRecord(_years_ + _sign_, 0, 0, 0). + 1. Else if _unit_ is *"month"*, then + 1. Let _endDuration_ be ? CreateDateDurationRecord(_years_, _months_ + _sign_, 0, 0). + 1. Else if _unit_ is *"week"*, then + 1. Let _endDuration_ be ? CreateDateDurationRecord(_years_, _months_, _weeks_ + _sign_, 0). + 1. Else, + 1. Assert: _unit_ is *"day"*. + 1. Let _endDuration_ be ? CreateDateDurationRecord(_years_, _months_, _weeks_, _days_ + _sign_). + 1. Let _end_ be ? AddDateTime(_plainDateTime_.[[ISOYear]], _plainDateTime_.[[ISOMonth], _plainDateTime_.[[ISODay]], _plainDateTime_.[[ISOHour]], _plainDateTime_.[[ISOMinute]], _plainDateTime_.[[ISOSecond]], _plainDateTime_.[[ISOMillisecond]], _plainDateTime_.[[ISOMicrosecond]], _plainDateTime_.[[ISONanosecond]], _calendarRec_, _endDuration_.[[Years]], _endDuration_.[[Months]], _endDuration_.[[Weeks]], _endDuration_.[[Days]], ZeroTimeDuration(), *undefined*). + 1. If _timeZoneRec_ is ~unset~, then + 1. Let _endEpochNs_ be GetUTCEpochNanoseconds(_end_.[[Year]], _end_.[[Month]], _end_.[[Day]], _end_.[[Hour]], _end_.[[Minute]], _end_.[[Second]], _end_.[[Millisecond]], _end_.[[Microsecond]], _end_.[[Nanosecond]]). + 1. Else, + 1. Let _endDateTime_ be ! CreateTemporalDateTime(_end_.[[Year]], _end_.[[Month]], _end_.[[Day]], _end_.[[Hour]], _end_.[[Minute]], _end_.[[Second]], _end_.[[Millisecond]], _end_.[[Microsecond]], _end_.[[Nanosecond]], _calendarRec_.[[Receiver]]). + 1. Let _endInstant_ be ? GetInstantFor(_timeZoneRec_, _endDateTime_, *"compatible"*). + 1. Let _endEpochNs_ be _endInstant_.[[Nanoseconds]]. + 1. Let _beyondEnd_ be _nudgedEpochNs_ - _endEpochNs_. + 1. If _beyondEnd_ < 0, let _beyondEndSign_ be -1; else if _beyondEnd_ > 0, let _beyondEndSign_ be 1; else let _beyondEndSign_ be 0. + 1. If _beyondEndSign_ ≠ -_sign_, then + 1. Set _years_ to _endDuration_.[[Years]]. + 1. Set _months_ to _endDuration_.[[Months]]. + 1. Set _weeks_ to _endDuration_.[[Weeks]]. + 1. Set _days_ to _endDuration_.[[Days]]. + 1. Set _norm_ to ZeroTimeDuration(). + 1. Else, + 1. Set _done_ to *true*. + 1. Set _unitIndex_ to _unitIndex_ - 1. + 1. Return ! CombineDateAndNormalizedTimeDuration(_years_, _months_, _weeks_, _days_, _norm_).
diff --git a/spec/instant.html b/spec/instant.html index c8dff05ab..1bf2f8635 100644 --- a/spec/instant.html +++ b/spec/instant.html @@ -598,7 +598,7 @@

1. Let _difference_ be NormalizedTimeDurationFromEpochNanosecondsDifference(_ns2_, _ns1_). - 1. Let _roundRecord_ be ! RoundDuration(0, 0, 0, 0, _difference_, _roundingIncrement_, _smallestUnit_, _roundingMode_). + 1. Let _roundRecord_ be ! RoundDuration(0, _difference_, _roundingIncrement_, _smallestUnit_, _roundingMode_). 1. Return the Record { [[NormalizedTimeDuration]]: _roundRecord_.[[NormalizedDuration]].[[NormalizedTime]], [[Total]]: _roundRecord_.[[Total]] }. diff --git a/spec/zoneddatetime.html b/spec/zoneddatetime.html index ce39ba46e..3bcf509fc 100644 --- a/spec/zoneddatetime.html +++ b/spec/zoneddatetime.html @@ -1466,76 +1466,6 @@

- -

- NormalizedTimeDurationToDays ( - _norm_: a Normalized Time Duration Record, - _zonedRelativeTo_: a Temporal.ZonedDateTime, - _timeZoneRec_: a Time Zone Methods Record, - optional _precalculatedPlainDateTime_: a Temporal.PlainDateTime, - ): either a normal completion containing a Record with fields [[Days]] (an integer), [[Remainder]] (a Normalized Time Duration Record), and [[DayLength]] (an integer), or a throw completion -

-
-
description
-
- It converts a normalized time duration _norm_ relative to a Temporal.ZonedDateTime _zonedRelativeTo_ into a number of days and a remainder normalized time duration, taking into account any offset changes in the time zone of _zonedRelativeTo_. - It also returns the length of the last day in nanoseconds, for rounding purposes. -
-
-

Unless _nanoseconds_ = 0, _timeZoneRec_ must have looked up both `getOffsetNanosecondsFor` and `getPossibleInstantsFor`.

- - 1. Let _sign_ be NormalizedTimeDurationSign(_norm_). - 1. If _sign_ = 0, then - 1. Return the Record { [[Days]]: 0, [[Remainder]]: _norm_, [[DayLength]]: nsPerDay }. - 1. Let _startNs_ be _zonedRelativeTo_.[[Nanoseconds]]. - 1. Let _startInstant_ be ! CreateTemporalInstant(_startNs_). - 1. Let _endNs_ be ? AddInstant(_startNs_, _norm_). - 1. Let _endInstant_ be ! CreateTemporalInstant(_endNs_). - 1. If _precalculatedPlainDateTime_ is present, let _startDateTime_ be _precalculatedPlainDateTime_; else let _startDateTime_ be ? GetPlainDateTimeFor(_timeZoneRec_, _startInstant_, *"iso8601"*). - 1. Let _endDateTime_ be ? GetPlainDateTimeFor(_timeZoneRec_, _endInstant_, *"iso8601"*). - 1. Let _date1_ be ! CreateTemporalDate(_startDateTime_.[[ISOYear]], _startDateTime_.[[ISOMonth]], _startDateTime_.[[ISODay]], *"iso8601"*). - 1. Let _date2_ be ! CreateTemporalDate(_endDateTime_.[[ISOYear]], _endDateTime_.[[ISOMonth]], _endDateTime_.[[ISODay]], *"iso8601"*). - 1. Let _days_ be DaysUntil(_date1_, _date2_). - 1. Let _timeSign_ be CompareTemporalTime(_startDateTime_.[[ISOHour]], _startDateTime_.[[ISOMinute]], _startDateTime_.[[ISOSecond]], _startDateTime_.[[ISOMillisecond]], _startDateTime_.[[ISOMicrosecond]], _startDateTime_.[[ISONanosecond]], _endDateTime_.[[ISOHour]], _endDateTime_.[[ISOMinute]], _endDateTime_.[[ISOSecond]], _endDateTime_.[[ISOMillisecond]], _endDateTime_.[[ISOMicrosecond]], _endDateTime_.[[ISONanosecond]]). - 1. If _days_ > 0 and _timeSign_ > 0, then - 1. Set _days_ to _days_ - 1. - 1. Else if _days_ < 0 and _timeSign_ < 0, then - 1. Set _days_ to _days_ + 1. - 1. Let _relativeResult_ be ? AddDaysToZonedDateTime(_startInstant_, _startDateTime_, _timeZoneRec_, _zonedRelativeTo_.[[Calendar]], _days_). - 1. If _sign_ = 1, and _days_ > 0, and ℝ(_relativeResult_.[[EpochNanoseconds]]) > _endNs_, then - 1. Set _days_ to _days_ - 1. - 1. Set _relativeResult_ to ? AddDaysToZonedDateTime(_startInstant_, _startDateTime_, _timeZoneRec_, _zonedRelativeTo_.[[Calendar]], _days_). - 1. If _days_ > 0 and ℝ(_relativeResult_.[[EpochNanoseconds]]) > _endNs_, throw a *RangeError* exception. - 1. Set _norm_ to NormalizedTimeDurationFromEpochNanosecondsDifference(_endNs_, _relativeResult_.[[EpochNanoseconds]]). - 1. Let _oneDayFarther_ be ? AddDaysToZonedDateTime(_relativeResult_.[[Instant]], _relativeResult_.[[DateTime]], _timeZoneRec_, _zonedRelativeTo_.[[Calendar]], _sign_). - 1. Let _dayLengthNs_ be NormalizedTimeDurationFromEpochNanosecondsDifference(_oneDayFarther_.[[EpochNanoseconds]], _relativeResult_.[[EpochNanoseconds]]). - 1. Let _oneDayLess_ be ! SubtractNormalizedTimeDuration(_norm_, _dayLengthNs_). - 1. If NormalizedTimeDurationSign(_oneDayLess_) × _sign_ ≥ 0, then - 1. Set _norm_ to _oneDayLess_. - 1. Set _relativeResult_ to _oneDayFarther_. - 1. Set _days_ to _days_ + _sign_. - 1. Set _oneDayFarther_ to ? AddDaysToZonedDateTime(_relativeResult_.[[Instant]], _relativeResult_.[[DateTime]], _timeZoneRec_, _zonedRelativeTo_.[[Calendar]], _sign_). - 1. Set _dayLengthNs_ to NormalizedTimeDurationFromEpochNanosecondsDifference(_oneDayFarther_.[[EpochNanoseconds]], _relativeResult_.[[EpochNanoseconds]]). - 1. If NormalizedTimeDurationSign(! SubtractNormalizedTimeDuration(_norm_, _dayLengthNs_)) × _sign_ ≥ 0, then - 1. Throw a *RangeError* exception. - 1. If _days_ < 0 and _sign_ = 1, throw a *RangeError* exception. - 1. If _days_ > 0 and _sign_ = -1, throw a *RangeError* exception. - 1. If _sign_ = -1, then - 1. If NormalizedTimeDurationSign(_norm_) = 1, throw a *RangeError* exception. - 1. Else, - 1. Assert: NormalizedTimeDurationSign(_norm_) ≥ 0. - 1. Assert: CompareNormalizedTimeDuration(NormalizedTimeDurationAbs(_norm_), NormalizedTimeDurationAbs(_dayLengthNs_)) = -1. - 1. Let _dayLength_ be abs(ℝ(_dayLengthNs_.[[TotalNanoseconds]])). - 1. If _dayLength_ ≥ 253, throw a *RangeError* exception. - 1. Assert: abs(_days_) < 253 / (HoursPerDay × MinutesPerHour × SecondsPerMinute). - 1. Return the Record { - [[Days]]: _days_, - [[Remainder]]: _norm_, - [[DayLength]]: _dayLength_ - }. - -
-

DifferenceZonedDateTimeWithRounding (