summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2021-11-04 16:45:54 +0100
committerLinus Groh <mail@linusgroh.de>2021-11-04 16:45:54 +0100
commit38809f90d9bd3c7f0deaa7122dc4a543c64625ba (patch)
tree98568f48592f97a6b8aac73ecc6d9795369a9274
parentd129e1ff29608e178d72e94a486e0510502feb2f (diff)
downloadserenity-38809f90d9bd3c7f0deaa7122dc4a543c64625ba.zip
LibJS: Introduce & use FormatISOTimeZoneOffsetString
This is a normative change in the Temporal spec. See: https://github.com/tc39/proposal-temporal/commit/6b7a993
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/Instant.cpp7
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp41
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.h1
3 files changed, 40 insertions, 9 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/Instant.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/Instant.cpp
index 2484feac11..e8595d553a 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/Instant.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/Instant.cpp
@@ -263,8 +263,11 @@ ThrowCompletionOr<String> temporal_instant_to_string(GlobalObject& global_object
}
// 9. Else,
else {
- // a. Let timeZoneString be ? BuiltinTimeZoneGetOffsetStringFor(timeZone, instant).
- time_zone_string = TRY(builtin_time_zone_get_offset_string_for(global_object, time_zone, instant));
+ // a. Let offsetNs be ? GetOffsetNanosecondsFor(timeZone, instant).
+ auto offset_ns = TRY(get_offset_nanoseconds_for(global_object, time_zone, instant));
+
+ // b. Let timeZoneString be ! FormatISOTimeZoneOffsetString(offsetNs).
+ time_zone_string = format_iso_time_zone_offset_string(offset_ns);
}
// 10. Return the string-concatenation of dateTimeString and timeZoneString.
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp
index f8b06b9293..f32e843394 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.cpp
@@ -348,7 +348,34 @@ String format_time_zone_offset_string(double offset_nanoseconds)
return builder.to_string();
}
-// 11.6.10 ToTemporalTimeZone ( temporalTimeZoneLike ), https://tc39.es/proposal-temporal/#sec-temporal-totemporaltimezone
+// 11.6.10 FormatISOTimeZoneOffsetString ( offsetNanoseconds ), https://tc39.es/proposal-temporal/#sec-temporal-formatisotimezoneoffsetstring
+String format_iso_time_zone_offset_string(double offset_nanoseconds)
+{
+ // 1. Assert: offsetNanoseconds is an integer.
+ VERIFY(trunc(offset_nanoseconds) == offset_nanoseconds);
+
+ // 2. Set offsetNanoseconds to ! RoundNumberToIncrement(offsetNanoseconds, 60 × 10^9, "halfExpand").
+ offset_nanoseconds = round_number_to_increment(offset_nanoseconds, 60000000000, "halfExpand"sv);
+
+ // 3. If offsetNanoseconds ≥ 0, let sign be "+"; otherwise, let sign be "-".
+ auto sign = offset_nanoseconds >= 0 ? "+"sv : "-"sv;
+
+ // 4. Set offsetNanoseconds to abs(offsetNanoseconds).
+ offset_nanoseconds = fabs(offset_nanoseconds);
+
+ // 5. Let minutes be offsetNanoseconds / (60 × 10^9) modulo 60.
+ auto minutes = fmod(offset_nanoseconds / 60000000000, 60);
+
+ // 6. Let hours be floor(offsetNanoseconds / (3600 × 10^9)).
+ auto hours = floor(offset_nanoseconds / 3600000000000);
+
+ // 7. Let h be hours, formatted as a two-digit decimal number, padded to the left with a zero if necessary.
+ // 8. Let m be minutes, formatted as a two-digit decimal number, padded to the left with a zero if necessary.
+ // 9. Return the string-concatenation of sign, h, the code unit 0x003A (COLON), and m.
+ return String::formatted("{}{:02}:{:02}", sign, (u32)hours, (u32)minutes);
+}
+
+// 11.6.11 ToTemporalTimeZone ( temporalTimeZoneLike ), https://tc39.es/proposal-temporal/#sec-temporal-totemporaltimezone
ThrowCompletionOr<Object*> to_temporal_time_zone(GlobalObject& global_object, Value temporal_time_zone_like)
{
auto& vm = global_object.vm();
@@ -385,7 +412,7 @@ ThrowCompletionOr<Object*> to_temporal_time_zone(GlobalObject& global_object, Va
return TRY(create_temporal_time_zone(global_object, result));
}
-// 11.6.11 GetOffsetNanosecondsFor ( timeZone, instant ), https://tc39.es/proposal-temporal/#sec-temporal-getoffsetnanosecondsfor
+// 11.6.12 GetOffsetNanosecondsFor ( timeZone, instant ), https://tc39.es/proposal-temporal/#sec-temporal-getoffsetnanosecondsfor
ThrowCompletionOr<double> get_offset_nanoseconds_for(GlobalObject& global_object, Value time_zone, Instant& instant)
{
auto& vm = global_object.vm();
@@ -419,7 +446,7 @@ ThrowCompletionOr<double> get_offset_nanoseconds_for(GlobalObject& global_object
return offset_nanoseconds;
}
-// 11.6.12 BuiltinTimeZoneGetOffsetStringFor ( timeZone, instant ), https://tc39.es/proposal-temporal/#sec-temporal-builtintimezonegetoffsetstringfor
+// 11.6.13 BuiltinTimeZoneGetOffsetStringFor ( timeZone, instant ), https://tc39.es/proposal-temporal/#sec-temporal-builtintimezonegetoffsetstringfor
ThrowCompletionOr<String> builtin_time_zone_get_offset_string_for(GlobalObject& global_object, Value time_zone, Instant& instant)
{
// 1. Let offsetNanoseconds be ? GetOffsetNanosecondsFor(timeZone, instant).
@@ -429,7 +456,7 @@ ThrowCompletionOr<String> builtin_time_zone_get_offset_string_for(GlobalObject&
return format_time_zone_offset_string(offset_nanoseconds);
}
-// 11.6.13 BuiltinTimeZoneGetPlainDateTimeFor ( timeZone, instant, calendar ), https://tc39.es/proposal-temporal/#sec-temporal-builtintimezonegetplaindatetimefor
+// 11.6.14 BuiltinTimeZoneGetPlainDateTimeFor ( timeZone, instant, calendar ), https://tc39.es/proposal-temporal/#sec-temporal-builtintimezonegetplaindatetimefor
ThrowCompletionOr<PlainDateTime*> builtin_time_zone_get_plain_date_time_for(GlobalObject& global_object, Value time_zone, Instant& instant, Object& calendar)
{
// 1. Assert: instant has an [[InitializedTemporalInstant]] internal slot.
@@ -447,7 +474,7 @@ ThrowCompletionOr<PlainDateTime*> builtin_time_zone_get_plain_date_time_for(Glob
return create_temporal_date_time(global_object, result.year, result.month, result.day, result.hour, result.minute, result.second, result.millisecond, result.microsecond, result.nanosecond, calendar);
}
-// 11.6.14 BuiltinTimeZoneGetInstantFor ( timeZone, dateTime, disambiguation ), https://tc39.es/proposal-temporal/#sec-temporal-builtintimezonegetinstantfor
+// 11.6.15 BuiltinTimeZoneGetInstantFor ( timeZone, dateTime, disambiguation ), https://tc39.es/proposal-temporal/#sec-temporal-builtintimezonegetinstantfor
ThrowCompletionOr<Instant*> builtin_time_zone_get_instant_for(GlobalObject& global_object, Value time_zone, PlainDateTime& date_time, StringView disambiguation)
{
// 1. Assert: dateTime has an [[InitializedTemporalDateTime]] internal slot.
@@ -459,7 +486,7 @@ ThrowCompletionOr<Instant*> builtin_time_zone_get_instant_for(GlobalObject& glob
return disambiguate_possible_instants(global_object, possible_instants, time_zone, date_time, disambiguation);
}
-// 11.6.15 DisambiguatePossibleInstants ( possibleInstants, timeZone, dateTime, disambiguation ), https://tc39.es/proposal-temporal/#sec-temporal-disambiguatepossibleinstants
+// 11.6.16 DisambiguatePossibleInstants ( possibleInstants, timeZone, dateTime, disambiguation ), https://tc39.es/proposal-temporal/#sec-temporal-disambiguatepossibleinstants
ThrowCompletionOr<Instant*> disambiguate_possible_instants(GlobalObject& global_object, Vector<Value> const& possible_instants, Value time_zone, PlainDateTime& date_time, StringView disambiguation)
{
// TODO: MarkedValueList<T> would be nice, then we could pass a Vector<Instant*> here and wouldn't need the casts...
@@ -573,7 +600,7 @@ ThrowCompletionOr<Instant*> disambiguate_possible_instants(GlobalObject& global_
return &static_cast<Instant&>(const_cast<Object&>(instant.as_object()));
}
-// 11.6.16 GetPossibleInstantsFor ( timeZone, dateTime ), https://tc39.es/proposal-temporal/#sec-temporal-getpossibleinstantsfor
+// 11.6.17 GetPossibleInstantsFor ( timeZone, dateTime ), https://tc39.es/proposal-temporal/#sec-temporal-getpossibleinstantsfor
ThrowCompletionOr<MarkedValueList> get_possible_instants_for(GlobalObject& global_object, Value time_zone, PlainDateTime& date_time)
{
auto& vm = global_object.vm();
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.h b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.h
index 8ed0e61ca7..d0cb7b0b58 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.h
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/TimeZone.h
@@ -45,6 +45,7 @@ BigInt* get_iana_time_zone_next_transition(GlobalObject&, BigInt const& epoch_na
BigInt* get_iana_time_zone_previous_transition(GlobalObject&, BigInt const& epoch_nanoseconds, StringView time_zone_identifier);
ThrowCompletionOr<double> parse_time_zone_offset_string(GlobalObject&, String const&);
String format_time_zone_offset_string(double offset_nanoseconds);
+String format_iso_time_zone_offset_string(double offset_nanoseconds);
ThrowCompletionOr<Object*> to_temporal_time_zone(GlobalObject&, Value temporal_time_zone_like);
ThrowCompletionOr<double> get_offset_nanoseconds_for(GlobalObject&, Value time_zone, Instant&);
ThrowCompletionOr<String> builtin_time_zone_get_offset_string_for(GlobalObject&, Value time_zone, Instant&);