LibJS: Implement Temporal.ZonedDateTime.prototype.to*

Includes:

Temporal.ZonedDateTime.prototype.toInstant
Temporal.ZonedDateTime.prototype.toPlainDate
Temporal.ZonedDateTime.prototype.toPlainTime
Temporal.ZonedDateTime.prototype.toPlainDateTime
This commit is contained in:
Timothy Flynn
2024-11-25 13:59:13 -05:00
committed by Andreas Kling
parent b95528d7b5
commit 58828ffd62
Notes: github-actions[bot] 2024-11-26 10:03:04 +00:00
6 changed files with 156 additions and 0 deletions

View File

@@ -81,6 +81,10 @@ void ZonedDateTimePrototype::initialize(Realm& realm)
define_native_function(realm, vm.names.valueOf, value_of, 0, attr);
define_native_function(realm, vm.names.startOfDay, start_of_day, 0, attr);
define_native_function(realm, vm.names.getTimeZoneTransition, get_time_zone_transition, 1, attr);
define_native_function(realm, vm.names.toInstant, to_instant, 0, attr);
define_native_function(realm, vm.names.toPlainDate, to_plain_date, 0, attr);
define_native_function(realm, vm.names.toPlainTime, to_plain_time, 0, attr);
define_native_function(realm, vm.names.toPlainDateTime, to_plain_date_time, 0, attr);
}
// 6.3.3 get Temporal.ZonedDateTime.prototype.calendarId, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.calendarid
@@ -901,4 +905,57 @@ JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::get_time_zone_transition)
return MUST(create_temporal_zoned_date_time(vm, BigInt::create(vm, transition.release_value()), time_zone, zoned_date_time->calendar()));
}
// 6.3.47 Temporal.ZonedDateTime.prototype.toInstant ( ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.toinstant
JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::to_instant)
{
// 1. Let zonedDateTime be the this value.
// 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
auto zoned_date_time = TRY(typed_this_object(vm));
// 3. Return ! CreateTemporalInstant(zonedDateTime.[[EpochNanoseconds]]).
return MUST(create_temporal_instant(vm, zoned_date_time->epoch_nanoseconds()));
}
// 6.3.48 Temporal.ZonedDateTime.prototype.toPlainDate ( ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.toplaindate
JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::to_plain_date)
{
// 1. Let zonedDateTime be the this value.
// 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
auto zoned_date_time = TRY(typed_this_object(vm));
// 3. Let isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
auto iso_date_time = get_iso_date_time_for(zoned_date_time->time_zone(), zoned_date_time->epoch_nanoseconds()->big_integer());
// 4. Return ! CreateTemporalDate(isoDateTime.[[ISODate]], zonedDateTime.[[Calendar]].).
return MUST(create_temporal_date(vm, iso_date_time.iso_date, zoned_date_time->calendar()));
}
// 6.3.49 Temporal.ZonedDateTime.prototype.toPlainTime ( ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.toplaintime
JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::to_plain_time)
{
// 1. Let zonedDateTime be the this value.
// 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
auto zoned_date_time = TRY(typed_this_object(vm));
// 3. Let isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
auto iso_date_time = get_iso_date_time_for(zoned_date_time->time_zone(), zoned_date_time->epoch_nanoseconds()->big_integer());
// 4. Return ! CreateTemporalTime(isoDateTime.[[Time]]).
return MUST(create_temporal_time(vm, iso_date_time.time));
}
// 6.3.50 Temporal.ZonedDateTime.prototype.toPlainDateTime ( ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.toplaindatetime
JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::to_plain_date_time)
{
// 1. Let zonedDateTime be the this value.
// 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
auto zoned_date_time = TRY(typed_this_object(vm));
// 3. Let isoDateTime be GetISODateTimeFor(zonedDateTime.[[TimeZone]], zonedDateTime.[[EpochNanoseconds]]).
auto iso_date_time = get_iso_date_time_for(zoned_date_time->time_zone(), zoned_date_time->epoch_nanoseconds()->big_integer());
// 4. Return ! CreateTemporalDateTime(isoDateTime, zonedDateTime.[[Calendar]]).
return MUST(create_temporal_date_time(vm, iso_date_time, zoned_date_time->calendar()));
}
}

