mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-01 05:39:11 +00:00
LibJS: Stub out Temporal.ZonedDateTime.prototype.getTimeZoneTransition
We will have to add facilities to determine next/previous time zone transitions. Ideally, ICU can provide this.
This commit is contained in:
parent
6d78f1327e
commit
b95528d7b5
Notes:
github-actions[bot]
2024-11-26 10:03:09 +00:00
Author: https://github.com/trflynn89
Commit: b95528d7b5
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2577
Reviewed-by: https://github.com/shannonbooth ✅
8 changed files with 133 additions and 0 deletions
|
@ -264,6 +264,7 @@ namespace JS {
|
|||
P(getTime) \
|
||||
P(getTimezoneOffset) \
|
||||
P(getTimeZones) \
|
||||
P(getTimeZoneTransition) \
|
||||
P(getUint8) \
|
||||
P(getUint16) \
|
||||
P(getUint32) \
|
||||
|
|
|
@ -245,6 +245,21 @@ ThrowCompletionOr<ShowOffset> get_temporal_show_offset_option(VM& vm, Object con
|
|||
return ShowOffset::Auto;
|
||||
}
|
||||
|
||||
// 13.13 GetDirectionOption ( options ), https://tc39.es/proposal-temporal/#sec-temporal-getdirectionoption
|
||||
ThrowCompletionOr<Direction> get_direction_option(VM& vm, Object const& options)
|
||||
{
|
||||
// 1. Let stringValue be ? GetOption(options, "direction", STRING, « "next", "previous" », REQUIRED).
|
||||
auto string_value = TRY(get_option(vm, options, vm.names.direction, OptionType::String, { "next"sv, "previous"sv }, Required {}));
|
||||
auto string_view = string_value.as_string().utf8_string_view();
|
||||
|
||||
// 2. If stringValue is "next", return NEXT.
|
||||
if (string_view == "next"sv)
|
||||
return Direction::Next;
|
||||
|
||||
// 3. Return PREVIOUS.
|
||||
return Direction::Previous;
|
||||
}
|
||||
|
||||
// 13.14 ValidateTemporalRoundingIncrement ( increment, dividend, inclusive ), https://tc39.es/proposal-temporal/#sec-validatetemporalroundingincrement
|
||||
ThrowCompletionOr<void> validate_temporal_rounding_increment(VM& vm, u64 increment, u64 dividend, bool inclusive)
|
||||
{
|
||||
|
|
|
@ -33,6 +33,11 @@ enum class DateType {
|
|||
YearMonth,
|
||||
};
|
||||
|
||||
enum class Direction {
|
||||
Next,
|
||||
Previous,
|
||||
};
|
||||
|
||||
enum class Disambiguation {
|
||||
Compatible,
|
||||
Earlier,
|
||||
|
@ -175,6 +180,7 @@ ThrowCompletionOr<OffsetOption> get_temporal_offset_option(VM&, Object const& op
|
|||
ThrowCompletionOr<ShowTimeZoneName> get_temporal_show_time_zone_name_option(VM&, Object const& options);
|
||||
ThrowCompletionOr<ShowOffset> get_temporal_show_offset_option(VM&, Object const& options);
|
||||
ThrowCompletionOr<ShowCalendar> get_temporal_show_calendar_name_option(VM&, Object const& options);
|
||||
ThrowCompletionOr<Direction> get_direction_option(VM&, Object const& options);
|
||||
ThrowCompletionOr<void> validate_temporal_rounding_increment(VM&, u64 increment, u64 dividend, bool inclusive);
|
||||
ThrowCompletionOr<Precision> get_temporal_fractional_second_digits_option(VM&, Object const& options);
|
||||
SecondsStringPrecision to_seconds_string_precision_record(UnitValue, Precision);
|
||||
|
|
|
@ -75,6 +75,26 @@ ISODateTime get_iso_parts_from_epoch(Crypto::SignedBigInteger const& epoch_nanos
|
|||
return combine_iso_date_and_time_record(iso_date, time);
|
||||
}
|
||||
|
||||
// 11.1.3 GetNamedTimeZoneNextTransition ( timeZoneIdentifier, epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-getnamedtimezonenexttransition
|
||||
Optional<Crypto::SignedBigInteger> get_named_time_zone_next_transition(StringView time_zone, Crypto::SignedBigInteger const& epoch_nanoseconds)
|
||||
{
|
||||
// FIXME: Implement this AO.
|
||||
(void)time_zone;
|
||||
(void)epoch_nanoseconds;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// 11.1.4 GetNamedTimeZonePreviousTransition ( timeZoneIdentifier, epochNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-getnamedtimezoneprevioustransition
|
||||
Optional<Crypto::SignedBigInteger> get_named_time_zone_previous_transition(StringView time_zone, Crypto::SignedBigInteger const& epoch_nanoseconds)
|
||||
{
|
||||
// FIXME: Implement this AO.
|
||||
(void)time_zone;
|
||||
(void)epoch_nanoseconds;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// 11.1.5 FormatOffsetTimeZoneIdentifier ( offsetMinutes [ , style ] ), https://tc39.es/proposal-temporal/#sec-temporal-formatoffsettimezoneidentifier
|
||||
String format_offset_time_zone_identifier(i64 offset_minutes, Optional<TimeStyle> style)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,8 @@ struct TimeZone {
|
|||
};
|
||||
|
||||
ISODateTime get_iso_parts_from_epoch(Crypto::SignedBigInteger const& epoch_nanoseconds);
|
||||
Optional<Crypto::SignedBigInteger> get_named_time_zone_next_transition(StringView time_zone, Crypto::SignedBigInteger const& epoch_nanoseconds);
|
||||
Optional<Crypto::SignedBigInteger> get_named_time_zone_previous_transition(StringView time_zone, Crypto::SignedBigInteger const& epoch_nanoseconds);
|
||||
String format_offset_time_zone_identifier(i64 offset_minutes, Optional<TimeStyle> = {});
|
||||
String format_utc_offset_nanoseconds(i64 offset_nanoseconds);
|
||||
String format_date_time_utc_offset_rounded(i64 offset_nanoseconds);
|
||||
|
|
|
@ -80,6 +80,7 @@ void ZonedDateTimePrototype::initialize(Realm& realm)
|
|||
define_native_function(realm, vm.names.toJSON, to_json, 0, attr);
|
||||
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);
|
||||
}
|
||||
|
||||
// 6.3.3 get Temporal.ZonedDateTime.prototype.calendarId, https://tc39.es/proposal-temporal/#sec-get-temporal.zoneddatetime.prototype.calendarid
|
||||
|
@ -832,4 +833,72 @@ JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::start_of_day)
|
|||
return MUST(create_temporal_zoned_date_time(vm, BigInt::create(vm, move(epoch_nanoseconds)), time_zone, calendar));
|
||||
}
|
||||
|
||||
// 6.3.46 Temporal.ZonedDateTime.prototype.getTimeZoneTransition ( directionParam ), https://tc39.es/proposal-temporal/#sec-temporal.zoneddatetime.prototype.gettimezonetransition
|
||||
JS_DEFINE_NATIVE_FUNCTION(ZonedDateTimePrototype::get_time_zone_transition)
|
||||
{
|
||||
auto& realm = *vm.current_realm();
|
||||
|
||||
auto direction_param_value = vm.argument(0);
|
||||
|
||||
// 1. Let zonedDateTime be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(zonedDateTime, [[InitializedTemporalZonedDateTime]]).
|
||||
auto zoned_date_time = TRY(typed_this_object(vm));
|
||||
|
||||
// 3. Let timeZone be zonedDateTime.[[TimeZone]].
|
||||
auto const& time_zone = zoned_date_time->time_zone();
|
||||
|
||||
// 4. If directionParam is undefined, throw a TypeError exception.
|
||||
if (direction_param_value.is_undefined())
|
||||
return vm.throw_completion<TypeError>(ErrorType::IsUndefined, "Transition direction parameter"sv);
|
||||
|
||||
GC::Ptr<Object> direction_param;
|
||||
|
||||
// 5. If directionParam is a String, then
|
||||
if (direction_param_value.is_string()) {
|
||||
// a. Let paramString be directionParam.
|
||||
auto param_string = direction_param_value;
|
||||
|
||||
// b. Set directionParam to OrdinaryObjectCreate(null).
|
||||
direction_param = Object::create(realm, nullptr);
|
||||
|
||||
// c. Perform ! CreateDataPropertyOrThrow(directionParam, "direction", paramString).
|
||||
MUST(direction_param->create_data_property_or_throw(vm.names.direction, param_string));
|
||||
}
|
||||
// 6. Else,
|
||||
else {
|
||||
// a. Set directionParam to ? GetOptionsObject(directionParam).
|
||||
direction_param = TRY(get_options_object(vm, direction_param_value));
|
||||
}
|
||||
|
||||
// 7. Let direction be ? GetDirectionOption(directionParam).
|
||||
auto direction = TRY(get_direction_option(vm, *direction_param));
|
||||
|
||||
// 8. If IsOffsetTimeZoneIdentifier(timeZone) is true, return null.
|
||||
if (is_offset_time_zone_identifier(time_zone))
|
||||
return js_null();
|
||||
|
||||
Optional<Crypto::SignedBigInteger> transition;
|
||||
|
||||
switch (direction) {
|
||||
// 9. If direction is NEXT, then
|
||||
case Direction::Next:
|
||||
// a. Let transition be GetNamedTimeZoneNextTransition(timeZone, zonedDateTime.[[EpochNanoseconds]]).
|
||||
transition = get_named_time_zone_next_transition(time_zone, zoned_date_time->epoch_nanoseconds()->big_integer());
|
||||
break;
|
||||
// 10. Else,
|
||||
case Direction::Previous:
|
||||
// a. Assert: direction is PREVIOUS.
|
||||
// b. Let transition be GetNamedTimeZonePreviousTransition(timeZone, zonedDateTime.[[EpochNanoseconds]]).
|
||||
transition = get_named_time_zone_previous_transition(time_zone, zoned_date_time->epoch_nanoseconds()->big_integer());
|
||||
break;
|
||||
}
|
||||
|
||||
// 11. If transition is null, return null.
|
||||
if (!transition.has_value())
|
||||
return js_null();
|
||||
|
||||
// 12. Return ! CreateTemporalZonedDateTime(transition, timeZone, zonedDateTime.[[Calendar]]).
|
||||
return MUST(create_temporal_zoned_date_time(vm, BigInt::create(vm, transition.release_value()), time_zone, zoned_date_time->calendar()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ private:
|
|||
JS_DECLARE_NATIVE_FUNCTION(to_json);
|
||||
JS_DECLARE_NATIVE_FUNCTION(value_of);
|
||||
JS_DECLARE_NATIVE_FUNCTION(start_of_day);
|
||||
JS_DECLARE_NATIVE_FUNCTION(get_time_zone_transition);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
describe("correct behavior", () => {
|
||||
test("length is 1", () => {
|
||||
expect(Temporal.ZonedDateTime.prototype.getTimeZoneTransition).toHaveLength(1);
|
||||
});
|
||||
|
||||
test("basic functionality", () => {
|
||||
const zonedDateTime = new Temporal.ZonedDateTime(1627318123456789000n, "UTC", "iso8601");
|
||||
expect(zonedDateTime.getTimeZoneTransition("next")).toBeNull();
|
||||
expect(zonedDateTime.getTimeZoneTransition("previous")).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("this value must be a Temporal.TimeZone object", () => {
|
||||
expect(() => {
|
||||
Temporal.ZonedDateTime.prototype.getTimeZoneTransition.call("foo");
|
||||
}).toThrowWithMessage(TypeError, "Not an object of type Temporal.ZonedDateTime");
|
||||
});
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue