From fa005bd276905a4f5dcdad47b4c1a3473ebec8e1 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Tue, 5 Jul 2022 15:56:23 -0400 Subject: [PATCH] LibTimeZone: Parse and generate a list of time zones used by region The zone1970.tab file in the TZDB contains regional time zone data, some of which we already parse for the system time zone settings map. This parses the region names from that file and generates a list of time zones which are used in each of those regions. --- .../LibTimeZone/GenerateTimeZoneData.cpp | 57 ++++++++++++++++++- Userland/Libraries/LibTimeZone/Forward.h | 1 + Userland/Libraries/LibTimeZone/TimeZone.cpp | 4 ++ Userland/Libraries/LibTimeZone/TimeZone.h | 5 ++ 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp b/Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp index e5b7fc336f..bf5499d8fa 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp @@ -18,8 +18,8 @@ namespace { -using StringIndexType = u8; -constexpr auto s_string_index_type = "u8"sv; +using StringIndexType = u16; +constexpr auto s_string_index_type = "u16"sv; struct DateTime { u16 year { 0 }; @@ -67,6 +67,9 @@ struct TimeZoneData { Vector dst_offset_names; HashMap time_zone_coordinates; + + HashMap> time_zone_regions; + Vector time_zone_region_names; }; } @@ -379,6 +382,7 @@ static ErrorOr parse_time_zone_coordinates(Core::Stream::BufferedFile& fil continue; auto segments = line.split_view('\t'); + auto regions = segments[0]; auto coordinates = segments[1]; auto zone = segments[2]; @@ -389,6 +393,14 @@ static ErrorOr parse_time_zone_coordinates(Core::Stream::BufferedFile& fil auto longitude = parse_coordinate(coordinates.substring_view(index)); time_zone_data.time_zone_coordinates.set(zone, { latitude, longitude }); + + regions.for_each_split_view(',', false, [&](auto region) { + auto index = time_zone_data.unique_strings.ensure(zone); + time_zone_data.time_zone_regions.ensure(region).append(index); + + if (!time_zone_data.time_zone_region_names.contains_slow(region)) + time_zone_data.time_zone_region_names.append(region); + }); } return {}; @@ -447,6 +459,7 @@ namespace TimeZone { generate_enum(generator, format_identifier, "TimeZone"sv, {}, time_zone_data.time_zone_names, time_zone_data.time_zone_aliases); generate_enum(generator, format_identifier, "DaylightSavingsRule"sv, {}, time_zone_data.dst_offset_names); + generate_enum(generator, format_identifier, "Region"sv, {}, time_zone_data.time_zone_region_names); generator.append(R"~~~( } @@ -556,6 +569,26 @@ static constexpr Array<@type@, @size@> @name@ { { append_offsets(name, "DaylightSavingsOffset"sv, dst_offsets); }); + generate_mapping(generator, time_zone_data.time_zone_region_names, s_string_index_type, "s_regional_time_zones"sv, "s_regional_time_zones_{}", format_identifier, + [&](auto const& name, auto const& value) { + auto const& time_zones = time_zone_data.time_zone_regions.find(value)->value; + + generator.set("name", name); + generator.set("size", String::number(time_zones.size())); + + generator.append(R"~~~( +static constexpr Array<@string_index_type@, @size@> @name@ { {)~~~"); + + bool first = true; + for (auto const& time_zone : time_zones) { + generator.append(first ? " " : ", "); + generator.append(String::number(time_zone)); + first = false; + } + + generator.append(" } };"); + }); + generator.set("size", String::number(time_zone_data.time_zone_names.size())); generator.append(R"~~~( static constexpr Array s_time_zone_locations { { @@ -590,6 +623,7 @@ static constexpr Array s_time_zone_locations { { append_string_conversions("TimeZone"sv, "time_zone"sv, time_zone_data.time_zone_names, time_zone_data.time_zone_aliases); append_string_conversions("DaylightSavingsRule"sv, "daylight_savings_rule"sv, time_zone_data.dst_offset_names); + append_string_conversions("Region"sv, "region"sv, time_zone_data.time_zone_region_names); generator.append(R"~~~( static Array find_dst_offsets(TimeZoneOffset const& time_zone_offset, AK::Time time) @@ -727,6 +761,25 @@ Optional get_time_zone_location(TimeZone time_zone) return location; return {}; } + +Vector time_zones_in_region(StringView region) +{ + auto region_value = region_from_string(region); + if (!region_value.has_value()) + return {}; + + auto region_index = to_underlying(*region_value); + + auto const& regional_time_zones = s_regional_time_zones[region_index]; + + Vector time_zones; + time_zones.ensure_capacity(regional_time_zones.size()); + + for (auto time_zone : regional_time_zones) + time_zones.unchecked_append(s_string_list[time_zone]); + + return time_zones; +} )~~~"); generate_available_values(generator, "all_time_zones"sv, time_zone_data.time_zone_names); diff --git a/Userland/Libraries/LibTimeZone/Forward.h b/Userland/Libraries/LibTimeZone/Forward.h index cd23df04e4..3902a56ae6 100644 --- a/Userland/Libraries/LibTimeZone/Forward.h +++ b/Userland/Libraries/LibTimeZone/Forward.h @@ -11,6 +11,7 @@ namespace TimeZone { enum class DaylightSavingsRule : u8; +enum class Region : u8; enum class TimeZone : u16; } diff --git a/Userland/Libraries/LibTimeZone/TimeZone.cpp b/Userland/Libraries/LibTimeZone/TimeZone.cpp index 253cad783f..20bbb1736a 100644 --- a/Userland/Libraries/LibTimeZone/TimeZone.cpp +++ b/Userland/Libraries/LibTimeZone/TimeZone.cpp @@ -192,4 +192,8 @@ Optional get_time_zone_location(StringView time_zone) return {}; } +Optional __attribute__((weak)) region_from_string(StringView) { return {}; } +StringView __attribute__((weak)) region_to_string(Region) { return {}; } +Vector __attribute__((weak)) time_zones_in_region(StringView) { return {}; } + } diff --git a/Userland/Libraries/LibTimeZone/TimeZone.h b/Userland/Libraries/LibTimeZone/TimeZone.h index 905b6d6cc4..738e548a7b 100644 --- a/Userland/Libraries/LibTimeZone/TimeZone.h +++ b/Userland/Libraries/LibTimeZone/TimeZone.h @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace TimeZone { @@ -68,4 +69,8 @@ Optional> get_named_time_zone_offsets(StringView time_zone Optional get_time_zone_location(TimeZone time_zone); Optional get_time_zone_location(StringView time_zone); +Optional region_from_string(StringView region); +StringView region_to_string(Region region); +Vector time_zones_in_region(StringView region); + }