mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 05:47:34 +00:00
LibJS: Implement Temporal.PlainTime.prototype.toZonedDateTime()
This commit is contained in:
parent
070f056926
commit
330ac1e5ad
3 changed files with 109 additions and 0 deletions
|
@ -9,10 +9,13 @@
|
|||
#include <LibJS/Runtime/GlobalObject.h>
|
||||
#include <LibJS/Runtime/Temporal/Calendar.h>
|
||||
#include <LibJS/Runtime/Temporal/Duration.h>
|
||||
#include <LibJS/Runtime/Temporal/Instant.h>
|
||||
#include <LibJS/Runtime/Temporal/PlainDate.h>
|
||||
#include <LibJS/Runtime/Temporal/PlainDateTime.h>
|
||||
#include <LibJS/Runtime/Temporal/PlainTime.h>
|
||||
#include <LibJS/Runtime/Temporal/PlainTimePrototype.h>
|
||||
#include <LibJS/Runtime/Temporal/TimeZone.h>
|
||||
#include <LibJS/Runtime/Temporal/ZonedDateTime.h>
|
||||
|
||||
namespace JS::Temporal {
|
||||
|
||||
|
@ -45,6 +48,7 @@ void PlainTimePrototype::initialize(GlobalObject& global_object)
|
|||
define_native_function(vm.names.with, with, 1, attr);
|
||||
define_native_function(vm.names.equals, equals, 1, attr);
|
||||
define_native_function(vm.names.toPlainDateTime, to_plain_date_time, 1, attr);
|
||||
define_native_function(vm.names.toZonedDateTime, to_zoned_date_time, 1, attr);
|
||||
define_native_function(vm.names.getISOFields, get_iso_fields, 0, attr);
|
||||
define_native_function(vm.names.toString, to_string, 0, attr);
|
||||
define_native_function(vm.names.toLocaleString, to_locale_string, 0, attr);
|
||||
|
@ -315,6 +319,55 @@ JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::to_plain_date_time)
|
|||
return TRY(create_temporal_date_time(global_object, temporal_date->iso_year(), temporal_date->iso_month(), temporal_date->iso_day(), temporal_time->iso_hour(), temporal_time->iso_minute(), temporal_time->iso_second(), temporal_time->iso_millisecond(), temporal_time->iso_microsecond(), temporal_time->iso_nanosecond(), temporal_date->calendar()));
|
||||
}
|
||||
|
||||
// 4.3.18 Temporal.PlainTime.prototype.toZonedDateTime ( item ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.tozoneddatetime
|
||||
JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::to_zoned_date_time)
|
||||
{
|
||||
auto item = vm.argument(0);
|
||||
|
||||
// 1. Let temporalTime be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(temporalTime, [[InitializedTemporalTime]]).
|
||||
auto* temporal_time = TRY(typed_this_object(global_object));
|
||||
|
||||
// 3. If Type(item) is not Object, then
|
||||
if (!item.is_object()) {
|
||||
// a. Throw a TypeError exception.
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::NotAnObject, item);
|
||||
}
|
||||
|
||||
// 4. Let temporalDateLike be ? Get(item, "plainDate").
|
||||
auto temporal_date_like = TRY(item.as_object().get(vm.names.plainDate));
|
||||
|
||||
// 5. If temporalDateLike is undefined, then
|
||||
if (temporal_date_like.is_undefined()) {
|
||||
// a. Throw a TypeError exception.
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::MissingRequiredProperty, vm.names.plainDate.as_string());
|
||||
}
|
||||
|
||||
// 6. Let temporalDate be ? ToTemporalDate(temporalDateLike).
|
||||
auto* temporal_date = TRY(to_temporal_date(global_object, temporal_date_like));
|
||||
|
||||
// 7. Let temporalTimeZoneLike be ? Get(item, "timeZone").
|
||||
auto temporal_time_zone_like = TRY(item.as_object().get(vm.names.timeZone));
|
||||
|
||||
// 8. If temporalTimeZoneLike is undefined, then
|
||||
if (temporal_time_zone_like.is_undefined()) {
|
||||
// a. Throw a TypeError exception.
|
||||
return vm.throw_completion<TypeError>(global_object, ErrorType::MissingRequiredProperty, vm.names.timeZone.as_string());
|
||||
}
|
||||
|
||||
// 9. Let timeZone be ? ToTemporalTimeZone(temporalTimeZoneLike).
|
||||
auto* time_zone = TRY(to_temporal_time_zone(global_object, temporal_time_zone_like));
|
||||
|
||||
// 10. Let temporalDateTime be ? CreateTemporalDateTime(temporalDate.[[ISOYear]], temporalDate.[[ISOMonth]], temporalDate.[[ISODay]], temporalTime.[[ISOHour]], temporalTime.[[ISOMinute]], temporalTime.[[ISOSecond]], temporalTime.[[ISOMillisecond]], temporalTime.[[ISOMicrosecond]], temporalTime.[[ISONanosecond]], temporalDate.[[Calendar]]).
|
||||
auto* temporal_date_time = TRY(create_temporal_date_time(global_object, temporal_date->iso_year(), temporal_date->iso_month(), temporal_date->iso_day(), temporal_time->iso_hour(), temporal_time->iso_minute(), temporal_time->iso_second(), temporal_time->iso_millisecond(), temporal_time->iso_microsecond(), temporal_time->iso_nanosecond(), temporal_date->calendar()));
|
||||
|
||||
// 11. Let instant be ? BuiltinTimeZoneGetInstantFor(timeZone, temporalDateTime, "compatible").
|
||||
auto* instant = TRY(builtin_time_zone_get_instant_for(global_object, time_zone, *temporal_date_time, "compatible"sv));
|
||||
|
||||
// 12. Return ! CreateTemporalZonedDateTime(instant.[[Nanoseconds]], timeZone, temporalDate.[[Calendar]]).
|
||||
return MUST(create_temporal_zoned_date_time(global_object, instant->nanoseconds(), *time_zone, temporal_date->calendar()));
|
||||
}
|
||||
|
||||
// 4.3.19 Temporal.PlainTime.prototype.getISOFields ( ), https://tc39.es/proposal-temporal/#sec-temporal.plaintime.prototype.getisofields
|
||||
JS_DEFINE_NATIVE_FUNCTION(PlainTimePrototype::get_iso_fields)
|
||||
{
|
||||
|
|
|
@ -32,6 +32,7 @@ private:
|
|||
JS_DECLARE_NATIVE_FUNCTION(with);
|
||||
JS_DECLARE_NATIVE_FUNCTION(equals);
|
||||
JS_DECLARE_NATIVE_FUNCTION(to_plain_date_time);
|
||||
JS_DECLARE_NATIVE_FUNCTION(to_zoned_date_time);
|
||||
JS_DECLARE_NATIVE_FUNCTION(get_iso_fields);
|
||||
JS_DECLARE_NATIVE_FUNCTION(to_string);
|
||||
JS_DECLARE_NATIVE_FUNCTION(to_locale_string);
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.PlainTime.prototype.toZonedDateTime).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const plainTime = new Temporal.PlainTime(18, 14, 47, 123, 456, 789);
|
||||
const plainDate = new Temporal.PlainDate(2021, 7, 6);
|
||||
const timeZone = new Temporal.TimeZone("UTC");
|
||||
const zonedDateTime = plainTime.toZonedDateTime({ plainDate, 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(plainDate.calendar);
|
||||
expect(zonedDateTime.timeZone).toBe(timeZone);
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.PlainTime object", () => {
|
||||
expect(() => {
|
||||
Temporal.PlainTime.prototype.toZonedDateTime.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.PlainTime");
|
||||
});
|
||||
|
||||
test("item argument must be an object", () => {
|
||||
const plainTime = new Temporal.PlainTime();
|
||||
for (const value of [123, NaN, Infinity, true, false, null, undefined]) {
|
||||
expect(() => {
|
||||
plainTime.toZonedDateTime(value);
|
||||
}).toThrowWithMessage(TypeError, `${value} is not an object`);
|
||||
}
|
||||
});
|
||||
|
||||
test("item argument must have a 'plainDate' property", () => {
|
||||
const plainTime = new Temporal.PlainTime();
|
||||
expect(() => {
|
||||
plainTime.toZonedDateTime({});
|
||||
}).toThrowWithMessage(TypeError, "Required property plainDate is missing or undefined");
|
||||
});
|
||||
|
||||
test("item argument must have a 'timeZone' property", () => {
|
||||
const plainDate = new Temporal.PlainDate(1970, 1, 1);
|
||||
const plainTime = new Temporal.PlainTime();
|
||||
expect(() => {
|
||||
plainTime.toZonedDateTime({ plainDate });
|
||||
}).toThrowWithMessage(TypeError, "Required property timeZone is missing or undefined");
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue