Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Editorial: Refactor common alg of since/until into AOs #2167

Merged
merged 13 commits into from
May 6, 2022
65 changes: 39 additions & 26 deletions spec/instant.html
Original file line number Diff line number Diff line change
Expand Up @@ -256,19 +256,7 @@ <h1>Temporal.Instant.prototype.until ( _other_ [ , _options_ ] )</h1>
<emu-alg>
1. Let _instant_ be the *this* value.
1. Perform ? RequireInternalSlot(_instant_, [[InitializedTemporalInstant]]).
1. Set _other_ to ? ToTemporalInstant(_other_).
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_options_, « *"year"*, *"month"*, *"week"*, *"day"* », *"nanosecond"*).
1. Let _defaultLargestUnit_ be ! LargerOfTwoTemporalUnits(*"second"*, _smallestUnit_).
1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, « *"year"*, *"month"*, *"week"*, *"day"* », *"auto"*, _defaultLargestUnit_).
1. Perform ? ValidateTemporalUnitRange(_largestUnit_, _smallestUnit_).
1. Let _roundingMode_ be ? ToTemporalRoundingMode(_options_, *"trunc"*).
1. Let _maximum_ be ! MaximumTemporalDurationRoundingIncrement(_smallestUnit_).
1. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
1. Let _roundedNs_ be ! DifferenceInstant(_instant_.[[Nanoseconds]], _other_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_).
1. Assert: The following steps cannot fail due to overflow in the Number domain because abs(_roundedNs_) &le; 1.728 &times; 10<sup>22</sup>.
1. Let _result_ be ! BalanceDuration(0, 0, 0, 0, 0, 0, _roundedNs_, _largestUnit_).
1. Return ! CreateTemporalDuration(0, 0, 0, 0, _result_.[[Hours]], _result_.[[Minutes]], _result_.[[Seconds]], _result_.[[Milliseconds]], _result_.[[Microseconds]], _result_.[[Nanoseconds]]).
1. Return ? DifferenceTemporalInstant(~until~, _instant_, _other_, _options_).
</emu-alg>
</emu-clause>

Expand All @@ -281,19 +269,7 @@ <h1>Temporal.Instant.prototype.since ( _other_ [ , _options_ ] )</h1>
<emu-alg>
1. Let _instant_ be the *this* value.
1. Perform ? RequireInternalSlot(_instant_, [[InitializedTemporalInstant]]).
1. Set _other_ to ? ToTemporalInstant(_other_).
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_options_, « *"year"*, *"month"*, *"week"*, *"day"* », *"nanosecond"*).
1. Let _defaultLargestUnit_ be ! LargerOfTwoTemporalUnits(*"second"*, _smallestUnit_).
1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, « *"year"*, *"month"*, *"week"*, *"day"* », *"auto"*, _defaultLargestUnit_).
1. Perform ? ValidateTemporalUnitRange(_largestUnit_, _smallestUnit_).
1. Let _roundingMode_ be ? ToTemporalRoundingMode(_options_, *"trunc"*).
1. Let _maximum_ be ! MaximumTemporalDurationRoundingIncrement(_smallestUnit_).
1. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
1. Let _roundedNs_ be ! DifferenceInstant(_other_.[[Nanoseconds]], _instant_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_).
1. Assert: The following steps cannot fail due to overflow in the Number domain because abs(_roundedNs_) &le; 1.728 &times; 10<sup>22</sup>.
1. Let _result_ be ! BalanceDuration(0, 0, 0, 0, 0, 0, _roundedNs_, _largestUnit_).
1. Return ! CreateTemporalDuration(0, 0, 0, 0, _result_.[[Hours]], _result_.[[Minutes]], _result_.[[Seconds]], _result_.[[Milliseconds]], _result_.[[Microseconds]], _result_.[[Nanoseconds]]).
1. Return ? DifferenceTemporalInstant(~since~, _instant_, _other_, _options_).
</emu-alg>
</emu-clause>

