diff --git a/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.cpp b/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.cpp index e9e3d9b665d..10a3ce9cea2 100644 --- a/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.cpp +++ b/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.cpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include namespace JS::Temporal { @@ -48,6 +50,8 @@ void PlainDatePrototype::initialize(Realm& realm) define_native_accessor(realm, vm.names.inLeapYear, in_leap_year_getter, {}, Attribute::Configurable); u8 attr = Attribute::Writable | Attribute::Configurable; + define_native_function(realm, vm.names.toPlainYearMonth, to_plain_year_month, 0, attr); + define_native_function(realm, vm.names.toPlainMonthDay, to_plain_month_day, 0, attr); define_native_function(realm, vm.names.add, add, 1, attr); define_native_function(realm, vm.names.subtract, subtract, 1, attr); define_native_function(realm, vm.names.with, with, 1, attr); @@ -188,6 +192,46 @@ JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::year_of_week_getter) return *result; } +// 3.3.19 Temporal.PlainDate.prototype.toPlainYearMonth ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.toplainyearmonth +JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::to_plain_year_month) +{ + // 1. Let temporalDate be the this value. + // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). + auto temporal_date = TRY(typed_this_object(vm)); + + // 3. Let calendar be temporalDate.[[Calendar]]. + auto const& calendar = temporal_date->calendar(); + + // 4. Let fields be ISODateToFields(calendar, temporalDate.[[ISODate]], DATE). + auto fields = iso_date_to_fields(calendar, temporal_date->iso_date(), DateType::Date); + + // 5. Let isoDate be ? CalendarYearMonthFromFields(calendar, fields, CONSTRAIN). + auto iso_date = TRY(calendar_year_month_from_fields(vm, calendar, move(fields), Overflow::Constrain)); + + // 6. Return ! CreateTemporalYearMonth(isoDate, calendar). + return MUST(create_temporal_year_month(vm, iso_date, calendar)); +} + +// 3.3.20 Temporal.PlainDate.prototype.toPlainMonthDay ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.toplainmonthday +JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::to_plain_month_day) +{ + // 1. Let temporalDate be the this value. + // 2. Perform ? RequireInternalSlot(temporalDate, [[InitializedTemporalDate]]). + auto temporal_date = TRY(typed_this_object(vm)); + + // 3. Let calendar be temporalDate.[[Calendar]]. + auto const& calendar = temporal_date->calendar(); + + // 4. Let fields be ISODateToFields(calendar, temporalDate.[[ISODate]], DATE). + auto fields = iso_date_to_fields(calendar, temporal_date->iso_date(), DateType::Date); + + // 5. Let isoDate be ? CalendarMonthDayFromFields(calendar, fields, CONSTRAIN). + auto iso_date = TRY(calendar_month_day_from_fields(vm, calendar, move(fields), Overflow::Constrain)); + + // 6. Return ! CreateTemporalMonthDay(isoDate, calendar). + return MUST(create_temporal_month_day(vm, iso_date, calendar)); +} + // 3.3.21 Temporal.PlainDate.prototype.add ( temporalDurationLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindate.prototype.add JS_DEFINE_NATIVE_FUNCTION(PlainDatePrototype::add) { diff --git a/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.h b/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.h index 0badab53a16..21ac80246cc 100644 --- a/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.h +++ b/Libraries/LibJS/Runtime/Temporal/PlainDatePrototype.h @@ -38,6 +38,8 @@ private: JS_DECLARE_NATIVE_FUNCTION(days_in_month_getter); JS_DECLARE_NATIVE_FUNCTION(days_in_year_getter); JS_DECLARE_NATIVE_FUNCTION(months_in_year_getter); + JS_DECLARE_NATIVE_FUNCTION(to_plain_year_month); + JS_DECLARE_NATIVE_FUNCTION(to_plain_month_day); JS_DECLARE_NATIVE_FUNCTION(in_leap_year_getter); JS_DECLARE_NATIVE_FUNCTION(add); JS_DECLARE_NATIVE_FUNCTION(subtract); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toPlainMonthDay.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toPlainMonthDay.js new file mode 100644 index 00000000000..3df9a14c238 --- /dev/null +++ b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toPlainMonthDay.js @@ -0,0 +1,17 @@ +describe("correct behavior", () => { + test("length is 0", () => { + expect(Temporal.PlainDate.prototype.toPlainMonthDay).toHaveLength(0); + }); + + test("basic functionality", () => { + const plainDate = new Temporal.PlainDate(2021, 7, 6); + const plainMonthDay = plainDate.toPlainMonthDay(); + expect(plainMonthDay.calendar).toBe(plainDate.calendar); + expect(plainMonthDay.monthCode).toBe("M07"); + expect(plainMonthDay.day).toBe(6); + + const fields = plainMonthDay.toString({ calendarName: "always" }); + const year = fields.split("-")[0]; + expect(year).toBe("1972"); + }); +}); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toPlainYearMonth.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toPlainYearMonth.js new file mode 100644 index 00000000000..c3a100c125e --- /dev/null +++ b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.prototype.toPlainYearMonth.js @@ -0,0 +1,13 @@ +describe("correct behavior", () => { + test("length is 0", () => { + expect(Temporal.PlainDate.prototype.toPlainYearMonth).toHaveLength(0); + }); + + test("basic functionality", () => { + const plainDate = new Temporal.PlainDate(2021, 7, 6); + const plainYearMonth = plainDate.toPlainYearMonth(); + expect(plainYearMonth.calendar).toBe(plainDate.calendar); + expect(plainYearMonth.year).toBe(2021); + expect(plainYearMonth.month).toBe(7); + }); +});