diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDate.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDate.cpp index ea8c0272c3..32d1f85a9f 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDate.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDate.cpp @@ -1,6 +1,7 @@ /* * Copyright (c) 2021, Idan Horowitz * Copyright (c) 2021-2023, Linus Groh + * Copyright (c) 2024, Shannon Booth * * SPDX-License-Identifier: BSD-2-Clause */ @@ -380,6 +381,38 @@ bool is_valid_iso_date(i32 year, u8 month, u8 day) return true; } +// 3.5.6 DifferenceDate ( calendarRec, one, two, options ), https://tc39.es/proposal-temporal/#sec-temporal-differencedate +ThrowCompletionOr> difference_date(VM& vm, Object const& calendar, PlainDate const& one, PlainDate const& two, Object const& options) +{ + // FIXME: 1. Assert: one.[[Calendar]] and two.[[Calendar]] have been determined to be equivalent as with CalendarEquals. + // FIXME: 2. Assert: options is an ordinary Object. + + // 3. Assert: options.[[Prototype]] is null. + VERIFY(!options.prototype()); + + // 4. Assert: options has a "largestUnit" data property. + VERIFY(MUST(options.has_own_property(vm.names.largestUnit))); + + // 5. If one.[[ISOYear]] = two.[[ISOYear]] and one.[[ISOMonth]] = two.[[ISOMonth]] and one.[[ISODay]] = two.[[ISODay]], then + if (one.iso_year() == two.iso_year() && one.iso_month() == two.iso_month() && one.iso_day() == two.iso_day()) { + // a. Return ! CreateTemporalDuration(0, 0, 0, 0, 0, 0, 0, 0, 0, 0). + return *MUST(create_temporal_duration(vm, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)); + } + + // 6. If ! Get(options, "largestUnit") is "day", then + auto largest_unit = MUST(options.get(vm.names.largestUnit)); + if (largest_unit.is_string() && largest_unit.as_string().utf8_string_view() == "day"sv) { + // a. Let days be DaysUntil(one, two). + auto days = days_until(one, two); + + // b. Return ! CreateTemporalDuration(0, 0, 0, days, 0, 0, 0, 0, 0, 0). + return *MUST(create_temporal_duration(vm, 0, 0, 0, days, 0, 0, 0, 0, 0, 0)); + } + + // 7. Return ? CalendarDateUntil(calendarRec, one, two, options). + return *TRY(calendar_date_until(vm, calendar, Value { &one }, Value { &two }, options)); +} + // 3.5.6 BalanceISODate ( year, month, day ), https://tc39.es/proposal-temporal/#sec-temporal-balanceisodate ISODateRecord balance_iso_date(double year, double month, double day) { diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDate.h b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDate.h index ee545c662f..44e8866778 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDate.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDate.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2021, Idan Horowitz * Copyright (c) 2021-2023, Linus Groh + * Copyright (c) 2024, Shannon Booth * * SPDX-License-Identifier: BSD-2-Clause */ @@ -58,5 +59,6 @@ ThrowCompletionOr temporal_date_to_string(VM&, PlainDate&, StringView sh ThrowCompletionOr add_iso_date(VM&, i32 year, u8 month, u8 day, double years, double months, double weeks, double days, StringView overflow); i8 compare_iso_date(i32 year1, u8 month1, u8 day1, i32 year2, u8 month2, u8 day2); ThrowCompletionOr difference_temporal_plain_date(VM&, DifferenceOperation, PlainDate&, Value other, Value options); +ThrowCompletionOr> difference_date(VM& vm, Object const& calendar, PlainDate const& one, PlainDate const& two, Object const& options); }