On Fri, 17 Jul 2026, 20:37 Tomasz Kamiński, <[email protected]> wrote:
> 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 Y rule used by America/Dawson > August 1945 transion 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 (we default to STD) > 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 geration before STD zone. > * testsuite/std/time/time_zone/116110.cc (test_dawson): > Add test for America/Dawson August 1945 transition. > --- > This addresses the root cause and provides much more targeted solution > for the problem described "Always seed info.offset and info.save from > the active rule." in Alvaro 5/5 patch: > https://gcc.gnu.org/pipermail/libstdc++/2026-May/066526.html. > > As this change is very minimal and affect only cases of sequence of > DST zones (we expand more zones), I think this is very safe to backport. > Yes, this is a nice simple fix. > Testing on x86_64-linux. *time_zone* test passed, in all standard modes > and -m32/debug. OK for trunk and GCC-16. > OK for both, thanks > 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 460a242fed1..99b3ed58d95 100644 > --- a/libstdc++-v3/src/c++20/tzdb.cc > +++ b/libstdc++-v3/src/c++20/tzdb.cc > @@ -1231,10 +1231,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 1ec01d35955..45daed8c050 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(); > } > -- > 2.55.0 > >