View File

@@ -67,6 +67,10 @@ private:
JS_DECLARE_NATIVE_FUNCTION(value_of);
JS_DECLARE_NATIVE_FUNCTION(start_of_day);
JS_DECLARE_NATIVE_FUNCTION(get_time_zone_transition);
JS_DECLARE_NATIVE_FUNCTION(to_instant);
JS_DECLARE_NATIVE_FUNCTION(to_plain_date);
JS_DECLARE_NATIVE_FUNCTION(to_plain_time);
JS_DECLARE_NATIVE_FUNCTION(to_plain_date_time);
};
}

View File

@@ -0,0 +1,20 @@
describe("correct behavior", () => {
test("length is 0", () => {
expect(Temporal.ZonedDateTime.prototype.toInstant).toHaveLength(0);
});
test("basic functionality", () => {
const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, "UTC");
const instant = zonedDateTime.toInstant();
expect(instant).toBeInstanceOf(Temporal.Instant);
expect(instant.epochNanoseconds).toBe(1625614921000000000n);
});
});
describe("errors", () => {
test("this value must be a Temporal.ZonedDateTime object", () => {
expect(() => {
Temporal.ZonedDateTime.prototype.toInstant.call("foo");
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime");
});
});

View File

@@ -0,0 +1,22 @@
describe("correct behavior", () => {
test("length is 0", () => {
expect(Temporal.ZonedDateTime.prototype.toPlainDate).toHaveLength(0);
});
test("basic functionality", () => {
const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, "UTC");
const plainDate = zonedDateTime.toPlainDate();
expect(plainDate).toBeInstanceOf(Temporal.PlainDate);
expect(plainDate.year).toBe(2021);
expect(plainDate.month).toBe(7);
expect(plainDate.day).toBe(6);
});
});
describe("errors", () => {
test("this value must be a Temporal.ZonedDateTime object", () => {
expect(() => {
Temporal.ZonedDateTime.prototype.toPlainDate.call("foo");
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime");
});
});

View File

@@ -0,0 +1,28 @@
describe("correct behavior", () => {
test("length is 0", () => {
expect(Temporal.ZonedDateTime.prototype.toPlainDateTime).toHaveLength(0);
});
test("basic functionality", () => {
const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, "UTC");
const plainDateTime = zonedDateTime.toPlainDateTime();
expect(plainDateTime).toBeInstanceOf(Temporal.PlainDateTime);
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);
});
});
describe("errors", () => {
test("this value must be a Temporal.ZonedDateTime object", () => {
expect(() => {
Temporal.ZonedDateTime.prototype.toPlainDateTime.call("foo");
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime");
});
});

View File

@@ -0,0 +1,25 @@
describe("correct behavior", () => {
test("length is 0", () => {
expect(Temporal.ZonedDateTime.prototype.toPlainTime).toHaveLength(0);
});
test("basic functionality", () => {
const zonedDateTime = new Temporal.ZonedDateTime(1625614921000000000n, "UTC");
const plainTime = zonedDateTime.toPlainTime();
expect(plainTime).toBeInstanceOf(Temporal.PlainTime);
expect(plainTime.hour).toBe(23);
expect(plainTime.minute).toBe(42);
expect(plainTime.second).toBe(1);
expect(plainTime.millisecond).toBe(0);
expect(plainTime.microsecond).toBe(0);
expect(plainTime.nanosecond).toBe(0);
});
});
describe("errors", () => {
test("this value must be a Temporal.ZonedDateTime object", () => {
expect(() => {
Temporal.ZonedDateTime.prototype.toPlainTime.call("foo");
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime");
});
});