LibJS: Add and use a BigInt-aware override of BalanceTime
With Temporal.PlainTime, we will need precise results for extremely large values.
This commit is contained in:
parent
7f3de3be9c
commit
971f794127
Notes:
github-actions[bot]
2024-11-24 00:38:09 +00:00
Author: https://github.com/trflynn89 Commit: https://github.com/LadybirdBrowser/ladybird/commit/971f794127c Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2535
2 changed files with 59 additions and 1 deletions
|
@ -15,6 +15,20 @@
|
|||
|
||||
namespace JS::Temporal {
|
||||
|
||||
// FIXME: We should add a generic floor() method to our BigInt classes. But for now, since we know we are only dividing
|
||||
// by powers of 10, we can implement a very situationally specific method to compute the floor of a division.
|
||||
static TimeDuration big_floor(TimeDuration const& numerator, Crypto::UnsignedBigInteger const& denominator)
|
||||
{
|
||||
auto result = numerator.divided_by(denominator);
|
||||
|
||||
if (result.remainder.is_zero())
|
||||
return result.quotient;
|
||||
if (!result.quotient.is_negative() && result.remainder.is_positive())
|
||||
return result.quotient;
|
||||
|
||||
return result.quotient.minus(TimeDuration { 1 });
|
||||
}
|
||||
|
||||
// 4.5.2 CreateTimeRecord ( hour, minute, second, millisecond, microsecond, nanosecond [ , deltaDays ] ), https://tc39.es/proposal-temporal/#sec-temporal-createtimerecord
|
||||
Time create_time_record(double hour, double minute, double second, double millisecond, double microsecond, double nanosecond, double delta_days)
|
||||
{
|
||||
|
@ -205,6 +219,49 @@ Time balance_time(double hour, double minute, double second, double millisecond,
|
|||
return create_time_record(hour, minute, second, millisecond, microsecond, nanosecond, delta_days);
|
||||
}
|
||||
|
||||
// 4.5.10 BalanceTime ( hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/proposal-temporal/#sec-temporal-balancetime
|
||||
Time balance_time(double hour, double minute, double second, double millisecond, double microsecond, TimeDuration const& nanosecond_value)
|
||||
{
|
||||
// 1. Set microsecond to microsecond + floor(nanosecond / 1000).
|
||||
auto microsecond_value = TimeDuration { microsecond }.plus(big_floor(nanosecond_value, NANOSECONDS_PER_MICROSECOND));
|
||||
|
||||
// 2. Set nanosecond to nanosecond modulo 1000.
|
||||
auto nanosecond = modulo(nanosecond_value, NANOSECONDS_PER_MICROSECOND).to_double();
|
||||
|
||||
// 3. Set millisecond to millisecond + floor(microsecond / 1000).
|
||||
auto millisecond_value = TimeDuration { millisecond }.plus(big_floor(microsecond_value, MICROSECONDS_PER_MILLISECOND));
|
||||
|
||||
// 4. Set microsecond to microsecond modulo 1000.
|
||||
microsecond = modulo(microsecond_value, MICROSECONDS_PER_MILLISECOND).to_double();
|
||||
|
||||
// 5. Set second to second + floor(millisecond / 1000).
|
||||
auto second_value = TimeDuration { second }.plus(big_floor(millisecond_value, MILLISECONDS_PER_SECOND));
|
||||
|
||||
// 6. Set millisecond to millisecond modulo 1000.
|
||||
millisecond = modulo(millisecond_value, MILLISECONDS_PER_SECOND).to_double();
|
||||
|
||||
// 7. Set minute to minute + floor(second / 60).
|
||||
auto minute_value = TimeDuration { minute }.plus(big_floor(second_value, SECONDS_PER_MINUTE));
|
||||
|
||||
// 8. Set second to second modulo 60.
|
||||
second = modulo(second_value, SECONDS_PER_MINUTE).to_double();
|
||||
|
||||
// 9. Set hour to hour + floor(minute / 60).
|
||||
auto hour_value = TimeDuration { hour }.plus(big_floor(minute_value, MINUTES_PER_HOUR));
|
||||
|
||||
// 10. Set minute to minute modulo 60.
|
||||
minute = modulo(minute_value, MINUTES_PER_HOUR).to_double();
|
||||
|
||||
// 11. Let deltaDays be floor(hour / 24).
|
||||
auto delta_days = big_floor(hour_value, HOURS_PER_DAY).to_double();
|
||||
|
||||
// 12. Set hour to hour modulo 24.
|
||||
hour = modulo(hour_value, HOURS_PER_DAY).to_double();
|
||||
|
||||
// 13. Return CreateTimeRecord(hour, minute, second, millisecond, microsecond, nanosecond, deltaDays).
|
||||
return create_time_record(hour, minute, second, millisecond, microsecond, nanosecond, delta_days);
|
||||
}
|
||||
|
||||
// 4.5.14 CompareTimeRecord ( time1, time2 ), https://tc39.es/proposal-temporal/#sec-temporal-comparetimerecord
|
||||
i8 compare_time_record(Time const& time1, Time const& time2)
|
||||
{
|
||||
|
@ -260,7 +317,7 @@ Time add_time(Time const& time, TimeDuration const& time_duration)
|
|||
auto nanoseconds = time_duration.plus(TimeDuration { static_cast<i64>(time.nanosecond) });
|
||||
|
||||
// 1. Return BalanceTime(time.[[Hour]], time.[[Minute]], time.[[Second]], time.[[Millisecond]], time.[[Microsecond]], time.[[Nanosecond]] + timeDuration).
|
||||
return balance_time(time.hour, time.minute, time.second, time.millisecond, time.microsecond, nanoseconds.to_double());
|
||||
return balance_time(time.hour, time.minute, time.second, time.millisecond, time.microsecond, nanoseconds);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ TimeDuration difference_time(Time const&, Time const&);
|
|||
ThrowCompletionOr<Time> regulate_time(VM&, double hour, double minute, double second, double millisecond, double microsecond, double nanosecond, Overflow);
|
||||
bool is_valid_time(double hour, double minute, double second, double millisecond, double microsecond, double nanosecond);
|
||||
Time balance_time(double hour, double minute, double second, double millisecond, double microsecond, double nanosecond);
|
||||
Time balance_time(double hour, double minute, double second, double millisecond, double microsecond, TimeDuration const& nanosecond);
|
||||
i8 compare_time_record(Time const&, Time const&);
|
||||
Time add_time(Time const&, TimeDuration const& time_duration);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue