From 3cfa53aa95a19c3b5fc711ad4d9f39ec9b8e7c3f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tomasz=20Kami=C5=84ski?= Date: Tue, 3 Jun 2025 11:40:17 +0200 Subject: [PATCH] libstdc++: Test for formatting with empty spec for time points. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Adding a tests for behavior of the ostream operator and the formatting with empty chrono-spec for the chrono types. Current coverage is: * time point, zoned_time and local_time_format in this commit, * duration and hh_mm_ss in r16-1099-gac0a04b7a254fb, * calendar types in r16-1016-g28a17985dd34b7. libstdc++-v3/ChangeLog: * testsuite/std/time/format/empty_spec.cc: New tests. Reviewed-by: Jonathan Wakely Signed-off-by: Tomasz Kamiński --- .../testsuite/std/time/format/empty_spec.cc | 208 ++++++++++++++++-- 1 file changed, 194 insertions(+), 14 deletions(-) diff --git a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc index 46942dc30fc..ec57a6f0d20 100644 --- a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc +++ b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc @@ -12,6 +12,46 @@ using namespace std::chrono; #define WIDEN_(C, S) ::std::__format::_Widen(S, L##S) #define WIDEN(S) WIDEN_(_CharT, S) +template +void +test_no_empty_spec() +{ + try + { + T t{}; + + if constexpr (std::is_same_v) + (void)std::vformat("{}", std::make_format_args(t)); +#ifdef _GLIBCXX_USE_WCHAR_T + else + (void)std::vformat(L"{}", std::make_wformat_args(t)); +#endif // _GLIBCXX_USE_WCHAR_T + VERIFY(false); + } + catch (const std::format_error&) + { + VERIFY(true); + } +} + +template +void verify(const T& t, std::basic_string_view<_CharT> str) +{ + std::basic_string<_CharT> res; + + res = std::format(WIDEN("{}"), t); + VERIFY( res == str ); + + std::basic_stringstream<_CharT> os; + os << t; + res = std::move(os).str(); + VERIFY( res == str ); +} + +template +void verify(const T& t, const CharT* str) +{ verify(t, std::basic_string_view(str)); } + template void test_padding() @@ -37,20 +77,6 @@ test_padding() VERIFY( res == WIDEN("==16 is not a valid month==") ); } -template -void verify(const T& t, const _CharT* str) -{ - std::basic_string<_CharT> res; - - res = std::format(WIDEN("{}"), t); - VERIFY( res == str ); - - std::basic_stringstream<_CharT> os; - os << t; - res = std::move(os).str(); - VERIFY( res == str ); -} - template struct Rep { @@ -553,6 +579,159 @@ test_calendar() test_year_month_weekday_last(); } +template +constexpr auto +wall_cast(const local_time& tp) +{ + using TP = time_point>; + if constexpr (std::is_same_v || std::is_same_v) + return clock_cast(wall_cast(tp)); + else if constexpr (std::is_same_v) + return TP(floor(tp.time_since_epoch()) + days(4383)); + else if constexpr (std::is_same_v) + return TP(floor(tp.time_since_epoch()) - days(3657)); + else // system_clock, local_t + return time_point(floor(tp.time_since_epoch())); +} + +using decadays = duration>; +using kilodays = duration>; + +template +void +test_time_point(bool daysAsTime) +{ + std::basic_string<_CharT> res; + + const auto lt = local_days(2024y/March/22) + 13h + 24min + 54s + 111222333ns; + auto strip_time = [daysAsTime](std::basic_string_view<_CharT> sv) + { return daysAsTime ? sv : sv.substr(0, 10); }; + + verify( wall_cast(lt), + WIDEN("2024-03-22 13:24:54.111222333") ); + verify( wall_cast(lt), + WIDEN("2024-03-22 13:24:54.111222") ); + verify( wall_cast(lt), + WIDEN("2024-03-22 13:24:54.111") ); + verify( wall_cast(lt), + WIDEN("2024-03-22 13:24:54") ); + verify( wall_cast(lt), + WIDEN("2024-03-22 13:24:00") ); + verify( wall_cast(lt), + WIDEN("2024-03-22 13:00:00") ); + verify( wall_cast(lt), + strip_time(WIDEN("2024-03-22 00:00:00")) ); + verify( wall_cast(lt), + strip_time(WIDEN("2024-03-18 00:00:00")) ); + verify( wall_cast(lt), + strip_time(WIDEN("2022-01-08 00:00:00")) ); +} + +template +void +test_leap_second() +{ + std::basic_string<_CharT> res; + + const auto st = sys_days(2012y/June/30) + 23h + 59min + 59s + 111222333ns; + auto tp = clock_cast(st); + tp += 1s; + + verify( floor(tp), + WIDEN("2012-06-30 23:59:60.111222333") ); + verify( floor(tp), + WIDEN("2012-06-30 23:59:60.111222") ); + verify( floor(tp), + WIDEN("2012-06-30 23:59:60.111") ); + verify( floor(tp), + WIDEN("2012-06-30 23:59:60") ); +} + +template +auto +make_zoned(const sys_time& st, const time_zone* tz) +{ return zoned_time(tz, floor(st)); } + +template +void +test_zoned_time() +{ + const auto st = sys_days(2024y/March/22) + 13h + 24min + 54s + 111222333ns; + const time_zone* tz = locate_zone("Europe/Sofia"); + VERIFY( tz != nullptr ); + + verify( make_zoned(st, tz), + WIDEN("2024-03-22 15:24:54.111222333 EET") ); + verify( make_zoned(st, tz), + WIDEN("2024-03-22 15:24:54.111222 EET") ); + verify( make_zoned(st, tz), + WIDEN("2024-03-22 15:24:54.111 EET") ); + verify( make_zoned(st, tz), + WIDEN("2024-03-22 15:24:54 EET") ); + verify( make_zoned(st, tz), + WIDEN("2024-03-22 15:24:00 EET") ); + verify( make_zoned(st, tz), + WIDEN("2024-03-22 15:00:00 EET") ); + verify( make_zoned(st, tz), + WIDEN("2024-03-22 02:00:00 EET") ); + verify( make_zoned(st, tz), + WIDEN("2024-03-18 02:00:00 EET") ); + verify( make_zoned(st, tz), + WIDEN("2022-01-08 02:00:00 EET") ); +} + +template +auto +local_fmt(const local_time& lt, std::string* zone) +{ return local_time_format(floor(lt), zone); } + +template +void +test_local_time_format() +{ + std::basic_string<_CharT> res; + + std::string abbrev = "Zone"; + const auto lt = local_days(2024y/March/22) + 13h + 24min + 54s + 111222333ns; + + res = std::format(WIDEN("{}"), local_fmt(lt, &abbrev)); + VERIFY( res == WIDEN("2024-03-22 13:24:54.111222333 Zone") ); + res = std::format(WIDEN("{}"), local_fmt(lt, &abbrev)); + VERIFY( res == WIDEN("2024-03-22 13:24:54.111222 Zone") ); + res = std::format(WIDEN("{}"), local_fmt(lt, &abbrev)); + VERIFY( res == WIDEN("2024-03-22 13:24:54.111 Zone") ); + res = std::format(WIDEN("{}"), local_fmt(lt, &abbrev)); + VERIFY( res == WIDEN("2024-03-22 13:24:54 Zone") ); + res = std::format(WIDEN("{}"), local_fmt(lt, &abbrev)); + VERIFY( res == WIDEN("2024-03-22 13:24:00 Zone") ); + res = std::format(WIDEN("{}"), local_fmt(lt, &abbrev)); + VERIFY( res == WIDEN("2024-03-22 13:00:00 Zone") ); + res = std::format(WIDEN("{}"), local_fmt(lt, &abbrev)); + VERIFY( res == WIDEN("2024-03-22 00:00:00 Zone") ); + res = std::format(WIDEN("{}"), local_fmt(lt, &abbrev)); + VERIFY( res == WIDEN("2024-03-18 00:00:00 Zone") ); + res = std::format(WIDEN("{}"), local_fmt(lt, &abbrev)); + VERIFY( res == WIDEN("2022-01-08 00:00:00 Zone") ); +} + +template +void +test_time_points() +{ + test_time_point(false); + test_time_point(false); + test_time_point(true); + test_time_point(true); + test_time_point(true); + test_time_point(true); + test_leap_second(); + test_zoned_time(); + test_local_time_format(); + + test_no_empty_spec>(); + test_no_empty_spec>>(); +} + template void test_all() @@ -560,6 +739,7 @@ test_all() test_padding(); test_durations(); test_calendar(); + test_time_points(); } int main() -- 2.47.2