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
This commit is contained in:
Linus Groh 2022-03-30 18:36:16 +01:00
parent b5392f9e39
commit b020b8eea2
Notes: sideshowbarker 2024-07-17 16:25:28 +09:00
3 changed files with 48 additions and 11 deletions

View file

@ -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;
}

View file

@ -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();

View file

@ -18,9 +18,10 @@ describe("normal behavior", () => {
["GMT", "UTC"],
["Etc/UTC", "UTC"],
["Etc/GMT", "UTC"],
// FIXME: https://github.com/tc39/proposal-temporal/issues/1993
// ["Etc/GMT+12", "Etc/GMT+12"],
// ["Etc/GMT-12", "Etc/GMT-12"],
["Etc/GMT+6", "Etc/GMT+6"],
["Etc/GMT-6", "Etc/GMT-6"],
["Etc/GMT+12", "Etc/GMT+12"],
["Etc/GMT-12", "Etc/GMT-12"],
["Europe/London", "Europe/London"],
["Europe/Isle_of_Man", "Europe/London"],
["1970-01-01+01", "+01:00"],