Expand Down Expand Up @@ -647,5 +623,42 @@ <h1>TemporalInstantToString ( _instant_, _timeZone_, _precision_ )</h1>
1. Return the string-concatenation of _dateTimeString_ and _timeZoneString_.
</emu-alg>
</emu-clause>
<emu-clause id="sec-temporal-differencetemporalinstant" type="abstract operation">
<h1>
DifferenceTemporalInstant (
ptomato marked this conversation as resolved.
Show resolved Hide resolved
_operation_: ~since~ or ~until~,
_instant_: a Temporal.Instant,
_other_: an ECMAScript language value,
_options_: an ECMAScript language value,
): either a normal completion containing a Temporal.Duration or an abrupt completion
</h1>
<dl class="header">
<dt>description</dt>
<dd>It computes the difference between the two times represented by _instant_ and _other_, optionally rounds it, and returns it as a Temporal.Duration object.</dd>
</dl>
<emu-alg>
1. Set _other_ to ? ToTemporalInstant(_other_).
1. If _operation_ is ~until~, then,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, can we use the same logic for until vs. since handling that's used in all other AOs (especially DifferenceTemporalPlainTime whose behavior should be almost identical to this one except for overflow handling) ?

Specifically, removing this swapping of _other_ and _instant_ and then using logic like we use elsewhere. Like this:

1. If _operation_ is ~since~, let _sign_ be -1. Otherwise, let _sign_ be 1.

then...

        1. If _operation_ is ~since~, then
          1. Set _roundingMode_ to ! NegateTemporalRoundingMode(_roundingMode_).

and finally:

1. Let _result_ be ! BalanceDuration(0, 0, 0, 0, 0, 0, `sign` × _roundedNs_, _largestUnit_).

If there's a perf or other reason that this AO should use the swapping logic, then why doesn't DifferenceTemporalPlainTime have the same optimization?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What you are asking is not a refactoring of the current logic, but rather a different math. I am not opposing to do that but I lack of confidence to that kind of change. Just look at the current spec:
https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.since
https://tc39.es/proposal-temporal/#sec-temporal.instant.prototype.round

I simply copy the alg there and factor out. What you suggest is way more complicated than that and I do not feel I have the time to ensure such change is correct.

I am also trubled by the "consistency" ideology. "consistency" will need to end somewhere while the two different type are differeent. It is not avoidable some "consistency" will be broken to deal with type specific issue. WHER the "consistency" should end is the question and I feel we push too deep on this. I think "consistency" should be kept on public API level and someone want it to be in the AO function level. But inside alg of AO? I think that simply go too far.

How about we first land this AO with if/swap . And if you or anyone feel comfortable of changing that logic w/o introduce error (which I do not feel confident) than you can do that later in a separate editorial PR.

