summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Runtime/Temporal
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2022-03-30 18:36:16 +0100
committerLinus Groh <mail@linusgroh.de>2022-03-31 17:09:10 +0100
commitb020b8eea25471b371af2466ace2b80b8cd691ee (patch)
tree3ec0674105a8e58472ab948898ba2855be981d74 /Userland/Libraries/LibJS/Runtime/Temporal
parentb5392f9e39d9bbf88fc84c3781baeb41ec28cf4a (diff)
downloadserenity-b020b8eea25471b371af2466ace2b80b8cd691ee.zip
LibJS: Handle Etc/GMT timezones properly in TimeZone{IANA,Bracketed}Name
This is a normative change in the Temporal spec. See: https://github.com/tc39/proposal-temporal/commit/8c73780
Diffstat (limited to 'Userland/Libraries/LibJS/Runtime/Temporal')
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.cpp51
-rw-r--r--Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.h1
2 files changed, 44 insertions, 8 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.cpp b/Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.cpp
index f55e215686..cca5fb9370 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.cpp
@@ -75,6 +75,32 @@ bool ISO8601Parser::parse_sign()
return true;
}
+// https://tc39.es/proposal-temporal/#prod-UnpaddedHour
+bool ISO8601Parser::parse_unpadded_hour()
+{
+ // UnpaddedHour :
+ // DecimalDigit
+ // 1 DecimalDigit
+ // 20
+ // 21
+ // 22
+ // 23
+ StateTransaction transaction { *this };
+ auto success = m_state.lexer.consume_specific("20"sv)
+ || m_state.lexer.consume_specific("21"sv)
+ || m_state.lexer.consume_specific("22"sv)
+ || m_state.lexer.consume_specific("23"sv);
+ if (!success) {
+ // This could be either of the first two productions.
+ if (m_state.lexer.consume_specific('1'))
+ (void)parse_decimal_digit();
+ else if (!parse_decimal_digit())
+ return false;
+ }
+ transaction.commit();
+ return true;
+}
+
// https://tc39.es/proposal-temporal/#prod-Hour
bool ISO8601Parser::parse_hour()
{
@@ -900,10 +926,25 @@ bool ISO8601Parser::parse_time_zone_iana_name_tail()
bool ISO8601Parser::parse_time_zone_iana_name()
{
// TimeZoneIANAName :
- // TimeZoneIANANameTail
+ // Etc/GMT ASCIISign UnpaddedHour
+ // TimeZoneIANANameTail but not Etc/GMT ASCIISign UnpaddedHour
+ auto parse_etc_gmt_with_offset = [this] {
+ StateTransaction transaction { *this };
+ if (!m_state.lexer.consume_specific("Etc/GMT"sv))
+ return false;
+ if (!parse_ascii_sign())
+ return false;
+ if (!parse_unpadded_hour())
+ return false;
+ transaction.commit();
+ return true;
+ };
StateTransaction transaction { *this };
- if (!parse_time_zone_iana_name_tail())
+ if (parse_etc_gmt_with_offset()) {
+ // no-op.
+ } else if (!parse_time_zone_iana_name_tail()) {
return false;
+ }
m_state.parse_result.time_zone_iana_name = transaction.parsed_string_view();
transaction.commit();
return true;
@@ -914,16 +955,10 @@ bool ISO8601Parser::parse_time_zone_bracketed_name()
{
// TimeZoneBracketedName :
// TimeZoneIANAName
- // Etc/GMT ASCIISign Hour
// TimeZoneUTCOffsetName
StateTransaction transaction { *this };
if (parse_time_zone_iana_name()) {
// no-op.
- } else if (m_state.lexer.consume_specific("Etc/GMT"sv)) {
- if (!parse_ascii_sign())
- return false;
- if (!parse_hour())
- return false;
} else if (!parse_time_zone_utc_offset_name()) {
return false;
}
diff --git a/Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.h b/Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.h
index 5b631bac3d..81425f3d89 100644
--- a/Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.h
+++ b/Userland/Libraries/LibJS/Runtime/Temporal/ISO8601.h
@@ -88,6 +88,7 @@ public:
[[nodiscard]] bool parse_non_zero_digit();
[[nodiscard]] bool parse_ascii_sign();
[[nodiscard]] bool parse_sign();
+ [[nodiscard]] bool parse_unpadded_hour();
[[nodiscard]] bool parse_hour();
[[nodiscard]] bool parse_minute_second();
[[nodiscard]] bool parse_decimal_separator();