summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp14
-rw-r--r--Tests/LibTimeZone/TestTimeZone.cpp4
2 files changed, 14 insertions, 4 deletions
diff --git a/Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp b/Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp
index 4762c63a05..adac6c3387 100644
--- a/Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp
+++ b/Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp
@@ -641,6 +641,7 @@ static Array<DaylightSavingsOffset const*, 2> find_dst_offsets(TimeZoneOffset co
DaylightSavingsOffset const* standard_offset = nullptr;
DaylightSavingsOffset const* daylight_offset = nullptr;
+ DaylightSavingsOffset const* last_offset = nullptr;
auto preferred_rule = [&](auto* current_offset, auto& new_offset) {
if (!current_offset)
@@ -652,6 +653,12 @@ static Array<DaylightSavingsOffset const*, 2> find_dst_offsets(TimeZoneOffset co
for (size_t index = 0; (index < dst_rules.size()) && (!standard_offset || !daylight_offset); ++index) {
auto const& dst_rule = dst_rules[index];
+
+ if (last_offset == nullptr)
+ last_offset = &dst_rule;
+ else if (dst_rule.time_in_effect(dst_rule.year_to) > last_offset->time_in_effect(last_offset->year_to))
+ last_offset = &dst_rule;
+
if ((time < dst_rule.year_from) || (time >= dst_rule.year_to))
continue;
@@ -661,11 +668,10 @@ static Array<DaylightSavingsOffset const*, 2> find_dst_offsets(TimeZoneOffset co
daylight_offset = preferred_rule(daylight_offset, dst_rule);
}
- // In modern times, there will always be a standard rule in the TZDB, but that isn't true in
- // all time zones in or before the early 1900s. For example, the "US" rules begin in 1918.
+ // If there isn't a standard or daylight rule in effect, fall back to the last rule given in the TZDB.
if (!standard_offset) {
- static DaylightSavingsOffset const empty_offset {};
- return { &empty_offset, &empty_offset };
+ VERIFY(last_offset != nullptr);
+ standard_offset = last_offset;
}
return { standard_offset, daylight_offset ? daylight_offset : standard_offset };
diff --git a/Tests/LibTimeZone/TestTimeZone.cpp b/Tests/LibTimeZone/TestTimeZone.cpp
index 1e44cffba2..7cf8a6fc2e 100644
--- a/Tests/LibTimeZone/TestTimeZone.cpp
+++ b/Tests/LibTimeZone/TestTimeZone.cpp
@@ -177,6 +177,10 @@ TEST_CASE(get_named_time_zone_offsets)
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