diff --git a/Libraries/LibJS/Runtime/Temporal/Instant.cpp b/Libraries/LibJS/Runtime/Temporal/Instant.cpp index 037de6d9c2b..cd0a7e3be09 100644 --- a/Libraries/LibJS/Runtime/Temporal/Instant.cpp +++ b/Libraries/LibJS/Runtime/Temporal/Instant.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -101,11 +102,11 @@ ThrowCompletionOr> to_temporal_instant(VM& vm, Value item) auto const& object = item.as_object(); // a. If item has an [[InitializedTemporalInstant]] or [[InitializedTemporalZonedDateTime]] internal slot, then - // FIXME: Handle ZonedDateTime. - if (is(object)) { - // i. Return ! CreateTemporalInstant(item.[[EpochNanoseconds]]). + // i. Return ! CreateTemporalInstant(item.[[EpochNanoseconds]]). + if (is(object)) return MUST(create_temporal_instant(vm, static_cast(object).epoch_nanoseconds())); - } + if (is(object)) + return MUST(create_temporal_instant(vm, static_cast(object).epoch_nanoseconds())); // b. NOTE: This use of ToPrimitive allows Instant-like objects to be converted. // c. Set item to ? ToPrimitive(item, STRING). diff --git a/Libraries/LibJS/Runtime/Temporal/PlainDate.cpp b/Libraries/LibJS/Runtime/Temporal/PlainDate.cpp index f93324dfcd4..b88e549d701 100644 --- a/Libraries/LibJS/Runtime/Temporal/PlainDate.cpp +++ b/Libraries/LibJS/Runtime/Temporal/PlainDate.cpp @@ -16,6 +16,8 @@ #include #include #include +#include +#include namespace JS::Temporal { @@ -84,11 +86,22 @@ ThrowCompletionOr> to_temporal_date(VM& vm, Value item, Value return MUST(create_temporal_date(vm, plain_date.iso_date(), plain_date.calendar())); } - // FIXME: b. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then - // FIXME: i. Let isoDateTime be GetISODateTimeFor(item.[[TimeZone]], item.[[EpochNanoseconds]]). - // FIXME: ii. Let resolvedOptions be ? GetOptionsObject(options). - // FIXME: iii. Perform ? GetTemporalOverflowOption(resolvedOptions). - // FIXME: iv. Return ! CreateTemporalDate(isoDateTime.[[ISODate]], item.[[Calendar]]). + // b. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then + if (is(object)) { + auto const& zoned_date_time = static_cast(object); + + // i. Let isoDateTime be GetISODateTimeFor(item.[[TimeZone]], item.[[EpochNanoseconds]]). + auto iso_date_time = get_iso_date_time_for(zoned_date_time.time_zone(), zoned_date_time.epoch_nanoseconds()->big_integer()); + + // ii. Let resolvedOptions be ? GetOptionsObject(options). + auto resolved_options = TRY(get_options_object(vm, options)); + + // iii. Perform ? GetTemporalOverflowOption(resolvedOptions). + TRY(get_temporal_overflow_option(vm, resolved_options)); + + // iv. Return ! CreateTemporalDate(isoDateTime.[[ISODate]], item.[[Calendar]]). + return MUST(create_temporal_date(vm, iso_date_time.iso_date, zoned_date_time.calendar())); + } // c. If item has an [[InitializedTemporalDateTime]] internal slot, then if (is(object)) { diff --git a/Libraries/LibJS/Runtime/Temporal/PlainDateTime.cpp b/Libraries/LibJS/Runtime/Temporal/PlainDateTime.cpp index f268cd52932..69b2478a76c 100644 --- a/Libraries/LibJS/Runtime/Temporal/PlainDateTime.cpp +++ b/Libraries/LibJS/Runtime/Temporal/PlainDateTime.cpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include namespace JS::Temporal { @@ -102,11 +104,22 @@ ThrowCompletionOr> to_temporal_date_time(VM& vm, Value it return MUST(create_temporal_date_time(vm, plain_date_time.iso_date_time(), plain_date_time.calendar())); } - // FIXME: b. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then - // FIXME: i. Let isoDateTime be GetISODateTimeFor(item.[[TimeZone]], item.[[EpochNanoseconds]]). - // FIXME: ii. Let resolvedOptions be ? GetOptionsObject(options). - // FIXME: iii. Perform ? GetTemporalOverflowOption(resolvedOptions). - // FIXME: iv. Return ! CreateTemporalDateTime(isoDateTime, item.[[Calendar]]). + // b. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then + if (is(object)) { + auto const& zoned_date_time = static_cast(object); + + // i. Let isoDateTime be GetISODateTimeFor(item.[[TimeZone]], item.[[EpochNanoseconds]]). + auto iso_date_time = get_iso_date_time_for(zoned_date_time.time_zone(), zoned_date_time.epoch_nanoseconds()->big_integer()); + + // ii. Let resolvedOptions be ? GetOptionsObject(options). + auto resolved_options = TRY(get_options_object(vm, options)); + + // iii. Perform ? GetTemporalOverflowOption(resolvedOptions). + TRY(get_temporal_overflow_option(vm, resolved_options)); + + // iv. Return ! CreateTemporalDateTime(isoDateTime, item.[[Calendar]]). + return MUST(create_temporal_date_time(vm, iso_date_time, zoned_date_time.calendar())); + } // c. If item has an [[InitializedTemporalDate]] internal slot, then if (is(object)) { diff --git a/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp b/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp index c0b7feb25a6..49ebf815d42 100644 --- a/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp +++ b/Libraries/LibJS/Runtime/Temporal/PlainTime.cpp @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include namespace JS::Temporal { @@ -129,11 +131,22 @@ ThrowCompletionOr> to_temporal_time(VM& vm, Value item, Value return MUST(create_temporal_time(vm, plain_date_time.iso_date_time().time)); } - // FIXME: c. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then - // FIXME: i. Let isoDateTime be GetISODateTimeFor(item.[[TimeZone]], item.[[EpochNanoseconds]]). - // FIXME: ii. Let resolvedOptions be ? GetOptionsObject(options). - // FIXME: iii. Perform ? GetTemporalOverflowOption(resolvedOptions). - // FIXME: iv. Return ! CreateTemporalTime(isoDateTime.[[Time]]). + // c. If item has an [[InitializedTemporalZonedDateTime]] internal slot, then + if (is(object)) { + auto const& zoned_date_time = static_cast(object); + + // i. Let isoDateTime be GetISODateTimeFor(item.[[TimeZone]], item.[[EpochNanoseconds]]). + auto iso_date_time = get_iso_date_time_for(zoned_date_time.time_zone(), zoned_date_time.epoch_nanoseconds()->big_integer()); + + // ii. Let resolvedOptions be ? GetOptionsObject(options). + auto resolved_options = TRY(get_options_object(vm, options)); + + // iii. Perform ? GetTemporalOverflowOption(resolvedOptions). + TRY(get_temporal_overflow_option(vm, resolved_options)); + + // iv. Return ! CreateTemporalTime(isoDateTime.[[Time]]). + return MUST(create_temporal_time(vm, iso_date_time.time)); + } // d. Let result be ? ToTemporalTimeRecord(item). auto result = TRY(to_temporal_time_record(vm, object)); diff --git a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.from.js b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.from.js index f2bd3d1d239..a7ec6f51ced 100644 --- a/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.from.js +++ b/Libraries/LibJS/Tests/builtins/Temporal/Instant/Instant.from.js @@ -34,6 +34,11 @@ describe("correct behavior", () => { expect(result).toBeInstanceOf(Temporal.Instant); expect(result.epochNanoseconds).toBe(0n); }); + + test("ZonedDateTime instance argument", () => { + const zonedDateTime = new Temporal.ZonedDateTime(123n, "UTC"); + expect(Temporal.Instant.from(zonedDateTime).epochNanoseconds).toBe(123n); + }); }); describe("errors", () => { diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.from.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.from.js index abb79f6538c..9b1c90969ed 100644 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.from.js +++ b/Libraries/LibJS/Tests/builtins/Temporal/PlainDate/PlainDate.from.js @@ -17,6 +17,14 @@ describe("correct behavior", () => { expect(createdPlainDate.month).toBe(7); expect(createdPlainDate.day).toBe(26); }); + + test("ZonedDateTime instance argument", () => { + const zonedDateTime = new Temporal.ZonedDateTime(1627318123456789000n, "UTC"); + const createdPlainDate = Temporal.PlainDate.from(zonedDateTime); + expect(createdPlainDate.year).toBe(2021); + expect(createdPlainDate.month).toBe(7); + expect(createdPlainDate.day).toBe(26); + }); }); describe("errors", () => { diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.from.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.from.js index f7740a45db9..8712a6bc264 100644 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.from.js +++ b/Libraries/LibJS/Tests/builtins/Temporal/PlainDateTime/PlainDateTime.from.js @@ -32,6 +32,20 @@ describe("correct behavior", () => { expect(plainDateTime.nanosecond).toBe(0); }); + test("ZonedDateTime instance argument", () => { + const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, "UTC"); + const plainDateTime = Temporal.PlainDateTime.from(zonedDateTime); + expect(plainDateTime.year).toBe(2021); + expect(plainDateTime.month).toBe(7); + expect(plainDateTime.day).toBe(6); + expect(plainDateTime.hour).toBe(23); + expect(plainDateTime.minute).toBe(42); + expect(plainDateTime.second).toBe(1); + expect(plainDateTime.millisecond).toBe(0); + expect(plainDateTime.microsecond).toBe(0); + expect(plainDateTime.nanosecond).toBe(0); + }); + test("fields object argument", () => { const object = { year: 2021, diff --git a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.from.js b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.from.js index 5a12ace646d..1c2b5b97a80 100644 --- a/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.from.js +++ b/Libraries/LibJS/Tests/builtins/Temporal/PlainTime/PlainTime.from.js @@ -23,6 +23,17 @@ describe("correct behavior", () => { expect(createdPlainTime.microsecond).toBe(0); expect(createdPlainTime.nanosecond).toBe(0); }); + + test("ZonedDateTime instance argument", () => { + const zonedDateTime = new Temporal.ZonedDateTime(1627318123456789000n, "UTC"); + const createdPlainTime = Temporal.PlainTime.from(zonedDateTime); + expect(createdPlainTime.hour).toBe(16); + expect(createdPlainTime.minute).toBe(48); + expect(createdPlainTime.second).toBe(43); + expect(createdPlainTime.millisecond).toBe(456); + expect(createdPlainTime.microsecond).toBe(789); + expect(createdPlainTime.nanosecond).toBe(0); + }); }); describe("errors", () => {