1. Let _first_ be _instant_.
1. Let _second_ be _other__.
FrankYFTang marked this conversation as resolved.
Show resolved Hide resolved
else.
FrankYFTang marked this conversation as resolved.
Show resolved Hide resolved
1. Let _first_ be _other_.
1. Let _second_ be _instant__.
FrankYFTang marked this conversation as resolved.
Show resolved Hide resolved
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_options_, « *"year"*, *"month"*, *"week"*, *"day"* », *"nanosecond"*).
1. Let _defaultLargestUnit_ be ! LargerOfTwoTemporalUnits(*"second"*, _smallestUnit_).
1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, « *"year"*, *"month"*, *"week"*, *"day"* », *"auto"*, _defaultLargestUnit_).
1. Perform ? ValidateTemporalUnitRange(_largestUnit_, _smallestUnit_).
1. Let _roundingMode_ be ? ToTemporalRoundingMode(_options_, *"trunc"*).
1. Let _maximum_ be ! MaximumTemporalDurationRoundingIncrement(_smallestUnit_).
ptomato marked this conversation as resolved.
Show resolved Hide resolved
1. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, _maximum_, *false*).
1. Let _roundedNs_ be ! DifferenceInstant(_first_.[[Nanoseconds]], _second_.[[Nanoseconds]], _roundingIncrement_, _smallestUnit_, _roundingMode_).
1. Assert: The following steps cannot fail due to overflow in the Number domain because abs(_roundedNs_) &le; 1.728 &times; 10<sup>22</sup>.
1. Let _result_ be ! BalanceDuration(0, 0, 0, 0, 0, 0, _roundedNs_, _largestUnit_).
1. Return ! CreateTemporalDuration(0, 0, 0, 0, _result_.[[Hours]], _result_.[[Minutes]], _result_.[[Seconds]], _result_.[[Milliseconds]], _result_.[[Microseconds]], _result_.[[Nanoseconds]]).
</emu-alg>
</emu-clause>
</emu-alg>
</emu-clause>
ptomato marked this conversation as resolved.
Show resolved Hide resolved
</emu-clause>
</emu-clause>
68 changes: 37 additions & 31 deletions spec/plaindate.html
Original file line number Diff line number Diff line change
Expand Up @@ -415,21 +415,7 @@ <h1>Temporal.PlainDate.prototype.until ( _other_ [ , _options_ ] )</h1>
<emu-alg>
1. Let _temporalDate_ be the *this* value.
1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
1. Set _other_ to ? ToTemporalDate(_other_).
1. If ? CalendarEquals(_temporalDate_.[[Calendar]], _other_.[[Calendar]]) is *false*, throw a *RangeError* exception.
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _disallowedUnits_ be « *"hour"*, *"minute"*, *"second"*, *"millisecond"*, *"microsecond"*, *"nanosecond"* ».
1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_options_, _disallowedUnits_, *"day"*).
1. Let _defaultLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _smallestUnit_).
1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, _disallowedUnits_, *"auto"*, _defaultLargestUnit_).
1. Perform ? ValidateTemporalUnitRange(_largestUnit_, _smallestUnit_).
1. Let _roundingMode_ be ? ToTemporalRoundingMode(_options_, *"trunc"*).
1. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*).
1. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _largestUnit_).
1. Let _result_ be ? CalendarDateUntil(_temporalDate_.[[Calendar]], _temporalDate_, _other_, _untilOptions_).
1. If _smallestUnit_ is not *"day"* or _roundingIncrement_ &ne; 1, then
1. Set _result_ to (? RoundDuration(_result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _result_.[[Days]], 0, 0, 0, 0, 0, 0, _roundingIncrement_, _smallestUnit_, _roundingMode_, _temporalDate_)).[[DurationRecord]].
1. Return ! CreateTemporalDuration(_result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _result_.[[Days]], 0, 0, 0, 0, 0, 0).
1. Return ? DifferenceTemporalPlainDate(~until~, _temporalDate_, _other_, _options_).
</emu-alg>
</emu-clause>

Expand All @@ -442,22 +428,7 @@ <h1>Temporal.PlainDate.prototype.since ( _other_ [ , _options_ ] )</h1>
<emu-alg>
1. Let _temporalDate_ be the *this* value.
1. Perform ? RequireInternalSlot(_temporalDate_, [[InitializedTemporalDate]]).
1. Set _other_ to ? ToTemporalDate(_other_).
1. If ? CalendarEquals(_temporalDate_.[[Calendar]], _other_.[[Calendar]]) is *false*, throw a *RangeError* exception.
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _disallowedUnits_ be « *"hour"*, *"minute"*, *"second"*, *"millisecond"*, *"microsecond"*, *"nanosecond"* ».
1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_options_, _disallowedUnits_, *"day"*).
1. Let _defaultLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _smallestUnit_).
1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, _disallowedUnits_, *"auto"*, _defaultLargestUnit_).
1. Perform ? ValidateTemporalUnitRange(_largestUnit_, _smallestUnit_).
1. Let _roundingMode_ be ? ToTemporalRoundingMode(_options_, *"trunc"*).
1. Set _roundingMode_ to ! NegateTemporalRoundingMode(_roundingMode_).
1. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*).
1. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _largestUnit_).
1. Let _result_ be ? CalendarDateUntil(_temporalDate_.[[Calendar]], _temporalDate_, _other_, _untilOptions_).
1. If _smallestUnit_ is not *"day"* or _roundingIncrement_ &ne; 1, then
1. Set _result_ to (? RoundDuration(_result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _result_.[[Days]], 0, 0, 0, 0, 0, 0, _roundingIncrement_, _smallestUnit_, _roundingMode_, _temporalDate_)).[[DurationRecord]].
1. Return ! CreateTemporalDuration(-_result_.[[Years]], -_result_.[[Months]], -_result_.[[Weeks]], -_result_.[[Days]], 0, 0, 0, 0, 0, 0).
1. Return ? DifferenceTemporalPlainDate(~since~, _temporalDate_, _other_, _options_).
</emu-alg>
</emu-clause>

