mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 20:27:45 +00:00
LibTimeZone: Parse and generate DST rule links for each ZONE entry
Each ZONE entry contains a RULES segment with one of the following: * A DST rule name, which links the ZONE to a RULE entry holding the DST rules to apply. * A static offset to be applied to the STDOFF offset. This implicitly means that the time zone is in DST during that time frame. * A "-" string, meaning no offset is applied to the STDOFF offset, and the time zone is in standard time during that time frame.
This commit is contained in:
parent
0e58b04b5c
commit
9dd4602636
1 changed files with 36 additions and 2 deletions
|
@ -33,6 +33,10 @@ struct DateTime {
|
||||||
struct TimeZoneOffset {
|
struct TimeZoneOffset {
|
||||||
i64 offset { 0 };
|
i64 offset { 0 };
|
||||||
Optional<DateTime> until;
|
Optional<DateTime> until;
|
||||||
|
|
||||||
|
Optional<String> dst_rule;
|
||||||
|
Optional<i32> dst_rule_index;
|
||||||
|
i64 dst_offset { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DaylightSavingsOffset {
|
struct DaylightSavingsOffset {
|
||||||
|
@ -76,10 +80,12 @@ struct AK::Formatter<TimeZoneOffset> : Formatter<FormatString> {
|
||||||
ErrorOr<void> format(FormatBuilder& builder, TimeZoneOffset const& time_zone_offset)
|
ErrorOr<void> format(FormatBuilder& builder, TimeZoneOffset const& time_zone_offset)
|
||||||
{
|
{
|
||||||
return Formatter<FormatString>::format(builder,
|
return Formatter<FormatString>::format(builder,
|
||||||
"{{ {}, {}, {} }}",
|
"{{ {}, {}, {}, {}, {} }}",
|
||||||
time_zone_offset.offset,
|
time_zone_offset.offset,
|
||||||
time_zone_offset.until.value_or({}),
|
time_zone_offset.until.value_or({}),
|
||||||
time_zone_offset.until.has_value());
|
time_zone_offset.until.has_value(),
|
||||||
|
time_zone_offset.dst_rule_index.value_or(-1),
|
||||||
|
time_zone_offset.dst_offset);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -158,6 +164,14 @@ static i64 parse_time_offset(StringView segment)
|
||||||
return (hours * 3600) + sign * ((minutes * 60) + seconds);
|
return (hours * 3600) + sign * ((minutes * 60) + seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parse_dst_rule(StringView segment, TimeZoneOffset& time_zone)
|
||||||
|
{
|
||||||
|
if (segment.contains(':'))
|
||||||
|
time_zone.dst_offset = parse_time_offset(segment);
|
||||||
|
else if (segment != "-"sv)
|
||||||
|
time_zone.dst_rule = segment;
|
||||||
|
}
|
||||||
|
|
||||||
static Vector<TimeZoneOffset>& parse_zone(StringView zone_line, TimeZoneData& time_zone_data)
|
static Vector<TimeZoneOffset>& parse_zone(StringView zone_line, TimeZoneData& time_zone_data)
|
||||||
{
|
{
|
||||||
auto segments = zone_line.split_view_if([](char ch) { return (ch == '\t') || (ch == ' '); });
|
auto segments = zone_line.split_view_if([](char ch) { return (ch == '\t') || (ch == ' '); });
|
||||||
|
@ -168,6 +182,7 @@ static Vector<TimeZoneOffset>& parse_zone(StringView zone_line, TimeZoneData& ti
|
||||||
|
|
||||||
TimeZoneOffset time_zone {};
|
TimeZoneOffset time_zone {};
|
||||||
time_zone.offset = parse_time_offset(segments[2]);
|
time_zone.offset = parse_time_offset(segments[2]);
|
||||||
|
parse_dst_rule(segments[3], time_zone);
|
||||||
|
|
||||||
if (segments.size() > 5)
|
if (segments.size() > 5)
|
||||||
time_zone.until = parse_date_time(segments.span().slice(5));
|
time_zone.until = parse_date_time(segments.span().slice(5));
|
||||||
|
@ -188,6 +203,7 @@ static void parse_zone_continuation(StringView zone_line, Vector<TimeZoneOffset>
|
||||||
// STDOFF RULES FORMAT [UNTIL]
|
// STDOFF RULES FORMAT [UNTIL]
|
||||||
TimeZoneOffset time_zone {};
|
TimeZoneOffset time_zone {};
|
||||||
time_zone.offset = parse_time_offset(segments[0]);
|
time_zone.offset = parse_time_offset(segments[0]);
|
||||||
|
parse_dst_rule(segments[1], time_zone);
|
||||||
|
|
||||||
if (segments.size() > 3)
|
if (segments.size() > 3)
|
||||||
time_zone.until = parse_date_time(segments.span().slice(3));
|
time_zone.until = parse_date_time(segments.span().slice(3));
|
||||||
|
@ -265,6 +281,19 @@ static ErrorOr<void> parse_time_zones(StringView time_zone_path, TimeZoneData& t
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_dst_rule_indices(TimeZoneData& time_zone_data)
|
||||||
|
{
|
||||||
|
for (auto& time_zone : time_zone_data.time_zones) {
|
||||||
|
for (auto& time_zone_offset : time_zone.value) {
|
||||||
|
if (!time_zone_offset.dst_rule.has_value())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto dst_rule_index = time_zone_data.dst_offset_names.find_first_index(*time_zone_offset.dst_rule);
|
||||||
|
time_zone_offset.dst_rule_index = static_cast<i32>(dst_rule_index.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static String format_identifier(StringView owner, String identifier)
|
static String format_identifier(StringView owner, String identifier)
|
||||||
{
|
{
|
||||||
constexpr auto gmt_time_zones = Array { "Etc/GMT"sv, "GMT"sv };
|
constexpr auto gmt_time_zones = Array { "Etc/GMT"sv, "GMT"sv };
|
||||||
|
@ -318,6 +347,8 @@ static void generate_time_zone_data_implementation(Core::File& file, TimeZoneDat
|
||||||
StringBuilder builder;
|
StringBuilder builder;
|
||||||
SourceGenerator generator { builder };
|
SourceGenerator generator { builder };
|
||||||
|
|
||||||
|
set_dst_rule_indices(time_zone_data);
|
||||||
|
|
||||||
generator.append(R"~~~(
|
generator.append(R"~~~(
|
||||||
#include <AK/Array.h>
|
#include <AK/Array.h>
|
||||||
#include <AK/BinarySearch.h>
|
#include <AK/BinarySearch.h>
|
||||||
|
@ -355,6 +386,9 @@ struct TimeZoneOffset {
|
||||||
|
|
||||||
DateTime until {};
|
DateTime until {};
|
||||||
bool has_until { false };
|
bool has_until { false };
|
||||||
|
|
||||||
|
i32 dst_rule { -1 };
|
||||||
|
i64 dst_offset { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DaylightSavingsOffset {
|
struct DaylightSavingsOffset {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue