-
Notifications
You must be signed in to change notification settings - Fork 159
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
Total methods for Duration? #584
Comments
From #730:
|
This is going to land with #856, not a dedicated "total" method, but: totalSeconds = duration.round({ largestUnit: 'seconds', smallestUnit: 'seconds' }).seconds; Can we close this? |
Meeting, Sept. 18: We will close this. |
Meeting 2020-10-09: We'll add a Caveat: our assumption is that implementing this will be straightforward on top of the work we've already done for Proposed behavior:
|
Here's a prototype userland implementation of The algorithm:
Steps 6-9 should be reworked after function total(duration, options) {
let { unit, relativeTo } = options;
const base = duration.round({ smallestUnit: unit, largestUnit: unit, roundingMode: 'trunc', relativeTo });
if (unit === 'nanoseconds') return base.nanoseconds;
const roundingMode = duration.sign < 0 ? 'floor' : 'ceil'; // TODO: replace with away-from-zero rounding mode
const away = duration.round({ smallestUnit: unit, largestUnit: unit, roundingMode, relativeTo });
if (base[unit] === away[unit]) return base[unit]; // No rounding means no remainder. Return the integer.
// If only time units, any DateTime is OK. Invalid options are caught by .round() above.
if (!relativeTo) relativeTo = new Temporal.DateTime(1970, 1, 1);
relativeTo = Temporal.DateTime.from(relativeTo);
// Calculate remainder, using diff of round-towards-zero and round-away-from-zero as denominator.
const plusBase = relativeTo.add(base);
const plusAway = relativeTo.add(away);
const denominator = plusAway.since(plusBase, { largestUnit: 'nanoseconds' });
const remainderDuration = relativeTo.add(duration).since(plusBase, { largestUnit: 'nanoseconds' });
const remainder = duration.sign * (remainderDuration.nanoseconds / denominator.nanoseconds);
return base[unit] + remainder;
} |
I commented on #998, but no need to wait for the changes to the rounding algorithm, as it should only affect this in edge cases. At first glance this looks correct for a userland implementation, though in the polyfill we should not use |
I thought the same thing. But the current Or can you see a way to simplify so that fewer operations would be needed for |
I believe the final two (BalanceDurationRelative and BalanceDuration) are not needed for total(). If you first balance down from the original duration so that all units above largestUnit are 0, then do everything in RoundDuration except actually round the fractional number, then I think you have the correct answer already. |
So |
That's correct. |
Unfortunately it seems to affect more than edge cases. I've implemented |
OK, I'll prioritize that one for today. |
While researching #558, I found that .NET's
Temporal.Duration
(calledTimeSpan
) has nice "total" methods, e.g.TotalMilliseconds
,TotalHours
.The value returned is a floating point number to capture fractional smaller units.
Should Temporal offer something similar? Per #559 it probably would be best to limit these to hours/minutes/seconds/etc. to avoid DST issues with
days
.I know that
largestUnit
serves this purpose in Temporal today and is helpful for cases where you want multiple units (e.g. 2 days and 10 hours). But IMHO thoseTotalXXX
methods seem like a nice way to handle the single-unit case with better ergonomics and better discoverability via IDE autocomplete, compared tolargestUnit
which is buried in an optional parameter.The text was updated successfully, but these errors were encountered: