From eaa3329573b9f19dbb4388ec79005bb625a5f69e Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Wed, 17 Nov 2021 22:31:28 +0000 Subject: [PATCH] LibJS: Fix incorrect use of "modulo" in get_iso_parts_from_epoch() This would return incorrect results for negative inputs. It still does to some extent, remainder() in step 2 might need to be replaced with modulo (I opened an issue in tc39/proposal-temporal about that). --- Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp index 2d67431569..fdeba4807f 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp @@ -118,11 +118,11 @@ ISODateTime get_iso_parts_from_epoch(BigInt const& epoch_nanoseconds) // 2. Let remainderNs be remainder(epochNanoseconds, 10^6). auto remainder_ns_bigint = epoch_nanoseconds.big_integer().divided_by(Crypto::UnsignedBigInteger { 1'000'000 }).remainder; - auto remainder_ns = remainder_ns_bigint.to_base(10).to_int().value(); + auto remainder_ns = remainder_ns_bigint.to_double(); // 3. Let epochMilliseconds be (epochNanoseconds − remainderNs) / 10^6. auto epoch_milliseconds_bigint = epoch_nanoseconds.big_integer().minus(remainder_ns_bigint).divided_by(Crypto::UnsignedBigInteger { 1'000'000 }).quotient; - auto epoch_milliseconds = (double)epoch_milliseconds_bigint.to_base(10).to_int().value(); + auto epoch_milliseconds = epoch_milliseconds_bigint.to_double(); // 4. Let year be ! YearFromTime(epochMilliseconds). auto year = year_from_time(epoch_milliseconds); @@ -146,13 +146,13 @@ ISODateTime get_iso_parts_from_epoch(BigInt const& epoch_nanoseconds) auto millisecond = ms_from_time(epoch_milliseconds); // 11. Let microsecond be floor(remainderNs / 1000) modulo 1000. - auto microsecond = static_cast((remainder_ns / 1000) % 1000); + auto microsecond = modulo(floor(remainder_ns / 1000), 1000.0); // 12. Let nanosecond be remainderNs modulo 1000. - auto nanosecond = static_cast(remainder_ns % 1000); + auto nanosecond = modulo(remainder_ns, 1000.0); // 13. Return the Record { [[Year]]: year, [[Month]]: month, [[Day]]: day, [[Hour]]: hour, [[Minute]]: minute, [[Second]]: second, [[Millisecond]]: millisecond, [[Microsecond]]: microsecond, [[Nanosecond]]: nanosecond }. - return { .year = year, .month = month, .day = day, .hour = hour, .minute = minute, .second = second, .millisecond = millisecond, .microsecond = microsecond, .nanosecond = nanosecond }; + return { .year = year, .month = month, .day = day, .hour = hour, .minute = minute, .second = second, .millisecond = millisecond, .microsecond = static_cast(microsecond), .nanosecond = static_cast(nanosecond) }; } // 11.6.4 GetIANATimeZoneEpochValue ( timeZoneIdentifier, year, month, day, hour, minute, second, millisecond, microsecond, nanosecond ), https://tc39.es/proposal-temporal/#sec-temporal-getianatimezoneepochvalue