libstdc++: Fix formatter for low-resolution chrono::zoned_time (LWG 4124)

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.
This commit is contained in:
Jonathan Wakely 2024-07-29 12:52:40 +01:00 committed by Jonathan Wakely
parent 8f05ada7df
commit 4883c9571f
No known key found for this signature in database
2 changed files with 13 additions and 3 deletions

View file

@ -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,

View file

@ -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()