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: Change TimeDuration to use time durations instead of internal durations #3026

Merged
merged 2 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions polyfill/lib/duration.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
SetSlot,
TIME_ZONE
} from './slots.mjs';
import { TimeDuration } from './timeduration.mjs';

export class Duration {
constructor(
Expand Down Expand Up @@ -282,9 +283,20 @@ export class Duration {
throw new RangeErrorCtor(`a starting point is required for ${largestUnit}s balancing`);
}
assert(!ES.IsCalendarUnit(smallestUnit), 'smallestUnit was larger than largestUnit');
let duration = ES.ToInternalDurationRecordWith24HourDays(this);
duration = ES.RoundTimeDuration(duration, roundingIncrement, smallestUnit, roundingMode);
return ES.TemporalDurationFromInternal(duration, largestUnit);
let internalDuration = ES.ToInternalDurationRecordWith24HourDays(this);
if (smallestUnit === 'day') {
// First convert time units up to days
const DAY_NANOS = 86400 * 1e9;
const { quotient, remainder } = internalDuration.time.divmod(DAY_NANOS);
let days = internalDuration.date.days + quotient + remainder.fdiv(DAY_NANOS);
days = ES.RoundNumberToIncrement(days, roundingIncrement, roundingMode);
const dateDuration = { years: 0, months: 0, weeks: 0, days };
internalDuration = ES.CombineDateAndTimeDuration(dateDuration, TimeDuration.ZERO);
} else {
const timeDuration = ES.RoundTimeDuration(internalDuration.time, roundingIncrement, smallestUnit, roundingMode);
internalDuration = ES.CombineDateAndTimeDuration(ES.ZeroDateDuration(), timeDuration);
}
return ES.TemporalDurationFromInternal(internalDuration, largestUnit);
}
total(totalOf) {
if (!ES.IsTemporalDuration(this)) throw new TypeErrorCtor('invalid receiver');
Expand Down Expand Up @@ -349,10 +361,11 @@ export class Duration {
if (unit === 'nanosecond' && increment === 1) return ES.TemporalDurationToString(this, precision);

const largestUnit = ES.DefaultTemporalLargestUnit(this);
let duration = ES.ToInternalDurationRecord(this);
duration = ES.RoundTimeDuration(duration, increment, unit, roundingMode);
let internalDuration = ES.ToInternalDurationRecord(this);
const timeDuration = ES.RoundTimeDuration(internalDuration.time, increment, unit, roundingMode);
internalDuration = ES.CombineDateAndTimeDuration(internalDuration.date, timeDuration);
const roundedDuration = ES.TemporalDurationFromInternal(
duration,
internalDuration,
ES.LargerOfTwoTemporalUnits(largestUnit, 'second')
);
return ES.TemporalDurationToString(roundedDuration, precision);
Expand Down
36 changes: 15 additions & 21 deletions polyfill/lib/ecmascript.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -778,7 +778,7 @@ export function AdjustDateDurationRecord({ years, months, weeks, days }, newDays
};
}

function ZeroDateDuration() {
export function ZeroDateDuration() {
return { years: 0, months: 0, weeks: 0, days: 0 };
}

Expand Down Expand Up @@ -2952,7 +2952,7 @@ export function TemporalDurationFromInternal(internalDuration, largestUnit) {
);
}

function CombineDateAndTimeDuration(dateDuration, timeDuration) {
export function CombineDateAndTimeDuration(dateDuration, timeDuration) {
const dateSign = DateDurationSign(dateDuration);
const timeSign = timeDuration.sign();
if (dateSign !== 0 && timeSign !== 0 && dateSign !== timeSign) {
Expand Down Expand Up @@ -2994,8 +2994,9 @@ function DifferenceTime(time1, time2) {
}

function DifferenceInstant(ns1, ns2, increment, smallestUnit, roundingMode) {
const diff = { date: ZeroDateDuration(), time: TimeDuration.fromEpochNsDiff(ns2, ns1) };
return RoundTimeDuration(diff, increment, smallestUnit, roundingMode);
let timeDuration = TimeDuration.fromEpochNsDiff(ns2, ns1);
timeDuration = RoundTimeDuration(timeDuration, increment, smallestUnit, roundingMode);
return CombineDateAndTimeDuration(ZeroDateDuration(), timeDuration);
}

function DifferenceISODateTime(isoDateTime1, isoDateTime2, calendar, largestUnit) {
Expand Down Expand Up @@ -3691,10 +3692,13 @@ export function DifferenceTemporalPlainTime(operation, plainTime, other, options
const settings = GetDifferenceSettings(operation, resolvedOptions, 'time', [], 'nanosecond', 'hour');

let timeDuration = DifferenceTime(GetSlot(plainTime, TIME), GetSlot(other, TIME));
let duration = { date: ZeroDateDuration(), time: timeDuration };
if (settings.smallestUnit !== 'nanosecond' || settings.roundingIncrement !== 1) {
duration = RoundTimeDuration(duration, settings.roundingIncrement, settings.smallestUnit, settings.roundingMode);
}
timeDuration = RoundTimeDuration(
timeDuration,
settings.roundingIncrement,
settings.smallestUnit,
settings.roundingMode
);
const duration = CombineDateAndTimeDuration(ZeroDateDuration(), timeDuration);

let result = TemporalDurationFromInternal(duration, settings.largestUnit);
if (operation === 'since') result = CreateNegatedTemporalDuration(result);
Expand Down Expand Up @@ -4060,20 +4064,10 @@ export function RoundTime(
}
}

export function RoundTimeDuration(duration, increment, unit, roundingMode) {
// unit must not be a calendar unit
if (unit === 'day') {
// First convert time units up to days
const { quotient, remainder } = duration.time.divmod(DAY_NANOS);
let days = duration.date.days + quotient + remainder.fdiv(DAY_NANOS);
days = RoundNumberToIncrement(days, increment, roundingMode);
const dateDuration = AdjustDateDurationRecord(duration.date, days);
return CombineDateAndTimeDuration(dateDuration, TimeDuration.ZERO);
}

export function RoundTimeDuration(timeDuration, increment, unit, roundingMode) {
// unit must be a time unit
const divisor = Call(MapPrototypeGet, NS_PER_TIME_UNIT, [unit]);
const timeDuration = duration.time.round(divisor * increment, roundingMode);
return CombineDateAndTimeDuration(duration.date, timeDuration);
return timeDuration.round(divisor * increment, roundingMode);
}

export function TotalTimeDuration(timeDuration, unit) {
Expand Down
31 changes: 16 additions & 15 deletions spec/duration.html
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,14 @@ <h1>Temporal.Duration.prototype.round ( _roundTo_ )</h1>
1. If IsCalendarUnit(_existingLargestUnit_) is *true*, or IsCalendarUnit(_largestUnit_) is *true*, throw a *RangeError* exception.
1. Assert: IsCalendarUnit(_smallestUnit_) is *false*.
1. Let _internalDuration_ be ToInternalDurationRecordWith24HourDays(_duration_).
1. Set _internalDuration_ to ? RoundTimeDuration(_internalDuration_, _roundingIncrement_, _smallestUnit_, _roundingMode_).
1. If _smallestUnit_ is ~day~, then
1. Let _fractionalDays_ be DivideTimeDuration(_internalDuration_.[[Time]], nsPerDay).
1. Let _days_ be RoundNumberToIncrement(_fractionalDays_, _roundingIncrement_, _roundingMode_).
1. Let _dateDuration_ be ? CreateDateDurationRecord(0, 0, 0, _days_).
1. Set _internalDuration_ to ! CombineDateAndTimeDuration(_dateDuration_, 0).
1. Else,
1. Let _timeDuration_ be ? RoundTimeDuration(_internalDuration_.[[Time]], _roundingIncrement_, _smallestUnit_, _roundingMode_).
1. Set _internalDuration_ to ! CombineDateAndTimeDuration(ZeroDateDuration(), _timeDuration_).
1. Return ? TemporalDurationFromInternal(_internalDuration_, _largestUnit_).
</emu-alg>
</emu-clause>
Expand Down Expand Up @@ -513,9 +520,10 @@ <h1>Temporal.Duration.prototype.toString ( [ _options_ ] )</h1>
1. Return TemporalDurationToString(_duration_, _precision_.[[Precision]]).
1. Let _largestUnit_ be DefaultTemporalLargestUnit(_duration_).
1. Let _internalDuration_ be ToInternalDurationRecord(_duration_).
1. Set _internalDuration_ to ? RoundTimeDuration(_internalDuration_, _precision_.[[Increment]], _precision_.[[Unit]], _roundingMode_).
1. Let _timeDuration_ be ? RoundTimeDuration(_internalDuration_.[[Time]], _precision_.[[Increment]], _precision_.[[Unit]], _roundingMode_).
1. Set _internalDuration_ to ! CombineDateAndTimeDuration(_internalDuration_.[[Date]], _timeDuration_).
1. Let _roundedLargestUnit_ be LargerOfTwoTemporalUnits(_largestUnit_, ~second~).
1. Let _roundedDuration_ be ! TemporalDurationFromInternal(_internalDuration_, _roundedLargestUnit_).
1. Let _roundedDuration_ be ? TemporalDurationFromInternal(_internalDuration_, _roundedLargestUnit_).
1. Return TemporalDurationToString(_roundedDuration_, _precision_.[[Precision]]).
</emu-alg>
</emu-clause>
Expand Down Expand Up @@ -1500,28 +1508,21 @@ <h1>
<emu-clause id="sec-temporal-roundtimeduration" type="abstract operation">
<h1>
RoundTimeDuration (
_duration_: an Internal Duration Record,
_timeDuration_: a time duration,
_increment_: a positive integer,
_unit_: a time unit or ~day~,
_unit_: a time unit,
_roundingMode_: a rounding mode,
): either a normal completion containing an Internal Duration Record, or a throw completion
): either a normal completion containing a time duration, or a throw completion
</h1>
<dl class="header">
<dt>description</dt>
<dd>
It rounds a _duration_ according to the rounding parameters _unit_, _increment_, and _roundingMode_, and returns the Internal Duration Record result.
It rounds a _timeDuration_ according to the rounding parameters _unit_, _increment_, and _roundingMode_, and returns the time duration result.
</dd>
</dl>
<emu-alg>
1. If _unit_ is ~day~, then
1. Let _fractionalDays_ be _duration_.[[Date]].[[Days]] + DivideTimeDuration(_duration_.[[Time]], nsPerDay).
1. Let _days_ be RoundNumberToIncrement(_fractionalDays_, _increment_, _roundingMode_).
1. Let _dateDuration_ be ? AdjustDateDurationRecord(_duration_.[[Date]], _days_).
1. Return ! CombineDateAndTimeDuration(_dateDuration_, 0).
1. Assert: TemporalUnitCategory(_unit_) is ~time~.
1. Let _divisor_ be the value in the "Length in Nanoseconds" column of the row of <emu-xref href="#table-temporal-units"></emu-xref> whose "Value" column contains _unit_.
1. Let _rounded_ be ? RoundTimeDurationToIncrement(_duration_.[[Time]], _divisor_ × _increment_, _roundingMode_).
1. Return ? CombineDateAndTimeDuration(_duration_.[[Date]], _rounded_).
1. Return ? RoundTimeDurationToIncrement(_timeDuration_, _divisor_ × _increment_, _roundingMode_).
</emu-alg>
</emu-clause>

Expand Down
6 changes: 3 additions & 3 deletions spec/instant.html
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ <h1>
_ns1_: a BigInt,
_ns2_: a BigInt,
_roundingIncrement_: a positive integer,
_smallestUnit_: a time unit or ~day~,
_smallestUnit_: a time unit,
_roundingMode_: a rounding mode,
): an Internal Duration Record
</h1>
Expand All @@ -473,8 +473,8 @@ <h1>
</dl>
<emu-alg>
1. Let _timeDuration_ be TimeDurationFromEpochNanosecondsDifference(_ns2_, _ns1_).
1. Let _internalDuration_ be ! CombineDateAndTimeDuration(ZeroDateDuration(), _timeDuration_).
1. Return ! RoundTimeDuration(_internalDuration_, _roundingIncrement_, _smallestUnit_, _roundingMode_).
1. Set _timeDuration_ to ! RoundTimeDuration(_timeDuration_, _roundingIncrement_, _smallestUnit_, _roundingMode_).
1. Return ! CombineDateAndTimeDuration(ZeroDateDuration(), _timeDuration_).
</emu-alg>
</emu-clause>

Expand Down
3 changes: 1 addition & 2 deletions spec/plaintime.html
Original file line number Diff line number Diff line change
Expand Up @@ -931,9 +931,8 @@ <h1>
1. Let _resolvedOptions_ be ? GetOptionsObject(_options_).
1. Let _settings_ be ? GetDifferenceSettings(_operation_, _resolvedOptions_, ~time~, « », ~nanosecond~, ~hour~).
1. Let _timeDuration_ be DifferenceTime(_temporalTime_.[[Time]], _other_.[[Time]]).
1. Set _timeDuration_ to ! RoundTimeDuration(_timeDuration_, _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]]).
1. Let _duration_ be ! CombineDateAndTimeDuration(ZeroDateDuration(), _timeDuration_).
1. If _settings_.[[SmallestUnit]] is not ~nanosecond~ or _settings_.[[RoundingIncrement]] ≠ 1, then
1. Set _duration_ to ! RoundTimeDuration(_duration_, _settings_.[[RoundingIncrement]], _settings_.[[SmallestUnit]], _settings_.[[RoundingMode]]).
1. Let _result_ be ! TemporalDurationFromInternal(_duration_, _settings_.[[LargestUnit]]).
1. If _operation_ is ~since~, set _result_ to CreateNegatedTemporalDuration(_result_).
1. Return _result_.
Expand Down
Loading