mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 20:15:17 +00:00
LibUnicode: Parse and generate long and short generic time zone names
This implements the CalendarPatternStyle::{Long,Short}Generic styles of time zone name formatting.
This commit is contained in:
parent
d50f5e14f8
commit
e2dfbe8f67
Notes:
sideshowbarker
2024-07-17 21:09:27 +09:00
Author: https://github.com/trflynn89 Commit: https://github.com/SerenityOS/serenity/commit/e2dfbe8f674 Pull-request: https://github.com/SerenityOS/serenity/pull/11813 Reviewed-by: https://github.com/linusg ✅
2 changed files with 80 additions and 35 deletions
|
@ -383,16 +383,26 @@ struct AK::Traits<Calendar> : public GenericTraits<Calendar> {
|
|||
struct TimeZoneNames {
|
||||
unsigned hash() const
|
||||
{
|
||||
return pair_int_hash(long_name, short_name);
|
||||
auto hash = pair_int_hash(short_standard_name, long_standard_name);
|
||||
hash = pair_int_hash(hash, short_generic_name);
|
||||
hash = pair_int_hash(hash, long_generic_name);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
bool operator==(TimeZoneNames const& other) const
|
||||
{
|
||||
return (long_name == other.long_name) && (short_name == other.short_name);
|
||||
return (short_standard_name == other.short_standard_name)
|
||||
&& (long_standard_name == other.long_standard_name)
|
||||
&& (short_generic_name == other.short_generic_name)
|
||||
&& (long_generic_name == other.long_generic_name);
|
||||
}
|
||||
|
||||
StringIndexType long_name { 0 };
|
||||
StringIndexType short_name { 0 };
|
||||
StringIndexType short_standard_name { 0 };
|
||||
StringIndexType long_standard_name { 0 };
|
||||
|
||||
StringIndexType short_generic_name { 0 };
|
||||
StringIndexType long_generic_name { 0 };
|
||||
};
|
||||
|
||||
template<>
|
||||
|
@ -400,9 +410,11 @@ struct AK::Formatter<TimeZoneNames> : Formatter<FormatString> {
|
|||
ErrorOr<void> format(FormatBuilder& builder, TimeZoneNames const& time_zone)
|
||||
{
|
||||
return Formatter<FormatString>::format(builder,
|
||||
"{{ {}, {} }}",
|
||||
time_zone.long_name,
|
||||
time_zone.short_name);
|
||||
"{{ {}, {}, {}, {} }}",
|
||||
time_zone.short_standard_name,
|
||||
time_zone.long_standard_name,
|
||||
time_zone.short_generic_name,
|
||||
time_zone.long_generic_name);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1411,18 +1423,16 @@ static ErrorOr<void> parse_time_zone_names(String locale_time_zone_names_path, U
|
|||
if (meta_zone_object.is_null())
|
||||
return {};
|
||||
|
||||
auto parse_name = [&](StringView type, JsonObject const& meta_zone_object) -> Optional<StringIndexType> {
|
||||
auto parse_name = [&](StringView type, JsonObject const& meta_zone_object, Span<StringView const> keys) -> Optional<StringIndexType> {
|
||||
auto const& names = meta_zone_object.get(type);
|
||||
if (!names.is_object())
|
||||
return {};
|
||||
|
||||
auto const& daylight = names.as_object().get("daylight"sv);
|
||||
if (daylight.is_string())
|
||||
return locale_data.unique_strings.ensure(daylight.as_string());
|
||||
|
||||
auto const& standard = names.as_object().get("standard"sv);
|
||||
if (standard.is_string())
|
||||
return locale_data.unique_strings.ensure(standard.as_string());
|
||||
for (auto key : keys) {
|
||||
auto const& name = names.as_object().get(key);
|
||||
if (name.is_string())
|
||||
return locale_data.unique_strings.ensure(name.as_string());
|
||||
}
|
||||
|
||||
return {};
|
||||
};
|
||||
|
@ -1458,16 +1468,23 @@ static ErrorOr<void> parse_time_zone_names(String locale_time_zone_names_path, U
|
|||
time_zone_formats.gmt_zero_format = locale_data.unique_strings.ensure(gmt_zero_format_string.as_string());
|
||||
|
||||
auto parse_time_zone = [&](StringView meta_zone, JsonObject const& meta_zone_object) {
|
||||
constexpr auto standard_keys = Array { "daylight"sv, "standard"sv };
|
||||
constexpr auto generic_keys = Array { "generic"sv };
|
||||
|
||||
auto golden_zones = locale_data.meta_zones.find(meta_zone);
|
||||
if (golden_zones == locale_data.meta_zones.end())
|
||||
return;
|
||||
|
||||
TimeZoneNames time_zone_names {};
|
||||
|
||||
if (auto long_name = parse_name("long"sv, meta_zone_object); long_name.has_value())
|
||||
time_zone_names.long_name = long_name.value();
|
||||
if (auto short_name = parse_name("short"sv, meta_zone_object); short_name.has_value())
|
||||
time_zone_names.short_name = short_name.value();
|
||||
if (auto name = parse_name("long"sv, meta_zone_object, standard_keys); name.has_value())
|
||||
time_zone_names.long_standard_name = name.value();
|
||||
if (auto name = parse_name("short"sv, meta_zone_object, standard_keys); name.has_value())
|
||||
time_zone_names.short_standard_name = name.value();
|
||||
if (auto name = parse_name("long"sv, meta_zone_object, generic_keys); name.has_value())
|
||||
time_zone_names.long_generic_name = name.value();
|
||||
if (auto name = parse_name("short"sv, meta_zone_object, generic_keys); name.has_value())
|
||||
time_zone_names.short_generic_name = name.value();
|
||||
|
||||
auto time_zone_index = locale_data.unique_time_zones.ensure(move(time_zone_names));
|
||||
|
||||
|
@ -1795,8 +1812,11 @@ struct CalendarData {
|
|||
};
|
||||
|
||||
struct TimeZoneNames {
|
||||
@string_index_type@ long_name { 0 };
|
||||
@string_index_type@ short_name { 0 };
|
||||
@string_index_type@ short_standard_name { 0 };
|
||||
@string_index_type@ long_standard_name { 0 };
|
||||
|
||||
@string_index_type@ short_generic_name { 0 };
|
||||
@string_index_type@ long_generic_name { 0 };
|
||||
};
|
||||
|
||||
struct TimeZoneFormatImpl {
|
||||
|
@ -2176,19 +2196,28 @@ static TimeZoneNames const* find_time_zone_names(StringView locale, StringView t
|
|||
|
||||
Optional<StringView> get_time_zone_name(StringView locale, StringView time_zone, CalendarPatternStyle style)
|
||||
{
|
||||
if ((style == CalendarPatternStyle::Long) || (style == CalendarPatternStyle::Short)) {
|
||||
if (auto const* data = find_time_zone_names(locale, time_zone); data != nullptr) {
|
||||
auto time_zone_index = style == CalendarPatternStyle::Long ? data->long_name : data->short_name;
|
||||
if (time_zone_index != 0)
|
||||
return s_string_list[time_zone_index];
|
||||
}
|
||||
} else {
|
||||
// FIXME: We will need to parse the "generic" time zone names from timeZoneNames.json
|
||||
// to support time zones other than UTC.
|
||||
VERIFY(time_zone == "UTC"sv);
|
||||
if (auto const* data = find_time_zone_names(locale, time_zone); data != nullptr) {
|
||||
size_t name_index = 0;
|
||||
|
||||
if (auto formats = get_time_zone_format(locale); formats.has_value())
|
||||
return formats->gmt_zero_format;
|
||||
switch (style) {
|
||||
case CalendarPatternStyle::Short:
|
||||
name_index = data->short_standard_name;
|
||||
break;
|
||||
case CalendarPatternStyle::Long:
|
||||
name_index = data->long_standard_name;
|
||||
break;
|
||||
case CalendarPatternStyle::ShortGeneric:
|
||||
name_index = data->short_generic_name;
|
||||
break;
|
||||
case CalendarPatternStyle::LongGeneric:
|
||||
name_index = data->long_generic_name;
|
||||
break;
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
if (name_index != 0)
|
||||
return s_string_list[name_index];
|
||||
}
|
||||
|
||||
return {};
|
||||
|
|
|
@ -23,37 +23,53 @@ TEST_CASE(time_zone_name)
|
|||
constexpr auto test_data = Array {
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::Long, "UTC"sv, "Coordinated Universal Time"sv },
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::Short, "UTC"sv, "UTC"sv },
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::ShortGeneric, "UTC"sv, "GMT"sv },
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::LongGeneric, "UTC"sv, "GMT"sv },
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::ShortGeneric, "UTC"sv, "GMT"sv },
|
||||
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::Long, "UTC"sv, "التوقيت العالمي المنسق"sv },
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::Short, "UTC"sv, "UTC"sv },
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::ShortGeneric, "UTC"sv, "غرينتش"sv },
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::LongGeneric, "UTC"sv, "غرينتش"sv },
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::ShortGeneric, "UTC"sv, "غرينتش"sv },
|
||||
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::Long, "America/Los_Angeles"sv, "Pacific Daylight Time"sv },
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::Short, "America/Los_Angeles"sv, "PDT"sv },
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::LongGeneric, "America/Los_Angeles"sv, "Pacific Time"sv },
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::ShortGeneric, "America/Los_Angeles"sv, "PT"sv },
|
||||
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::Long, "America/Los_Angeles"sv, "توقيت المحيط الهادي الصيفي"sv },
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::Short, "America/Los_Angeles"sv, "غرينتش-٨"sv },
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::LongGeneric, "America/Los_Angeles"sv, "توقيت المحيط الهادي"sv },
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::ShortGeneric, "America/Los_Angeles"sv, "غرينتش-٨"sv },
|
||||
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::Long, "America/Vancouver"sv, "Pacific Daylight Time"sv },
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::Short, "America/Vancouver"sv, "PDT"sv },
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::LongGeneric, "America/Vancouver"sv, "Pacific Time"sv },
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::ShortGeneric, "America/Vancouver"sv, "PT"sv },
|
||||
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::Long, "America/Vancouver"sv, "توقيت المحيط الهادي الصيفي"sv },
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::Short, "America/Vancouver"sv, "غرينتش-٨"sv },
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::LongGeneric, "America/Vancouver"sv, "توقيت المحيط الهادي"sv },
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::ShortGeneric, "America/Vancouver"sv, "غرينتش-٨"sv },
|
||||
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::Long, "Europe/London"sv, "Greenwich Mean Time"sv },
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::Short, "Europe/London"sv, "GMT"sv },
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::LongGeneric, "Europe/London"sv, "GMT"sv },
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::ShortGeneric, "Europe/London"sv, "GMT"sv },
|
||||
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::Long, "Europe/London"sv, "توقيت غرينتش"sv },
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::Short, "Europe/London"sv, "غرينتش"sv },
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::LongGeneric, "Europe/London"sv, "غرينتش"sv },
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::ShortGeneric, "Europe/London"sv, "غرينتش"sv },
|
||||
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::Long, "Africa/Accra"sv, "Greenwich Mean Time"sv },
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::Short, "Africa/Accra"sv, "GMT"sv },
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::LongGeneric, "Africa/Accra"sv, "GMT"sv },
|
||||
TestData { "en"sv, Unicode::CalendarPatternStyle::ShortGeneric, "Africa/Accra"sv, "GMT"sv },
|
||||
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::Long, "Africa/Accra"sv, "توقيت غرينتش"sv },
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::Short, "Africa/Accra"sv, "غرينتش"sv },
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::LongGeneric, "Africa/Accra"sv, "غرينتش"sv },
|
||||
TestData { "ar"sv, Unicode::CalendarPatternStyle::ShortGeneric, "Africa/Accra"sv, "غرينتش"sv },
|
||||
};
|
||||
|
||||
constexpr auto jan_1_2022 = AK::Time::from_seconds(1640995200); // Saturday, January 1, 2022 12:00:00 AM
|
||||
|
|
Loading…
Add table
Reference in a new issue