diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTimePrototype.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTimePrototype.cpp index c4e0a1c28d..2dedbf52f4 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTimePrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTimePrototype.cpp @@ -9,10 +9,13 @@ #include #include #include +#include #include #include #include #include +#include +#include namespace JS::Temporal { @@ -61,6 +64,7 @@ void PlainDateTimePrototype::initialize(GlobalObject& global_object) define_native_function(vm.names.subtract, subtract, 1, attr); define_native_function(vm.names.equals, equals, 1, attr); define_native_function(vm.names.valueOf, value_of, 0, attr); + define_native_function(vm.names.toZonedDateTime, to_zoned_date_time, 1, attr); define_native_function(vm.names.toPlainDate, to_plain_date, 0, attr); define_native_function(vm.names.toPlainYearMonth, to_plain_year_month, 0, attr); define_native_function(vm.names.toPlainMonthDay, to_plain_month_day, 0, attr); @@ -472,6 +476,29 @@ JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::value_of) return vm.throw_completion(global_object, ErrorType::Convert, "Temporal.PlainDateTime", "a primitive value"); } +// 5.3.36 Temporal.PlainDateTime.prototype.toZonedDateTime ( temporalTimeZoneLike [ , options ] ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.tozoneddatetime +JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::to_zoned_date_time) +{ + // 1. Let dateTime be the this value. + // 2. Perform ? RequireInternalSlot(dateTime, [[InitializedTemporalDateTime]]). + auto* date_time = TRY(typed_this_object(global_object)); + + // 3. Let timeZone be ? ToTemporalTimeZone(temporalTimeZoneLike). + auto* time_zone = TRY(to_temporal_time_zone(global_object, vm.argument(0))); + + // 4. Set options to ? GetOptionsObject(options). + auto* options = TRY(get_options_object(global_object, vm.argument(1))); + + // 5. Let disambiguation be ? ToTemporalDisambiguation(options). + auto disambiguation = TRY(to_temporal_disambiguation(global_object, *options)); + + // 6. Let instant be ? BuiltinTimeZoneGetInstantFor(timeZone, dateTime, disambiguation). + auto* instant = TRY(builtin_time_zone_get_instant_for(global_object, time_zone, *date_time, disambiguation)); + + // 7. Return ! CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZone, dateTime.[[Calendar]]). + return MUST(create_temporal_zoned_date_time(global_object, instant->nanoseconds(), *time_zone, date_time->calendar())); +} + // 5.3.37 Temporal.PlainDateTime.prototype.toPlainDate ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaindatetime.prototype.toplaindate JS_DEFINE_NATIVE_FUNCTION(PlainDateTimePrototype::to_plain_date) { diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTimePrototype.h b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTimePrototype.h index 66b1827e84..238b1ba911 100644 --- a/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTimePrototype.h +++ b/Userland/Libraries/LibJS/Runtime/Temporal/PlainDateTimePrototype.h @@ -48,6 +48,7 @@ private: JS_DECLARE_NATIVE_FUNCTION(subtract); JS_DECLARE_NATIVE_FUNCTION(equals); JS_DECLARE_NATIVE_FUNCTION(value_of); + JS_DECLARE_NATIVE_FUNCTION(to_zoned_date_time); JS_DECLARE_NATIVE_FUNCTION(to_plain_date); JS_DECLARE_NATIVE_FUNCTION(to_plain_year_month); JS_DECLARE_NATIVE_FUNCTION(to_plain_month_day); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toZonedDateTime.js b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toZonedDateTime.js new file mode 100644 index 0000000000..a35ce0fbe7 --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.prototype.toZonedDateTime.js @@ -0,0 +1,30 @@ +describe("correct behavior", () => { + test("length is 1", () => { + expect(Temporal.PlainDateTime.prototype.toZonedDateTime).toHaveLength(1); + }); + + test("basic functionality", () => { + const plainDateTime = new Temporal.PlainDateTime(2021, 7, 6, 18, 14, 47, 123, 456, 789); + const timeZone = new Temporal.TimeZone("UTC"); + const zonedDateTime = plainDateTime.toZonedDateTime(timeZone); + expect(zonedDateTime.year).toBe(2021); + expect(zonedDateTime.month).toBe(7); + expect(zonedDateTime.day).toBe(6); + expect(zonedDateTime.hour).toBe(18); + expect(zonedDateTime.minute).toBe(14); + expect(zonedDateTime.second).toBe(47); + expect(zonedDateTime.millisecond).toBe(123); + expect(zonedDateTime.microsecond).toBe(456); + expect(zonedDateTime.nanosecond).toBe(789); + expect(zonedDateTime.calendar).toBe(plainDateTime.calendar); + expect(zonedDateTime.timeZone).toBe(timeZone); + }); +}); + +describe("errors", () => { + test("this value must be a Temporal.PlainDateTime object", () => { + expect(() => { + Temporal.PlainDateTime.prototype.toZonedDateTime.call("foo"); + }).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainDateTime"); + }); +});