mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-08 02:26:10 +00:00
LibJS: Move regulating and balancing logic into ISODateSurpasses
This is an editorial change in the Temporal proposal. See:
eddb77f
This commit is contained in:
parent
a95d3e2a5e
commit
3920194bca
Notes:
github-actions[bot]
2025-08-05 15:19:24 +00:00
Author: https://github.com/trflynn89
Commit: 3920194bca
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5721
3 changed files with 54 additions and 27 deletions
|
@ -395,8 +395,8 @@ DateDuration calendar_date_until(VM& vm, StringView calendar, ISODate one, ISODa
|
|||
if (candidate_years != 0)
|
||||
candidate_years -= sign;
|
||||
|
||||
// d.ii. Repeat, while ISODateSurpasses(sign, one.[[Year]] + candidateYears, one.[[Month]], one.[[Day]], two) is false,
|
||||
while (!iso_date_surpasses(sign, static_cast<double>(one.year) + candidate_years, one.month, one.day, two)) {
|
||||
// d.ii. Repeat, while ISODateSurpasses(sign, one, two, candidateYears, 0, 0, 0) is false,
|
||||
while (!iso_date_surpasses(vm, sign, one, two, candidate_years, 0, 0, 0)) {
|
||||
// 1. Set years to candidateYears.
|
||||
years = candidate_years;
|
||||
|
||||
|
@ -407,19 +407,13 @@ DateDuration calendar_date_until(VM& vm, StringView calendar, ISODate one, ISODa
|
|||
// f.i. Let candidateMonths be sign.
|
||||
double candidate_months = sign;
|
||||
|
||||
// f.ii. Let intermediate be BalanceISOYearMonth(one.[[Year]] + years, one.[[Month]] + candidateMonths).
|
||||
auto intermediate = balance_iso_year_month(static_cast<double>(one.year) + years, static_cast<double>(one.month) + candidate_months);
|
||||
|
||||
// f.iii. Repeat, while ISODateSurpasses(sign, intermediate.[[Year]], intermediate.[[Month]], one.[[Day]], two) is false,
|
||||
while (!iso_date_surpasses(sign, intermediate.year, intermediate.month, one.day, two)) {
|
||||
// f.ii. Repeat, while ISODateSurpasses(sign, one, two, years, candidateMonths, 0, 0) is false,
|
||||
while (!iso_date_surpasses(vm, sign, one, two, years, candidate_months, 0, 0)) {
|
||||
// 1. Set months to candidateMonths.
|
||||
months = candidate_months;
|
||||
|
||||
// 2. Set candidateMonths to candidateMonths + sign.
|
||||
candidate_months += sign;
|
||||
|
||||
// 3. Set intermediate to BalanceISOYearMonth(intermediate.[[Year]], intermediate.[[Month]] + sign).
|
||||
intermediate = balance_iso_year_month(intermediate.year, static_cast<double>(intermediate.month) + sign);
|
||||
}
|
||||
|
||||
if (largest_unit == Unit::Month) {
|
||||
|
@ -428,28 +422,24 @@ DateDuration calendar_date_until(VM& vm, StringView calendar, ISODate one, ISODa
|
|||
}
|
||||
}
|
||||
|
||||
// g. Set intermediate to BalanceISOYearMonth(one.[[Year]] + years, one.[[Month]] + months).
|
||||
auto intermediate = balance_iso_year_month(static_cast<double>(one.year) + years, static_cast<double>(one.month) + months);
|
||||
|
||||
// h. Let constrained be ! RegulateISODate(intermediate.[[Year]], intermediate.[[Month]], one.[[Day]], CONSTRAIN).
|
||||
auto constrained = MUST(regulate_iso_date(vm, intermediate.year, intermediate.month, one.day, Overflow::Constrain));
|
||||
|
||||
// i. Let weeks be 0.
|
||||
// g. Let weeks be 0.
|
||||
double weeks = 0;
|
||||
|
||||
// OPTIMIZATION: If the largestUnit is DAY, we do not want to enter an ISODateSurpasses loop. The loop would have
|
||||
// us increment the intermediate ISOYearMonth one day at time, which will take an extremely long
|
||||
// time if the difference is a large number of years. Instead, we can compute the day difference,
|
||||
// and convert to weeks if needed.
|
||||
auto year_month = balance_iso_year_month(static_cast<double>(one.year) + years, static_cast<double>(one.month) + months);
|
||||
auto regulated_date = MUST(regulate_iso_date(vm, year_month.year, year_month.month, one.day, Overflow::Constrain));
|
||||
|
||||
auto days = iso_date_to_epoch_days(two.year, two.month - 1, two.day) - iso_date_to_epoch_days(constrained.year, constrained.month - 1, constrained.day);
|
||||
auto days = iso_date_to_epoch_days(two.year, two.month - 1, two.day) - iso_date_to_epoch_days(regulated_date.year, regulated_date.month - 1, regulated_date.day);
|
||||
|
||||
if (largest_unit == Unit::Week) {
|
||||
weeks = trunc(days / 7.0);
|
||||
days = fmod(days, 7.0);
|
||||
}
|
||||
|
||||
// o. Return ! CreateDateDurationRecord(years, months, weeks, days).
|
||||
// l. Return ! CreateDateDurationRecord(years, months, weeks, days).
|
||||
return MUST(create_date_duration_record(vm, years, months, weeks, days));
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <LibJS/Runtime/Temporal/PlainDateConstructor.h>
|
||||
#include <LibJS/Runtime/Temporal/PlainDateTime.h>
|
||||
#include <LibJS/Runtime/Temporal/PlainTime.h>
|
||||
#include <LibJS/Runtime/Temporal/PlainYearMonth.h>
|
||||
#include <LibJS/Runtime/Temporal/TimeZone.h>
|
||||
#include <LibJS/Runtime/Temporal/ZonedDateTime.h>
|
||||
|
||||
|
@ -165,29 +166,65 @@ ThrowCompletionOr<GC::Ref<PlainDate>> to_temporal_date(VM& vm, Value item, Value
|
|||
return TRY(create_temporal_date(vm, iso_date, move(calendar)));
|
||||
}
|
||||
|
||||
// 3.5.5 ISODateSurpasses ( sign, y1, m1, d1, isoDate2 ), https://tc39.es/proposal-temporal/#sec-temporal-isodatesurpasses
|
||||
bool iso_date_surpasses(i8 sign, double year1, double month1, double day1, ISODate iso_date2)
|
||||
// 3.5.5 ISODateSurpasses ( sign, baseDate, isoDate2, years, months, weeks, days ), https://tc39.es/proposal-temporal/#sec-temporal-isodatesurpasses
|
||||
bool iso_date_surpasses(VM& vm, i8 sign, ISODate base_date, ISODate iso_date2, double years, double months, double weeks, double days)
|
||||
{
|
||||
// 1. If y1 ≠ isoDate2.[[Year]], then
|
||||
// 1. Let yearMonth be BalanceISOYearMonth(baseDate.[[Year]] + years, baseDate.[[Month]] + months).
|
||||
auto year_month = balance_iso_year_month(static_cast<double>(base_date.year) + years, static_cast<double>(base_date.month) + months);
|
||||
|
||||
i32 year1 = 0;
|
||||
u8 month1 = 0;
|
||||
u8 day1 = 0;
|
||||
|
||||
// 2. If weeks is not 0 or days is not 0, then
|
||||
if (weeks != 0 || days != 0) {
|
||||
// a. Let regulatedDate be ! RegulateISODate(yearMonth.[[Year]], yearMonth.[[Month]], baseDate.[[Day]], CONSTRAIN).
|
||||
auto regulated_date = MUST(regulate_iso_date(vm, year_month.year, year_month.month, base_date.day, Overflow::Constrain));
|
||||
|
||||
// b. Let balancedDate be BalanceISODate(regulatedDate.[[Year]], regulatedDate.[[Month]], regulatedDate.[[Day]] + 7 * weeks + days).
|
||||
auto balanced_date = balance_iso_date(regulated_date.year, regulated_date.month, static_cast<double>(regulated_date.day) + (7 * weeks) + days);
|
||||
|
||||
// c. Let y1 be balancedDate.[[Year]].
|
||||
year1 = balanced_date.year;
|
||||
|
||||
// d. Let m1 be balancedDate.[[Month]].
|
||||
month1 = balanced_date.month;
|
||||
|
||||
// e. Let d1 be balancedDate.[[Day]].
|
||||
day1 = balanced_date.day;
|
||||
}
|
||||
// 3. Else,
|
||||
else {
|
||||
// a. Let y1 be yearMonth.[[Year]].
|
||||
year1 = year_month.year;
|
||||
|
||||
// b. Let m1 be yearMonth.[[Month]].
|
||||
month1 = year_month.month;
|
||||
|
||||
// c. Let d1 be baseDate.[[Day]].
|
||||
day1 = base_date.day;
|
||||
}
|
||||
|
||||
// 4. If y1 ≠ isoDate2.[[Year]], then
|
||||
if (year1 != iso_date2.year) {
|
||||
// a. If sign × (y1 - isoDate2.[[Year]]) > 0, return true.
|
||||
if (sign * (year1 - iso_date2.year) > 0)
|
||||
return true;
|
||||
}
|
||||
// 2. Else if m1 ≠ isoDate2.[[Month]], then
|
||||
// 5. Else if m1 ≠ isoDate2.[[Month]], then
|
||||
else if (month1 != iso_date2.month) {
|
||||
// a. If sign × (m1 - isoDate2.[[Month]]) > 0, return true.
|
||||
if (sign * (month1 - iso_date2.month) > 0)
|
||||
return true;
|
||||
}
|
||||
// 3. Else if d1 ≠ isoDate2.[[Day]], then
|
||||
// 6. Else if d1 ≠ isoDate2.[[Day]], then
|
||||
else if (day1 != iso_date2.day) {
|
||||
// a. If sign × (d1 - isoDate2.[[Day]]) > 0, return true.
|
||||
if (sign * (day1 - iso_date2.day) > 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
// 4. Return false.
|
||||
// 7. Return false.
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
|
||||
* Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
|
||||
* Copyright (c) 2024, Shannon Booth <shannon@serenityos.org>
|
||||
* Copyright (c) 2024, Tim Flynn <trflynn89@ladybird.org>
|
||||
* Copyright (c) 2024-2025, Tim Flynn <trflynn89@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -37,7 +37,7 @@ private:
|
|||
ISODate create_iso_date_record(double year, double month, double day);
|
||||
ThrowCompletionOr<GC::Ref<PlainDate>> to_temporal_date(VM& vm, Value item, Value options = js_undefined());
|
||||
ThrowCompletionOr<GC::Ref<PlainDate>> create_temporal_date(VM&, ISODate, String calendar, GC::Ptr<FunctionObject> new_target = {});
|
||||
bool iso_date_surpasses(i8 sign, double year1, double month1, double day1, ISODate iso_date2);
|
||||
bool iso_date_surpasses(VM&, i8 sign, ISODate base_date, ISODate iso_date2, double years, double months, double weeks, double days);
|
||||
ThrowCompletionOr<ISODate> regulate_iso_date(VM& vm, double year, double month, double day, Overflow overflow);
|
||||
bool is_valid_iso_date(double year, double month, double day);
|
||||
ISODate balance_iso_date(double year, double month, double day);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue