diff --git a/Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp b/Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp index 4762c63a05f..adac6c33876 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibTimeZone/GenerateTimeZoneData.cpp @@ -641,6 +641,7 @@ static Array 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 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 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 1e44cffba23..7cf8a6fc2e0 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