From f8d207badba23d2ba49dccd04ee2b23541e7ff87 Mon Sep 17 00:00:00 2001 From: Daksh Goyal <39990619+daksh-goyal@users.noreply.github.com> Date: Sat, 21 Feb 2026 15:56:12 -0800 Subject: [PATCH 1/4] fix: improper use of ucal_inDaylightTime `ucal_inDaylightTime` is used to check whether the timezone is currently observing DST. STL (likely in an attempt to be defensive) tries to use it as a way to tell whether the timezone observed DST on the date in question (which could be in the past), which is wrong. --- stl/src/tzdb.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/stl/src/tzdb.cpp b/stl/src/tzdb.cpp index 511951451b7..0c841fc9ab0 100644 --- a/stl/src/tzdb.cpp +++ b/stl/src/tzdb.cpp @@ -146,11 +146,6 @@ namespace { return _Fun(status); } - [[nodiscard]] UBool __icu_ucal_inDaylightTime(const UCalendar* cal, UErrorCode* status) noexcept { - const auto _Fun = _Icu_functions._Pfn_ucal_inDaylightTime.load(_STD memory_order_relaxed); - return _Fun(cal, status); - } - [[nodiscard]] UCalendar* __icu_ucal_open( const UChar* zoneID, int32_t len, const char* locale, UCalendarType type, UErrorCode* status) noexcept { const auto _Fun = _Icu_functions._Pfn_ucal_open.load(_STD memory_order_relaxed); @@ -519,12 +514,7 @@ void __stdcall __std_tzdb_delete_current_zone(__std_tzdb_current_zone_info* cons return _Report_error(_Info, __std_tzdb_error::_Icu_error); } - const auto _Is_daylight = __icu_ucal_inDaylightTime(_Cal.get(), &_UErr); - if (U_FAILURE(_UErr)) { - return _Report_error(_Info, __std_tzdb_error::_Icu_error); - } - - _Info->_Save = _Is_daylight ? __icu_ucal_get(_Cal.get(), UCalendarDateFields::UCAL_DST_OFFSET, &_UErr) : 0; + _Info->_Save = __icu_ucal_get(_Cal.get(), UCalendarDateFields::UCAL_DST_OFFSET, &_UErr); if (U_FAILURE(_UErr)) { return _Report_error(_Info, __std_tzdb_error::_Icu_error); } @@ -665,3 +655,4 @@ void __stdcall __std_free_crt(void* p) noexcept { } } // extern "C" + From 851bdb6f1f898c12e72f0f6bd53f96c77252b548 Mon Sep 17 00:00:00 2001 From: Daksh Goyal <39990619+daksh-goyal@users.noreply.github.com> Date: Sat, 21 Feb 2026 17:01:13 -0800 Subject: [PATCH 2/4] fix: dropped lingering bad references and removed dead code --- stl/src/tzdb.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/stl/src/tzdb.cpp b/stl/src/tzdb.cpp index 0c841fc9ab0..bad8b2f1ae2 100644 --- a/stl/src/tzdb.cpp +++ b/stl/src/tzdb.cpp @@ -30,7 +30,6 @@ namespace { _STD atomic _Pfn_ucal_getTimeZoneDisplayName{nullptr}; _STD atomic _Pfn_ucal_getTimeZoneTransitionDate{nullptr}; _STD atomic _Pfn_ucal_getTZDataVersion{nullptr}; - _STD atomic _Pfn_ucal_inDaylightTime{nullptr}; _STD atomic _Pfn_ucal_open{nullptr}; _STD atomic _Pfn_ucal_openTimeZoneIDEnumeration{nullptr}; _STD atomic _Pfn_ucal_setMillis{nullptr}; @@ -78,7 +77,6 @@ namespace { _Load_address(_Icu_module, _Icu_functions._Pfn_ucal_getTimeZoneTransitionDate, "ucal_getTimeZoneTransitionDate", _Last_error); _Load_address(_Icu_module, _Icu_functions._Pfn_ucal_getTZDataVersion, "ucal_getTZDataVersion", _Last_error); - _Load_address(_Icu_module, _Icu_functions._Pfn_ucal_inDaylightTime, "ucal_inDaylightTime", _Last_error); _Load_address(_Icu_module, _Icu_functions._Pfn_ucal_open, "ucal_open", _Last_error); _Load_address(_Icu_module, _Icu_functions._Pfn_ucal_openTimeZoneIDEnumeration, "ucal_openTimeZoneIDEnumeration", _Last_error); @@ -550,7 +548,7 @@ void __stdcall __std_tzdb_delete_current_zone(__std_tzdb_current_zone_info* cons } int32_t _Abbrev_len{}; - const auto _Abbrev = _Get_timezone_short_id(_Cal.get(), _Is_daylight, _Abbrev_len, _Info->_Err); + const auto _Abbrev = _Get_timezone_short_id(_Cal.get(), _Info->_Save != 0, _Abbrev_len, _Info->_Err); if (_Abbrev == nullptr) { return _Propagate_error(_Info); } @@ -655,4 +653,3 @@ void __stdcall __std_free_crt(void* p) noexcept { } } // extern "C" - From 4e26d2b244e1fde560b6a50eabb44eb48afa5d2c Mon Sep 17 00:00:00 2001 From: Daksh Goyal <39990619+daksh-goyal@users.noreply.github.com> Date: Sat, 21 Feb 2026 18:08:24 -0800 Subject: [PATCH 3/4] test: implement tests for historical DST abolition offsets Added regression tests for timezones that abolished DST to ensure correct historical offsets. --- .../test.cpp | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_time_zones/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_time_zones/test.cpp index fdfa456263b..a016cadc252 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_time_zones/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_time_zones/test.cpp @@ -402,6 +402,31 @@ void timezone_sorted_vectors_test() { assert(ranges::is_sorted(my_tzdb.leap_seconds)); } +void timezone_historical_dst_abolished_test() { + // Regression test: timezones that abolished DST must still report + // correct historical offsets for dates when DST was active. + const auto& my_tzdb = get_tzdb(); + + { // America/Sao_Paulo - abolished DST Feb 2019 + auto tz = my_tzdb.locate_zone("America/Sao_Paulo"); + auto info = tz->get_info(sys_days{year{2019} / January / day{1}}); + assert(info.offset == seconds{-7200}); + assert(info.save == minutes{60}); + } + { // Europe/Istanbul - abolished DST Sep 2016 + auto tz = my_tzdb.locate_zone("Europe/Istanbul"); + auto info = tz->get_info(sys_days{year{2016} / July / day{1}}); + assert(info.offset == seconds{10800}); + assert(info.save == minutes{60}); + } + { // Europe/Moscow - abolished DST Oct 2014 + auto tz = my_tzdb.locate_zone("Europe/Moscow"); + auto info = tz->get_info(sys_days{year{2010} / July / day{1}}); + assert(info.offset == seconds{14400}); + assert(info.save == minutes{60}); + } +} + void test() { timezone_tzdb_list_test(); timezone_version_test(); @@ -411,6 +436,7 @@ void test() { timezone_local_info_test(); timezone_precision_test(); timezone_sorted_vectors_test(); + timezone_historical_dst_abolished_test(); } int main() { From 97426cc747825f38dbd9f3b135fc2cd5f072c927 Mon Sep 17 00:00:00 2001 From: Daksh Goyal <39990619+daksh-goyal@users.noreply.github.com> Date: Sat, 21 Feb 2026 18:31:12 -0800 Subject: [PATCH 4/4] fix: code formatting --- .../test.cpp | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/std/tests/P0355R7_calendars_and_time_zones_time_zones/test.cpp b/tests/std/tests/P0355R7_calendars_and_time_zones_time_zones/test.cpp index a016cadc252..7af9458b46c 100644 --- a/tests/std/tests/P0355R7_calendars_and_time_zones_time_zones/test.cpp +++ b/tests/std/tests/P0355R7_calendars_and_time_zones_time_zones/test.cpp @@ -403,28 +403,28 @@ void timezone_sorted_vectors_test() { } void timezone_historical_dst_abolished_test() { - // Regression test: timezones that abolished DST must still report - // correct historical offsets for dates when DST was active. - const auto& my_tzdb = get_tzdb(); - - { // America/Sao_Paulo - abolished DST Feb 2019 - auto tz = my_tzdb.locate_zone("America/Sao_Paulo"); - auto info = tz->get_info(sys_days{year{2019} / January / day{1}}); - assert(info.offset == seconds{-7200}); - assert(info.save == minutes{60}); - } - { // Europe/Istanbul - abolished DST Sep 2016 - auto tz = my_tzdb.locate_zone("Europe/Istanbul"); - auto info = tz->get_info(sys_days{year{2016} / July / day{1}}); - assert(info.offset == seconds{10800}); - assert(info.save == minutes{60}); - } - { // Europe/Moscow - abolished DST Oct 2014 - auto tz = my_tzdb.locate_zone("Europe/Moscow"); - auto info = tz->get_info(sys_days{year{2010} / July / day{1}}); - assert(info.offset == seconds{14400}); - assert(info.save == minutes{60}); - } + // Regression test: timezones that abolished DST must still report + // correct historical offsets for dates when DST was active. + const auto& my_tzdb = get_tzdb(); + + { // America/Sao_Paulo - abolished DST Feb 2019 + auto tz = my_tzdb.locate_zone("America/Sao_Paulo"); + auto info = tz->get_info(sys_days{year{2019} / January / day{1}}); + assert(info.offset == seconds{-7200}); + assert(info.save == minutes{60}); + } + { // Europe/Istanbul - abolished DST Sep 2016 + auto tz = my_tzdb.locate_zone("Europe/Istanbul"); + auto info = tz->get_info(sys_days{year{2016} / July / day{1}}); + assert(info.offset == seconds{10800}); + assert(info.save == minutes{60}); + } + { // Europe/Moscow - abolished DST Oct 2014 + auto tz = my_tzdb.locate_zone("Europe/Moscow"); + auto info = tz->get_info(sys_days{year{2010} / July / day{1}}); + assert(info.offset == seconds{14400}); + assert(info.save == minutes{60}); + } } void test() {