Expand Down Expand Up @@ -921,6 +892,41 @@ <h1>CompareISODate ( _y1_, _m1_, _d1_, _y2_, _m2_, _d2_ )</h1>
1. If _d1_ &lt; _d2_, return -1.
1. Return 0.
</emu-alg>
</emu-clause>
<emu-clause id="sec-temporal-differencetemporalplaindate" type="abstract operation">
<h1>
DifferenceTemporalPlainDate (
_operation_: ~since~ or ~until~,
_temporalDate_: a Temporal.PlainDate,
_other_: an ECMAScript language value,
_options_: an ECMAScript language value,
): either a normal completion containing a Temporal.Duration or an abrupt completion
</h1>
<dl class="header">
<dt>description</dt>
<dd>It computes the difference between the two times represented by _temporalDate_ and _other_, optionally rounds it, and returns it as a Temporal.Duration object.</dd>
</dl>
</h1>
ptomato marked this conversation as resolved.
Show resolved Hide resolved
<emu-alg>
1. If _operation_ is ~since~, let _sign_ be -1. Otherwise, let _sign_ be 1.
1. Set _other_ to ? ToTemporalDate(_other_).
1. If ? CalendarEquals(_temporalDate_.[[Calendar]], _other_.[[Calendar]]) is *false*, throw a *RangeError* exception.
1. Set _options_ to ? GetOptionsObject(_options_).
1. Let _disallowedUnits_ be « *"hour"*, *"minute"*, *"second"*, *"millisecond"*, *"microsecond"*, *"nanosecond"* ».
1. Let _smallestUnit_ be ? ToSmallestTemporalUnit(_options_, _disallowedUnits_, *"day"*).
1. Let _defaultLargestUnit_ be ! LargerOfTwoTemporalUnits(*"day"*, _smallestUnit_).
1. Let _largestUnit_ be ? ToLargestTemporalUnit(_options_, _disallowedUnits_, *"auto"*, _defaultLargestUnit_).
1. Perform ? ValidateTemporalUnitRange(_largestUnit_, _smallestUnit_).
1. Let _roundingMode_ be ? ToTemporalRoundingMode(_options_, *"trunc"*).
1. If _operation_ is ~since~, then
1. Set _roundingMode_ to ! NegateTemporalRoundingMode(_roundingMode_).
1. Let _roundingIncrement_ be ? ToTemporalRoundingIncrement(_options_, *undefined*, *false*).
1. Let _untilOptions_ be ? MergeLargestUnitOption(_options_, _largestUnit_).
1. Let _result_ be ? CalendarDateUntil(_temporalDate_.[[Calendar]], _temporalDate_, _other_, _untilOptions_).
1. If _smallestUnit_ is not *"day"* or _roundingIncrement_ &ne; 1, then
1. Set _result_ to (? RoundDuration(_result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _result_.[[Days]], 0, 0, 0, 0, 0, 0, _roundingIncrement_, _smallestUnit_, _roundingMode_, _temporalDate_)).[[DurationRecord]].
1. Return ! CreateTemporalDuration(_sign_ &times; _result_.[[Years]], _sign_ &times; _result_.[[Months]], _sign_ &times; _result_.[[Weeks]], _sign_ &times; _result_.[[Days]], 0, 0, 0, 0, 0, 0).
</emu-alg>
</emu-clause>
</emu-clause>
</emu-clause>
Loading