diff mbox series

[2/2] libstdc++: Fix formatter for low-resolution chrono::zoned_time (LWG 4124)

Message ID 20240729175835.825721-2-jwakely@redhat.com
State New
Headers show
Series [1/2] libstdc++: Fix std::format output for std::chrono::zoned_time | expand

Commit Message

Jonathan Wakely July 29, 2024, 5:56 p.m. UTC
Tested x86_64-linux.

-- >8 --

This implements the proposed resolution of LWG 4124, so that
low-resolution chrono::zoned_time objects can be formatted. The
formatter for zoned_time<D, P> needs to account for get_local_time
returning local_time<common_type_t<D, seconds>> not local_time<D>.

libstdc++-v3/ChangeLog:

	* include/bits/chrono_io.h (__local_time_fmt_for): New alias
	template.
	(formatter<zoned_time<D, P>>): Use __local_time_fmt_for.
	* testsuite/std/time/zoned_time/io.cc: Check zoned_time<minutes>
	can be formatted.
---
 libstdc++-v3/include/bits/chrono_io.h            | 12 +++++++++---
 libstdc++-v3/testsuite/std/time/zoned_time/io.cc |  4 ++++
 2 files changed, 13 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h
index e7e7deb2cde..d8a4a121113 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -164,6 +164,12 @@  namespace __detail
       const string* _M_abbrev;
       const seconds* _M_offset_sec;
     };
+
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 4124. Cannot format zoned_time with resolution coarser than seconds
+  template<typename _Duration>
+    using __local_time_fmt_for
+      = __local_time_fmt<common_type_t<_Duration, seconds>>;
 }
 /// @endcond
 
@@ -2137,15 +2143,15 @@  namespace __format
 #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
   template<typename _Duration, typename _TimeZonePtr, typename _CharT>
     struct formatter<chrono::zoned_time<_Duration, _TimeZonePtr>, _CharT>
-    : formatter<chrono::__detail::__local_time_fmt<_Duration>, _CharT>
+    : formatter<chrono::__detail::__local_time_fmt_for<_Duration>, _CharT>
     {
       template<typename _FormatContext>
 	typename _FormatContext::iterator
 	format(const chrono::zoned_time<_Duration, _TimeZonePtr>& __tp,
 	       _FormatContext& __ctx) const
 	{
-	  using chrono::__detail::__local_time_fmt;
-	  using _Base = formatter<__local_time_fmt<_Duration>, _CharT>;
+	  using _Ltf = chrono::__detail::__local_time_fmt_for<_Duration>;
+	  using _Base = formatter<_Ltf, _CharT>;
 	  const chrono::sys_info __info = __tp.get_info();
 	  const auto __lf = chrono::local_time_format(__tp.get_local_time(),
 						      &__info.abbrev,
diff --git a/libstdc++-v3/testsuite/std/time/zoned_time/io.cc b/libstdc++-v3/testsuite/std/time/zoned_time/io.cc
index ee3b9edba81..c113eea6d3f 100644
--- a/libstdc++-v3/testsuite/std/time/zoned_time/io.cc
+++ b/libstdc++-v3/testsuite/std/time/zoned_time/io.cc
@@ -66,6 +66,10 @@  test_format()
   ws = std::format(L"{:+^34}", zoned_time<microseconds>(zone, t));
   VERIFY( ws == L"++2022-12-19 12:26:25.708000 EST++" );
 #endif
+
+  // LWG 4124. Cannot format zoned_time with resolution coarser than seconds
+  s = std::format("{}", zoned_time<minutes>(zone, time_point_cast<minutes>(t)));
+  VERIFY( s == "2022-12-19 12:26:00 EST" );
 }
 
 int main()