LibTimeZone: Remove entirely unused time zone methods

Evaluating third-party alternatives to LibTimeZone will be simpler with
unused functionality removed.
This commit is contained in:
Timothy Flynn 2024-06-23 16:54:10 -04:00 committed by Andreas Kling
parent be0dca8da3
commit 3c23ce9007
4 changed files with 5 additions and 228 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
* Copyright (c) 2022-2024, Tim Flynn <trflynn89@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -63,8 +63,6 @@ struct TimeZoneData {
HashMap<ByteString, Vector<DaylightSavingsOffset>> dst_offsets;
Vector<ByteString> dst_offset_names;
HashMap<ByteString, TimeZone::Location> time_zone_coordinates;
HashMap<ByteString, Vector<size_t>> time_zone_regions;
Vector<ByteString> time_zone_region_names;
@ -140,29 +138,6 @@ struct AK::Formatter<TimeZone::TimeZoneIdentifier> : Formatter<FormatString> {
}
};
template<>
struct AK::Formatter<TimeZone::Coordinate> : Formatter<FormatString> {
ErrorOr<void> format(FormatBuilder& builder, TimeZone::Coordinate const& coordinate)
{
return Formatter<FormatString>::format(builder,
"{{ {}, {}, {} }}"sv,
coordinate.degrees,
coordinate.minutes,
coordinate.seconds);
}
};
template<>
struct AK::Formatter<TimeZone::Location> : Formatter<FormatString> {
ErrorOr<void> format(FormatBuilder& builder, TimeZone::Location const& location)
{
return Formatter<FormatString>::format(builder,
"{{ {}, {} }}"sv,
location.latitude,
location.longitude);
}
};
static Optional<DateTime> parse_date_time(ReadonlySpan<StringView> segments)
{
auto comment_index = find_index(segments.begin(), segments.end(), "#"sv);
@ -363,35 +338,6 @@ static ErrorOr<void> parse_time_zones(StringView time_zone_path, TimeZoneData& t
static ErrorOr<void> 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<int>().value();
parsed.minutes = coordinate.substring_view(3).template to_number<int>().value();
} else if (coordinate.length() == 6) {
// ±DDDMM
parsed.degrees = coordinate.substring_view(0, 4).template to_number<int>().value();
parsed.minutes = coordinate.substring_view(4).template to_number<int>().value();
} else if (coordinate.length() == 7) {
// ±DDMMSS
parsed.degrees = coordinate.substring_view(0, 3).template to_number<int>().value();
parsed.minutes = coordinate.substring_view(3, 2).template to_number<int>().value();
parsed.seconds = coordinate.substring_view(5).template to_number<int>().value();
} else if (coordinate.length() == 8) {
// ±DDDDMMSS
parsed.degrees = coordinate.substring_view(0, 4).template to_number<int>().value();
parsed.minutes = coordinate.substring_view(4, 2).template to_number<int>().value();
parsed.seconds = coordinate.substring_view(6).template to_number<int>().value();
} else {
VERIFY_NOT_REACHED();
}
return parsed;
};
Array<u8, 1024> buffer {};
while (TRY(file.can_read_line())) {
@ -402,17 +348,10 @@ static ErrorOr<void> 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<void> {
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<Location, @size@> 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<Alias> const& aliases = {}) -> ErrorOr<void> {
HashValueMap<ByteString> hashes;
TRY(hashes.try_ensure_capacity(values.size()));
@ -647,7 +574,6 @@ static constexpr Array<Location, @size@> 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<Offset> get_time_zone_offset(TimeZone time_zone, AK::UnixDateTime time)
return dst_offset;
}
Optional<Array<NamedOffset, 2>> get_named_time_zone_offsets(TimeZone time_zone, AK::UnixDateTime time)
{
auto const& time_zone_offset = find_time_zone_offset(time_zone, time);
Array<NamedOffset, 2> 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<Location> 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<StringView> time_zones_in_region(StringView region)
{
auto region_value = region_from_string(region);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
* Copyright (c) 2022-2024, Tim Flynn <trflynn89@serenityos.org>
*
* 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)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
* Copyright (c) 2022-2024, Tim Flynn <trflynn89@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -8,11 +8,9 @@
#include <AK/Debug.h>
#include <AK/ScopeGuard.h>
#include <LibTimeZone/TimeZone.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
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<void> change_time_zone([[maybe_unused]] StringView time_zone)
{
// Do not even attempt to change the time zone of someone's host machine.
return {};
}
ReadonlySpan<TimeZoneIdentifier> __attribute__((weak)) all_time_zones()
{
#if !ENABLE_TIME_ZONE_DATA
@ -178,9 +169,6 @@ Optional<StringView> canonicalize_time_zone(StringView time_zone)
return canonical_time_zone;
}
Optional<DaylightSavingsRule> __attribute__((weak)) daylight_savings_rule_from_string(StringView) { return {}; }
StringView __attribute__((weak)) daylight_savings_rule_to_string(DaylightSavingsRule) { return {}; }
Optional<Offset> __attribute__((weak)) get_time_zone_offset([[maybe_unused]] TimeZone time_zone, AK::UnixDateTime)
{
#if !ENABLE_TIME_ZONE_DATA
@ -198,36 +186,6 @@ Optional<Offset> get_time_zone_offset(StringView time_zone, AK::UnixDateTime tim
return {};
}
Optional<Array<NamedOffset, 2>> __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<Array<NamedOffset, 2>> 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<Location> __attribute__((weak)) get_time_zone_location(TimeZone) { return {}; }
Optional<Location> 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<Region> __attribute__((weak)) region_from_string(StringView) { return {}; }
StringView __attribute__((weak)) region_to_string(Region) { return {}; }
Vector<StringView> __attribute__((weak)) time_zones_in_region(StringView) { return {}; }

View File

@ -1,13 +1,11 @@
/*
* Copyright (c) 2022, Tim Flynn <trflynn89@serenityos.org>
* Copyright (c) 2022-2024, Tim Flynn <trflynn89@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Array.h>
#include <AK/ByteString.h>
#include <AK/Error.h>
#include <AK/Format.h>
#include <AK/Optional.h>
@ -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<float>(degrees) + (static_cast<float>(minutes) / 60.0f) + (static_cast<float>(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<void> change_time_zone(StringView time_zone);
ReadonlySpan<TimeZoneIdentifier> all_time_zones();
Optional<TimeZone> time_zone_from_string(StringView time_zone);
StringView time_zone_to_string(TimeZone time_zone);
Optional<StringView> canonicalize_time_zone(StringView time_zone);
Optional<DaylightSavingsRule> daylight_savings_rule_from_string(StringView daylight_savings_rule);
StringView daylight_savings_rule_to_string(DaylightSavingsRule daylight_savings_rule);
Optional<Offset> get_time_zone_offset(TimeZone time_zone, AK::UnixDateTime time);
Optional<Offset> get_time_zone_offset(StringView time_zone, AK::UnixDateTime time);
Optional<Array<NamedOffset, 2>> get_named_time_zone_offsets(TimeZone time_zone, AK::UnixDateTime time);
Optional<Array<NamedOffset, 2>> get_named_time_zone_offsets(StringView time_zone, AK::UnixDateTime time);
Optional<Location> get_time_zone_location(TimeZone time_zone);
Optional<Location> get_time_zone_location(StringView time_zone);
Optional<Region> region_from_string(StringView region);
StringView region_to_string(Region region);
Vector<StringView> time_zones_in_region(StringView region);