diff --git a/Tests/LibUnicode/TestTimeZone.cpp b/Tests/LibUnicode/TestTimeZone.cpp index 2992e3ea510..15f34901324 100644 --- a/Tests/LibUnicode/TestTimeZone.cpp +++ b/Tests/LibUnicode/TestTimeZone.cpp @@ -49,6 +49,18 @@ TEST_CASE(available_time_zones) EXPECT(!time_zones.contains_slow("EAT"sv)); } +TEST_CASE(available_time_zones_in_region) +{ + { + auto time_zones = Unicode::available_time_zones_in_region("AD"sv); + EXPECT_EQ(time_zones, to_array({ "Europe/Andorra"_string })); + } + { + auto time_zones = Unicode::available_time_zones_in_region("ES"sv); + EXPECT_EQ(time_zones, to_array({ "Africa/Ceuta"_string, "Atlantic/Canary"_string, "Europe/Madrid"_string })); + } +} + TEST_CASE(resolve_primary_time_zone) { EXPECT_EQ(Unicode::resolve_primary_time_zone("UTC"sv), "Etc/UTC"sv); diff --git a/Userland/Libraries/LibJS/Runtime/Intl/Locale.cpp b/Userland/Libraries/LibJS/Runtime/Intl/Locale.cpp index 3ffa0f10adc..f9a07402dc4 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/Locale.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/Locale.cpp @@ -8,9 +8,9 @@ #include #include #include -#include #include #include +#include #include namespace JS::Intl { @@ -142,12 +142,11 @@ NonnullGCPtr time_zones_of_locale(VM& vm, StringView region) // 3. Let region be the substring of locale corresponding to the unicode_region_subtag production of the unicode_language_id. // 4. Let list be a List of unique canonical time zone identifiers, which must be String values indicating a canonical Zone name of the IANA Time Zone Database, ordered as if an Array of the same values had been sorted using %Array.prototype.sort% using undefined as comparefn, of those in common use in region. If no time zones are commonly used in region, let list be a new empty List. - auto list = TimeZone::time_zones_in_region(region); - quick_sort(list); + auto list = Unicode::available_time_zones_in_region(region); // 5. Return ! CreateArrayFromList( list ). - return Array::create_from(realm, list, [&vm](auto value) { - return PrimitiveString::create(vm, String::from_utf8(value).release_value()); + return Array::create_from(realm, list, [&vm](auto value) { + return PrimitiveString::create(vm, value); }); } diff --git a/Userland/Libraries/LibUnicode/TimeZone.cpp b/Userland/Libraries/LibUnicode/TimeZone.cpp index 07b9a9ddd85..662583811f3 100644 --- a/Userland/Libraries/LibUnicode/TimeZone.cpp +++ b/Userland/Libraries/LibUnicode/TimeZone.cpp @@ -76,26 +76,35 @@ static constexpr bool is_legacy_non_iana_time_zone(StringView time_zone) return legacy_zones.contains_slow(time_zone); } +static Vector icu_available_time_zones(Optional const& region) +{ + UErrorCode status = U_ZERO_ERROR; + + char const* icu_region = region.has_value() ? region->characters() : nullptr; + + auto time_zone_enumerator = adopt_own_if_nonnull(icu::TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_ANY, icu_region, nullptr, status)); + if (icu_failure(status)) + return { "UTC"_string }; + + auto time_zones = icu_string_enumeration_to_list(move(time_zone_enumerator), [](char const* zone) { + return !is_legacy_non_iana_time_zone({ zone, strlen(zone) }); + }); + + quick_sort(time_zones); + return time_zones; +} + Vector const& available_time_zones() { - static auto time_zones = []() -> Vector { - UErrorCode status = U_ZERO_ERROR; - - auto time_zone_enumerator = adopt_own_if_nonnull(icu::TimeZone::createEnumeration(status)); - if (icu_failure(status)) - return { "UTC"_string }; - - auto time_zones = icu_string_enumeration_to_list(move(time_zone_enumerator), [](char const* zone) { - return !is_legacy_non_iana_time_zone({ zone, strlen(zone) }); - }); - - quick_sort(time_zones); - return time_zones; - }(); - + static auto time_zones = icu_available_time_zones({}); return time_zones; } +Vector available_time_zones_in_region(StringView region) +{ + return icu_available_time_zones(region); +} + Optional resolve_primary_time_zone(StringView time_zone) { UErrorCode status = U_ZERO_ERROR; diff --git a/Userland/Libraries/LibUnicode/TimeZone.h b/Userland/Libraries/LibUnicode/TimeZone.h index a3a59063c56..6e5b7ca4fa6 100644 --- a/Userland/Libraries/LibUnicode/TimeZone.h +++ b/Userland/Libraries/LibUnicode/TimeZone.h @@ -14,6 +14,7 @@ namespace Unicode { String current_time_zone(); Vector const& available_time_zones(); +Vector available_time_zones_in_region(StringView region); Optional resolve_primary_time_zone(StringView time_zone); }