diff --git a/Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp b/Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp index 041bc9cb454..f4a23d9523a 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Tim Flynn + * Copyright (c) 2022-2024, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -63,8 +63,6 @@ struct TimeZoneData { HashMap> dst_offsets; Vector dst_offset_names; - HashMap time_zone_coordinates; - HashMap> time_zone_regions; Vector time_zone_region_names; @@ -140,29 +138,6 @@ struct AK::Formatter : Formatter { } }; -template<> -struct AK::Formatter : Formatter { - ErrorOr format(FormatBuilder& builder, TimeZone::Coordinate const& coordinate) - { - return Formatter::format(builder, - "{{ {}, {}, {} }}"sv, - coordinate.degrees, - coordinate.minutes, - coordinate.seconds); - } -}; - -template<> -struct AK::Formatter : Formatter { - ErrorOr format(FormatBuilder& builder, TimeZone::Location const& location) - { - return Formatter::format(builder, - "{{ {}, {} }}"sv, - location.latitude, - location.longitude); - } -}; - static Optional parse_date_time(ReadonlySpan segments) { auto comment_index = find_index(segments.begin(), segments.end(), "#"sv); @@ -363,35 +338,6 @@ static ErrorOr parse_time_zones(StringView time_zone_path, TimeZoneData& t static ErrorOr parse_time_zone_coordinates(Core::InputBufferedFile& file, TimeZoneData& time_zone_data) { - auto parse_coordinate = [](auto coordinate) { - VERIFY(coordinate.substring_view(0, 1).is_one_of("+"sv, "-"sv)); - TimeZone::Coordinate parsed {}; - - if (coordinate.length() == 5) { - // ±DDMM - parsed.degrees = coordinate.substring_view(0, 3).template to_number().value(); - parsed.minutes = coordinate.substring_view(3).template to_number().value(); - } else if (coordinate.length() == 6) { - // ±DDDMM - parsed.degrees = coordinate.substring_view(0, 4).template to_number().value(); - parsed.minutes = coordinate.substring_view(4).template to_number().value(); - } else if (coordinate.length() == 7) { - // ±DDMMSS - parsed.degrees = coordinate.substring_view(0, 3).template to_number().value(); - parsed.minutes = coordinate.substring_view(3, 2).template to_number().value(); - parsed.seconds = coordinate.substring_view(5).template to_number().value(); - } else if (coordinate.length() == 8) { - // ±DDDDMMSS - parsed.degrees = coordinate.substring_view(0, 4).template to_number().value(); - parsed.minutes = coordinate.substring_view(4, 2).template to_number().value(); - parsed.seconds = coordinate.substring_view(6).template to_number().value(); - } else { - VERIFY_NOT_REACHED(); - } - - return parsed; - }; - Array buffer {}; while (TRY(file.can_read_line())) { @@ -402,17 +348,10 @@ static ErrorOr parse_time_zone_coordinates(Core::InputBufferedFile& file, auto segments = line.split_view('\t'); auto regions = segments[0]; - auto coordinates = segments[1]; auto zone = segments[2]; VERIFY(time_zone_data.time_zones.contains(zone)); - auto index = coordinates.find_any_of("+-"sv, StringView::SearchDirection::Backward).value(); - auto latitude = parse_coordinate(coordinates.substring_view(0, index)); - auto longitude = parse_coordinate(coordinates.substring_view(index)); - - time_zone_data.time_zone_coordinates.set(zone, { latitude, longitude }); - TRY(regions.for_each_split_view(',', SplitBehavior::Nothing, [&](auto region) -> ErrorOr { auto index = time_zone_data.unique_strings.ensure(zone); TRY(time_zone_data.time_zone_regions.ensure(region).try_append(index)); @@ -612,18 +551,6 @@ static constexpr Array<@string_index_type@, @size@> @name@ { {)~~~"); generator.append(" } };"); }); - generator.set("size", ByteString::number(time_zone_data.time_zone_names.size())); - generator.append(R"~~~( -static constexpr Array s_time_zone_locations { { -)~~~"); - - for (auto const& time_zone : time_zone_data.time_zone_names) { - auto location = time_zone_data.time_zone_coordinates.get(time_zone).value_or({}); - - generator.append(ByteString::formatted(" {},\n", location)); - } - generator.append("} };\n"); - auto append_string_conversions = [&](StringView enum_title, StringView enum_snake, auto const& values, Vector const& aliases = {}) -> ErrorOr { HashValueMap hashes; TRY(hashes.try_ensure_capacity(values.size())); @@ -647,7 +574,6 @@ static constexpr Array s_time_zone_locations { { }; TRY(append_string_conversions("TimeZone"sv, "time_zone"sv, time_zone_data.time_zone_names, time_zone_data.time_zone_aliases)); - TRY(append_string_conversions("DaylightSavingsRule"sv, "daylight_savings_rule"sv, time_zone_data.dst_offset_names)); TRY(append_string_conversions("Region"sv, "region"sv, time_zone_data.time_zone_region_names)); generator.append(R"~~~( @@ -745,51 +671,6 @@ Optional get_time_zone_offset(TimeZone time_zone, AK::UnixDateTime time) return dst_offset; } -Optional> get_named_time_zone_offsets(TimeZone time_zone, AK::UnixDateTime time) -{ - auto const& time_zone_offset = find_time_zone_offset(time_zone, time); - Array named_offsets; - - auto format_name = [](auto format, auto offset) -> ByteString { - if (offset == 0) - return decode_string(format).replace("{}"sv, ""sv, ReplaceMode::FirstOnly); - return ByteString::formatted(decode_string(format), decode_string(offset)); - }; - - auto set_named_offset = [&](auto& named_offset, auto dst_offset, auto in_dst, auto format, auto offset) { - named_offset.seconds = time_zone_offset.offset + dst_offset; - named_offset.in_dst = in_dst; - named_offset.name = format_name(format, offset); - }; - - if (time_zone_offset.dst_rule != -1) { - auto offsets = find_dst_offsets(time_zone_offset, time); - auto in_dst = offsets[1]->offset == 0 ? InDST::No : InDST::Yes; - - set_named_offset(named_offsets[0], offsets[0]->offset, InDST::No, time_zone_offset.standard_format, offsets[0]->format); - set_named_offset(named_offsets[1], offsets[1]->offset, in_dst, time_zone_offset.daylight_format, offsets[1]->format); - } else { - auto in_dst = time_zone_offset.dst_offset == 0 ? InDST::No : InDST::Yes; - set_named_offset(named_offsets[0], time_zone_offset.dst_offset, in_dst, time_zone_offset.standard_format, 0); - set_named_offset(named_offsets[1], time_zone_offset.dst_offset, in_dst, time_zone_offset.daylight_format, 0); - } - - return named_offsets; -} - -Optional get_time_zone_location(TimeZone time_zone) -{ - auto is_valid_coordinate = [](auto const& coordinate) { - return (coordinate.degrees != 0) || (coordinate.minutes != 0) || (coordinate.seconds != 0); - }; - - auto const& location = s_time_zone_locations[to_underlying(time_zone)]; - - if (is_valid_coordinate(location.latitude) && is_valid_coordinate(location.longitude)) - return location; - return {}; -} - Vector time_zones_in_region(StringView region) { auto region_value = region_from_string(region); diff --git a/Tests/LibTimeZone/TestTimeZone.cpp b/Tests/LibTimeZone/TestTimeZone.cpp index 0ad467cdb0c..b272953f5ba 100644 --- a/Tests/LibTimeZone/TestTimeZone.cpp +++ b/Tests/LibTimeZone/TestTimeZone.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Tim Flynn + * Copyright (c) 2022-2024, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -180,35 +180,6 @@ TEST_CASE(get_time_zone_offset_with_dst) test_offset("America/Asuncion"sv, 1671453238, offset(-1, 3, 00, 00), Yes); // Monday, December 19, 2022 12:33:58 PM } -TEST_CASE(get_named_time_zone_offsets) -{ - auto test_named_offsets = [](auto time_zone, i64 time, i64 expected_standard_offset, i64 expected_daylight_offset, auto expected_standard_name, auto expected_daylight_name) { - auto actual_offsets = TimeZone::get_named_time_zone_offsets(time_zone, AK::UnixDateTime::from_seconds_since_epoch(time)); - VERIFY(actual_offsets.has_value()); - - EXPECT_EQ(actual_offsets->at(0).seconds, expected_standard_offset); - EXPECT_EQ(actual_offsets->at(1).seconds, expected_daylight_offset); - EXPECT_EQ(actual_offsets->at(0).name, expected_standard_name); - EXPECT_EQ(actual_offsets->at(1).name, expected_daylight_name); - }; - - test_named_offsets("America/New_York"sv, 1642558528, offset(-1, 5, 00, 00), offset(-1, 4, 00, 00), "EST"sv, "EDT"sv); // Wednesday, January 19, 2022 2:15:28 AM - test_named_offsets("UTC"sv, 1642558528, offset(+1, 0, 00, 00), offset(+1, 0, 00, 00), "UTC"sv, "UTC"sv); // Wednesday, January 19, 2022 2:15:28 AM - test_named_offsets("GMT"sv, 1642558528, offset(+1, 0, 00, 00), offset(+1, 0, 00, 00), "GMT"sv, "GMT"sv); // Wednesday, January 19, 2022 2:15:28 AM - - // Phoenix does not observe DST. - test_named_offsets("America/Phoenix"sv, 1642558528, offset(-1, 7, 00, 00), offset(-1, 7, 00, 00), "MST"sv, "MST"sv); // Wednesday, January 19, 2022 2:15:28 AM - - // Moscow's observed DST changed several times in 1919. - test_named_offsets("Europe/Moscow"sv, -1609459200, offset(+1, 2, 31, 19), offset(+1, 3, 31, 19), "MSK"sv, "MSD"sv); // Wednesday, January 1, 1919 12:00:00 AM - test_named_offsets("Europe/Moscow"sv, -1596412800, offset(+1, 2, 31, 19), offset(+1, 4, 31, 19), "MSK"sv, "MDST"sv); // Sunday, June 1, 1919 12:00:00 AM - test_named_offsets("Europe/Moscow"sv, -1589068800, offset(+1, 3, 00, 00), offset(+1, 4, 00, 00), "MSK"sv, "MSD"sv); // Monday, August 25, 1919 12:00:00 AM - - // Shanghai's DST rules end in 1991. - test_named_offsets("Asia/Shanghai"sv, 694223999, offset(+1, 8, 00, 00), offset(+1, 9, 00, 00), "CST"sv, "CDT"sv); // Tuesday, December 31, 1991 11:59:59 PM - test_named_offsets("Asia/Shanghai"sv, 694224000, offset(+1, 8, 00, 00), offset(+1, 8, 00, 00), "CST"sv, "CST"sv); // Wednesday, January 1, 1992 12:00:00 AM -} - #else TEST_CASE(time_zone_from_string) diff --git a/Userland/Libraries/LibTimeZone/TimeZone.cpp b/Userland/Libraries/LibTimeZone/TimeZone.cpp index f5858df8268..bff13ac56af 100644 --- a/Userland/Libraries/LibTimeZone/TimeZone.cpp +++ b/Userland/Libraries/LibTimeZone/TimeZone.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Tim Flynn + * Copyright (c) 2022-2024, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ @@ -8,11 +8,9 @@ #include #include #include -#include #include #include #include -#include #include namespace TimeZone { @@ -75,7 +73,7 @@ private: FILE* m_file { nullptr }; }; -StringView system_time_zone() +static StringView system_time_zone() { TimeZoneFile time_zone_file("r"); auto time_zone = time_zone_file.read_time_zone(); @@ -126,16 +124,9 @@ StringView current_time_zone() dbgln_if(TIME_ZONE_DEBUG, "Could not read the /etc/localtime link: {}", strerror(errno)); } - // Read the system timezone file /etc/timezone return system_time_zone(); } -ErrorOr change_time_zone([[maybe_unused]] StringView time_zone) -{ - // Do not even attempt to change the time zone of someone's host machine. - return {}; -} - ReadonlySpan __attribute__((weak)) all_time_zones() { #if !ENABLE_TIME_ZONE_DATA @@ -178,9 +169,6 @@ Optional canonicalize_time_zone(StringView time_zone) return canonical_time_zone; } -Optional __attribute__((weak)) daylight_savings_rule_from_string(StringView) { return {}; } -StringView __attribute__((weak)) daylight_savings_rule_to_string(DaylightSavingsRule) { return {}; } - Optional __attribute__((weak)) get_time_zone_offset([[maybe_unused]] TimeZone time_zone, AK::UnixDateTime) { #if !ENABLE_TIME_ZONE_DATA @@ -198,36 +186,6 @@ Optional get_time_zone_offset(StringView time_zone, AK::UnixDateTime tim return {}; } -Optional> __attribute__((weak)) get_named_time_zone_offsets([[maybe_unused]] TimeZone time_zone, AK::UnixDateTime) -{ -#if !ENABLE_TIME_ZONE_DATA - VERIFY(time_zone == TimeZone::UTC); - - NamedOffset utc_offset {}; - utc_offset.name = "UTC"sv; - - return Array { utc_offset, utc_offset }; -#else - return {}; -#endif -} - -Optional> get_named_time_zone_offsets(StringView time_zone, AK::UnixDateTime time) -{ - if (auto maybe_time_zone = time_zone_from_string(time_zone); maybe_time_zone.has_value()) - return get_named_time_zone_offsets(*maybe_time_zone, time); - return {}; -} - -Optional __attribute__((weak)) get_time_zone_location(TimeZone) { return {}; } - -Optional get_time_zone_location(StringView time_zone) -{ - if (auto maybe_time_zone = time_zone_from_string(time_zone); maybe_time_zone.has_value()) - return get_time_zone_location(*maybe_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 a345cc9eaa0..f5ffbefdccc 100644 --- a/Userland/Libraries/LibTimeZone/TimeZone.h +++ b/Userland/Libraries/LibTimeZone/TimeZone.h @@ -1,13 +1,11 @@ /* - * Copyright (c) 2022, Tim Flynn + * Copyright (c) 2022-2024, Tim Flynn * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once -#include -#include #include #include #include @@ -39,47 +37,16 @@ struct Offset { InDST in_dst { InDST::No }; }; -struct NamedOffset : public Offset { - ByteString name; -}; - -struct Coordinate { - constexpr float decimal_coordinate() const - { - return static_cast(degrees) + (static_cast(minutes) / 60.0f) + (static_cast(seconds) / 3'600.0f); - } - - i16 degrees { 0 }; - u8 minutes { 0 }; - u8 seconds { 0 }; -}; - -struct Location { - Coordinate latitude; - Coordinate longitude; -}; - -StringView system_time_zone(); StringView current_time_zone(); -ErrorOr change_time_zone(StringView time_zone); ReadonlySpan all_time_zones(); Optional time_zone_from_string(StringView time_zone); StringView time_zone_to_string(TimeZone time_zone); Optional canonicalize_time_zone(StringView time_zone); -Optional daylight_savings_rule_from_string(StringView daylight_savings_rule); -StringView daylight_savings_rule_to_string(DaylightSavingsRule daylight_savings_rule); - Optional get_time_zone_offset(TimeZone time_zone, AK::UnixDateTime time); Optional get_time_zone_offset(StringView time_zone, AK::UnixDateTime time); -Optional> get_named_time_zone_offsets(TimeZone time_zone, AK::UnixDateTime time); -Optional> get_named_time_zone_offsets(StringView time_zone, AK::UnixDateTime time); - -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);