[gcc r14-12779] libstdc++: Fix condition for stopping lazy zone expansion [PR116110]
Tomasz Kaminski via Gcc-cvs <[email protected]> Fri, 31 Jul 2026 10:56:25 +0000 (GMT)
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <20260731105625.7132C4B35884__20646.5687647992$1785495409$gmane$org@sourceware.org> |
https://gcc.gnu.org/g:296b23d0b9e70cf8f416d0a502e0bfbf520fc4d4 commit r14-12779-g296b23d0b9e70cf8f416d0a502e0bfbf520fc4d4 Author: Tomasz Kamiński <[email protected]> Date: Fri Jul 17 21:14:42 2026 +0200 libstdc++: Fix condition for stopping lazy zone expansion [PR116110] At indicated by the pre-existing comment, the lazy zone expansion can be only resumed from STD (save == 0) zone. However, the current condition for stopping on DST (save != 0) doesn't ensure that, as some rule specify transitions between DST zones. For example August 1945 of Y rule used by America/Dawson only change letters: Y 1942 o - F 9 2 1 W Y 1945 o - Au 14 23u 1 P This patch correct the condition, by using next_rule (i.e. one applying after last expanded zone): either there is no zone (last expanded range) or it have save zero. libstdc++-v3/ChangeLog: PR libstdc++/116110 * src/c++20/tzdb.cc (time_zone::_M_get_sys_info): Correct condition for stopping zone expansion before STD zone. * testsuite/std/time/time_zone/116110.cc (test_dawson): Add test for America/Dawson August 1945 transition. Reviewed-by: Jonathan Wakely <[email protected]> Signed-off-by: Tomasz Kamiński <[email protected]> (cherry picked from commit 57a09e2f362ab8a8be84250fd4266b333a74b977) Diff: --- libstdc++-v3/src/c++20/tzdb.cc | 4 +-- .../testsuite/std/time/time_zone/116110.cc | 41 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/libstdc++-v3/src/c++20/tzdb.cc b/libstdc++-v3/src/c++20/tzdb.cc index 3c19f5c6467c..25dd5d2e4de2 100644 --- a/libstdc++-v3/src/c++20/tzdb.cc +++ b/libstdc++-v3/src/c++20/tzdb.cc @@ -989,10 +989,10 @@ namespace std::chrono result_index = new_infos.size() - 1; else if (result_index >= 0 && !merged) { - // Finish on a DST sys_info if possible, so that if we resume + // Finish before a STD sys_info if possible, so that if we resume // generating sys_info objects after this time point, save=0 // should be correct for the next sys_info. - if (num_after > 1 || info.save != 0min) + if (num_after > 1 || !next_rule || next_rule->save == 0s) --num_after; } diff --git a/libstdc++-v3/testsuite/std/time/time_zone/116110.cc b/libstdc++-v3/testsuite/std/time/time_zone/116110.cc index 26b9ba33c316..3751c5df910c 100644 --- a/libstdc++-v3/testsuite/std/time/time_zone/116110.cc +++ b/libstdc++-v3/testsuite/std/time/time_zone/116110.cc @@ -78,9 +78,50 @@ test_apia() VERIFY( info.abbrev == "+14" ); } +void +test_dawson() +{ + /* 1945 August rule change changes letters (abbrev) + and remains in DST: + R Y 1942 o - F 9 2 1 W + R Y 1945 o - Au 14 23u 1 P + R Y 1945 o - S 30 2 0 S + Z America/Dawson -9:17:40 - LMT 1900 Au 20 + -9 Y Y%sT 1965 + -9 Yu Y%sT 1973 O 28 + */ + + auto* tz = locate_zone("America/Dawson"); + + // Triggers rule transitions from the start. + sys_info info = tz->get_info(sys_days(1900y/August/20) + 10h); + VERIFY( info.offset == -9h ); + VERIFY( info.save == 0min ); + VERIFY( info.abbrev == "YST" ); + + // Check YWT transition at 02:00 + 9h UT, that is DST + info = tz->get_info(sys_days(1942y/February/9) + 11h); + VERIFY( info.offset == -8h ); + VERIFY( info.save == 60min ); + VERIFY( info.abbrev == "YWT" ); + + // Check YPT transition at 23:00 UT, remains DST + info = tz->get_info(sys_days(1945y/August/14) + 23h); + VERIFY( info.offset == -8h ); + VERIFY( info.save == 60min ); + VERIFY( info.abbrev == "YPT" ); + + // Check YST transition at 02:00 + 8h UT, switches to STD + info = tz->get_info(sys_days(1945y/September/30) + 10h); + VERIFY( info.offset == -9h ); + VERIFY( info.save == 0min ); + VERIFY( info.abbrev == "YST" ); +} + int main() { test_broken_hill(); test_kiritimati(); test_apia(); + test_dawson(); }