On Wed, Jun 4, 2025 at 4:04 PM Jonathan Wakely <jwak...@redhat.com> wrote:

> On 04/06/25 13:06 +0200, Tomasz Kamiński wrote:
> >Adding a tests for behavior of the ostream operator and the formatting
> >with empty chronio-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.
> >---
> >The only change is mention of the duration test in commit message,
> >after the rebase. OK for trunk?
>
> OK with one comment added, as suggested below. Thanks.
>
>
> > .../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..1cb0066a608 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<C>(S, L##S)
> > #define WIDEN(S) WIDEN_(_CharT, S)
> >
> >+template<typename CharT, typename T>
> >+void
> >+test_no_empty_spec()
> >+{
> >+  try
> >+  {
> >+    T t{};
> >+
> >+    if constexpr (std::is_same_v<CharT, char>)
> >+      (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<typename T, typename _CharT>
> >+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<typename T, typename CharT>
> >+void verify(const T& t, const CharT* str)
> >+{ verify(t, std::basic_string_view<CharT>(str)); }
> >+
> > template<typename _CharT>
> > void
> > test_padding()
> >@@ -37,20 +77,6 @@ test_padding()
> >   VERIFY( res == WIDEN("==16 is not a valid month==") );
> > }
> >
> >-template<typename T, typename _CharT>
> >-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<typename Ret = void>
> > struct Rep
> > {
> >@@ -553,6 +579,159 @@ test_calendar()
> >   test_year_month_weekday_last<CharT>();
> > }
> >
> >+template<typename Clock, typename Dur, typename Dur2>
> >+constexpr auto
> >+wall_cast(const local_time<Dur2>& tp)
> >+{
> >+  using TP = time_point<Clock, std::common_type_t<Dur, days>>;
> >+  if constexpr (std::is_same_v<Clock, utc_clock> ||
> std::is_same_v<Clock, file_clock>)
> >+    return clock_cast<Clock>(wall_cast<system_clock, Dur>(tp));
> >+  else if constexpr (std::is_same_v<Clock, tai_clock>)
> >+    return TP(floor<Dur>(tp.time_since_epoch()) + days(4383));
> >+  else if constexpr (std::is_same_v<Clock, gps_clock>)
> >+    return TP(floor<Dur>(tp.time_since_epoch()) - days(3657));
> >+  else
>
> I would find "else // system_clock" helpful here, so that it's easier
> to quickly find which case is used for sys times. Otherwise I have to
> carefully read all the other cases to be sure they don't mention
> system_clock.
>
Added // system_clock, local_t
We also use local_t time to call the floor.
I was discussing with Howard having to_local/from_local and
clock_cast_conversion
specializations, to construct or fetch wall time. But then I failed to find
a good way to handle leap
seconds, as local_time cannot represent them.

>
> >+    return time_point<Clock, Dur>(floor<Dur>(tp.time_since_epoch()));
> >+}
> >+
> >+using decadays = duration<days::rep, std::ratio_multiply<std::deca,
> days::period>>;
> >+using kilodays = duration<days::rep, std::ratio_multiply<std::kilo,
> days::period>>;
> >+
> >+template<typename _CharT, typename Clock>
> >+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<Clock, nanoseconds>(lt),
> >+        WIDEN("2024-03-22 13:24:54.111222333") );
> >+  verify( wall_cast<Clock, microseconds>(lt),
> >+        WIDEN("2024-03-22 13:24:54.111222") );
> >+  verify( wall_cast<Clock, milliseconds>(lt),
> >+        WIDEN("2024-03-22 13:24:54.111") );
> >+  verify( wall_cast<Clock, seconds>(lt),
> >+        WIDEN("2024-03-22 13:24:54") );
> >+  verify( wall_cast<Clock, minutes>(lt),
> >+        WIDEN("2024-03-22 13:24:00") );
> >+  verify( wall_cast<Clock, hours>(lt),
> >+        WIDEN("2024-03-22 13:00:00") );
> >+  verify( wall_cast<Clock, days>(lt),
> >+        strip_time(WIDEN("2024-03-22 00:00:00")) );
> >+  verify( wall_cast<Clock, decadays>(lt),
> >+        strip_time(WIDEN("2024-03-18 00:00:00")) );
> >+  verify( wall_cast<Clock, kilodays>(lt),
> >+        strip_time(WIDEN("2022-01-08 00:00:00")) );
> >+}
> >+
> >+template<typename _CharT>
> >+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<utc_clock>(st);
> >+  tp += 1s;
> >+
> >+  verify( floor<nanoseconds>(tp),
> >+        WIDEN("2012-06-30 23:59:60.111222333") );
> >+  verify( floor<microseconds>(tp),
> >+        WIDEN("2012-06-30 23:59:60.111222") );
> >+  verify( floor<milliseconds>(tp),
> >+        WIDEN("2012-06-30 23:59:60.111") );
> >+  verify( floor<seconds>(tp),
> >+        WIDEN("2012-06-30 23:59:60") );
>
> Thanks for remembering to test the sneaky leap second case.
>
> >+}
> >+
> >+template<typename Dur, typename Dur2>
> >+auto
> >+make_zoned(const sys_time<Dur2>& st, const time_zone* tz)
> >+{ return zoned_time<Dur>(tz, floor<Dur>(st)); }
> >+
> >+template<typename _CharT>
> >+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<nanoseconds>(st, tz),
> >+        WIDEN("2024-03-22 15:24:54.111222333 EET") );
> >+  verify( make_zoned<microseconds>(st, tz),
> >+        WIDEN("2024-03-22 15:24:54.111222 EET") );
> >+  verify( make_zoned<milliseconds>(st, tz),
> >+        WIDEN("2024-03-22 15:24:54.111 EET") );
> >+  verify( make_zoned<seconds>(st, tz),
> >+        WIDEN("2024-03-22 15:24:54 EET") );
> >+  verify( make_zoned<minutes>(st, tz),
> >+        WIDEN("2024-03-22 15:24:00 EET") );
> >+  verify( make_zoned<hours>(st, tz),
> >+        WIDEN("2024-03-22 15:00:00 EET") );
> >+  verify( make_zoned<days>(st, tz),
> >+        WIDEN("2024-03-22 02:00:00 EET") );
> >+  verify( make_zoned<decadays>(st, tz),
> >+        WIDEN("2024-03-18 02:00:00 EET") );
> >+  verify( make_zoned<kilodays>(st, tz),
> >+        WIDEN("2022-01-08 02:00:00 EET") );
> >+}
> >+
> >+template<typename Dur, typename Dur2>
> >+auto
> >+local_fmt(const local_time<Dur2>& lt, std::string* zone)
> >+{ return local_time_format(floor<Dur>(lt), zone); }
> >+
> >+template<typename _CharT>
> >+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<nanoseconds>(lt, &abbrev));
> >+  VERIFY( res == WIDEN("2024-03-22 13:24:54.111222333 Zone") );
> >+  res = std::format(WIDEN("{}"), local_fmt<microseconds>(lt, &abbrev));
> >+  VERIFY( res == WIDEN("2024-03-22 13:24:54.111222 Zone") );
> >+  res = std::format(WIDEN("{}"), local_fmt<milliseconds>(lt, &abbrev));
> >+  VERIFY( res == WIDEN("2024-03-22 13:24:54.111 Zone") );
> >+  res = std::format(WIDEN("{}"), local_fmt<seconds>(lt, &abbrev));
> >+  VERIFY( res == WIDEN("2024-03-22 13:24:54 Zone") );
> >+  res = std::format(WIDEN("{}"), local_fmt<minutes>(lt, &abbrev));
> >+  VERIFY( res == WIDEN("2024-03-22 13:24:00 Zone") );
> >+  res = std::format(WIDEN("{}"), local_fmt<hours>(lt, &abbrev));
> >+  VERIFY( res == WIDEN("2024-03-22 13:00:00 Zone") );
> >+  res = std::format(WIDEN("{}"), local_fmt<days>(lt, &abbrev));
> >+  VERIFY( res == WIDEN("2024-03-22 00:00:00 Zone") );
> >+  res = std::format(WIDEN("{}"), local_fmt<decadays>(lt, &abbrev));
> >+  VERIFY( res == WIDEN("2024-03-18 00:00:00 Zone") );
> >+  res = std::format(WIDEN("{}"), local_fmt<kilodays>(lt, &abbrev));
> >+  VERIFY( res == WIDEN("2022-01-08 00:00:00 Zone") );
> >+}
> >+
> >+template<typename CharT>
> >+void
> >+test_time_points()
> >+{
> >+  test_time_point<CharT, local_t>(false);
> >+  test_time_point<CharT, system_clock>(false);
> >+  test_time_point<CharT, utc_clock>(true);
> >+  test_time_point<CharT, tai_clock>(true);
> >+  test_time_point<CharT, gps_clock>(true);
> >+  test_time_point<CharT, file_clock>(true);
> >+  test_leap_second<CharT>();
> >+  test_zoned_time<CharT>();
> >+  test_local_time_format<CharT>();
> >+
> >+  test_no_empty_spec<CharT, sys_time<years>>();
> >+  test_no_empty_spec<CharT, sys_time<duration<float>>>();
> >+}
> >+
> > template<typename CharT>
> > void
> > test_all()
> >@@ -560,6 +739,7 @@ test_all()
> >   test_padding<CharT>();
> >   test_durations<CharT>();
> >   test_calendar<CharT>();
> >+  test_time_points<CharT>();
> > }
> >
> > int main()
> >--
> >2.49.0
> >
> >
>
>

Reply via email to