Skip to content

Commit

Permalink
Introduce abstract operation TotalDurationNanoseconds
Browse files Browse the repository at this point in the history
This operation gives the total number of nanoseconds in an exact
duration as a bigint, not losing precision. This will be reused in
Duration.compare().

This operation takes an "offset shift" parameter, used if there are days
that need to be balanced down to hours. If it's 0 (as is the case
everywhere in this commit) then days are always 24 hours. We will start
using nonzero values for this in Duration.compare().

See: #856
  • Loading branch information
ptomato committed Nov 10, 2020
1 parent bf1b944 commit 1654b43
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 6 deletions.
19 changes: 16 additions & 3 deletions polyfill/lib/ecmascript.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1481,7 +1481,7 @@ export const ES = ObjectAssign({}, ES2020, {
if (minutes) timeParts.push(`${formatNumber(Math.abs(minutes))}M`);

const secondParts = [];
let total = bigInt(seconds).times(1000).plus(ms).times(1000).plus(µs).times(1000).plus(ns);
let total = ES.TotalDurationNanoseconds(0, 0, 0, seconds, ms, µs, ns, 0);
({ quotient: total, remainder: ns } = total.divmod(1000));
({ quotient: total, remainder: µs } = total.divmod(1000));
({ quotient: seconds, remainder: ms } = total.divmod(1000));
Expand Down Expand Up @@ -1872,13 +1872,26 @@ export const ES = ObjectAssign({}, ES2020, {
}
return { year, month, years, months };
},
BalanceDuration: (days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, largestUnit) => {
TotalDurationNanoseconds: (days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, offsetShift) => {
if (days !== 0) nanoseconds = bigInt(nanoseconds).subtract(offsetShift);
hours = bigInt(hours).add(bigInt(days).multiply(24));
minutes = bigInt(minutes).add(hours.multiply(60));
seconds = bigInt(seconds).add(minutes.multiply(60));
milliseconds = bigInt(milliseconds).add(seconds.multiply(1000));
microseconds = bigInt(microseconds).add(milliseconds.multiply(1000));
nanoseconds = bigInt(nanoseconds).add(microseconds.multiply(1000));
return bigInt(nanoseconds).add(microseconds.multiply(1000));
},
BalanceDuration: (days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds, largestUnit) => {
nanoseconds = ES.TotalDurationNanoseconds(
days,
hours,
minutes,
seconds,
milliseconds,
microseconds,
nanoseconds,
0
);
const sign = nanoseconds.lesser(0) ? -1 : 1;
nanoseconds = nanoseconds.abs();
microseconds = milliseconds = seconds = minutes = hours = days = bigInt.zero;
Expand Down
18 changes: 15 additions & 3 deletions spec/duration.html
Original file line number Diff line number Diff line change
Expand Up @@ -817,15 +817,27 @@ <h1>CreateTemporalDurationFromStatic ( _constructor_, _years_, _months_, _weeks_
</emu-alg>
</emu-clause>

<emu-clause id="sec-temporal-balanceduration" aoid="BalanceDuration">
<h1>BalanceDuration ( _days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_, _largestUnit_ )</h1>
<emu-clause id="sec-temporal-totaldurationnanoseconds" aoid="TotalDurationNanoseconds">
<h1>TotalDurationNanoseconds ( _days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_, _offsetShift_ )</h1>
<p>
The abstract operation TotalDurationNanoseconds computes a mathematical value number of nanoseconds from the given units, applying a given time zone offset shift in nanoseconds when converting from days to hours.
</p>
<emu-alg>
1. If _days_ ≠ 0, then
1. Set _nanoseconds_ to ℝ(_nanoseconds_) − ℝ(_offsetShift_).
1. Set _hours_ to ℝ(_hours_) + ℝ(_days_) × 24.
1. Set _minutes_ to ℝ(_minutes_) + _hours_ × 60.
1. Set _seconds_ to ℝ(_seconds_) + _minutes_ × 60.
1. Set _milliseconds_ to ℝ(_milliseconds_) + _seconds_ × 1000.
1. Set _microseconds_ to ℝ(_microseconds_) + _milliseconds_ × 1000.
1. Set _nanoseconds_ to ℝ(_nanoseconds_) + _microseconds_ × 1000.
1. Return ℝ(_nanoseconds_) + _microseconds_ × 1000.
</emu-alg>
</emu-clause>

<emu-clause id="sec-temporal-balanceduration" aoid="BalanceDuration">
<h1>BalanceDuration ( _days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_, _largestUnit_ )</h1>
<emu-alg>
1. Set _nanoseconds_ to ! TotalDurationNanoseconds(_days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_, 0).
1. Set _days_, _hours_, _minutes_, _seconds_, _milliseconds_, and _microseconds_ to 0.
1. If _nanoseconds_ &lt; 0, let _sign_ be −1; else, let _sign_ be 1.
1. Set _nanoseconds_ to abs(_nanoseconds_).
Expand Down

0 comments on commit 1654b43

Please sign in to comment.