On Thu, Jul 23, 2026 at 1:13 PM Jonathan Wakely <[email protected]> wrote:
> On Thu, 23 Jul 2026 at 12:03, Tomasz Kaminski <[email protected]> wrote: > > > > > > > > On Thu, Jul 23, 2026 at 12:47 PM Jonathan Wakely <[email protected]> > wrote: > >> > >> On Wed, 01 Jul 2026 at 14:33 +0200, Tomasz Kaminski wrote: > >> >On Wed, Jul 1, 2026 at 2:15 PM Anlai Lu <[email protected]> wrote: > >> > > >> >> Add __detail::__chrono_write which formats a chrono object into a > >> >> stack buffer via std::format_to_n with _S_empty_fs(), then writes > >> >> through __ostream_insert. A non-type template parameter _BufSize > >> >> (default 128) allows per-type buffer tuning. Each _BufSize is the > >> >> smallest power of two that accommodates the longest possible > formatted > >> >> output for that type, including error cases. All chrono operator<< > >> >> overloads that previously used std::format, std::vformat, or > >> >> basic_stringstream now use this helper. > >> >> > >> >> libstdc++-v3/ChangeLog: > >> >> > >> >> * include/bits/chrono_io.h (__formatter_chrono::_S_empty_fs): > >> >> Make public. > >> >> (__detail::__chrono_write): New function template. > >> >> (operator<<): Use __chrono_write consistently for all chrono > >> >> types. > >> >> > >> >> Signed-off-by: Anlai Lu <[email protected]> > >> >> --- > >> >> libstdc++-v3/include/bits/chrono_io.h | 244 > ++++++-------------------- > >> >> 1 file changed, 52 insertions(+), 192 deletions(-) > >> >> > >> >LGTM. Thank you for working on this. > >> > > >> >> > >> >> diff --git a/libstdc++-v3/include/bits/chrono_io.h > >> >> b/libstdc++-v3/include/bits/chrono_io.h > >> >> index f8bb485d1..d3740a0e1 100644 > >> >> --- a/libstdc++-v3/include/bits/chrono_io.h > >> >> +++ b/libstdc++-v3/include/bits/chrono_io.h > >> >> @@ -884,11 +884,13 @@ namespace __format > >> >> static constexpr const _CharT* _S_minus_empty_spec = _S_chars > + 17; > >> >> static constexpr const _CharT* _S_empty_spec = _S_chars + 18; > >> >> > >> >> + public: > >> >> [[__gnu__::__always_inline__]] > >> >> static _Dynamic_format_string<_CharT> > >> >> _S_empty_fs() > >> >> { return _Dynamic_format_string<_CharT>(_S_empty_spec); } > >> >> > >> >> + protected: > >> >> static constexpr const _CharT* _S_weekdays[] > >> >> { > >> >> _GLIBCXX_WIDEN("Sunday"), > >> >> @@ -3607,6 +3609,30 @@ namespace __detail > >> >> } > >> >> } > >> >> > >> >> + // Format into a stack buffer via std::format_to_n with the empty > >> >> + // chrono-spec (_S_empty_fs), then write through __ostream_insert. > >> >> + // The empty spec lets each formatter use its __defSpec, producing > >> >> + // output equivalent to the corresponding operator<<. > >> >> + // _BufSize allows per-type tuning of the stack buffer size. > >> >> + template<size_t _BufSize = 128, typename _CharT, typename _Traits, > >> >> > >> >I am wondering about making buffer size explicit on each call, and > >> >removing the default. But I will handle that before committing, if > Jonathan > >> >also like that direction. > >> > >> What would be the advantage of requiring it explicitly every time? > > > > You immediately see what buffer size is expected for each type of chrono > object, > > and if we remove the default, it will force you to think of one instead > of defaulting > > to 128. > > I don't have any strong opinion on that. 128 characters is not a lot > of stack space to use (anybody formatting wide strings can probably > afford the 512 bytes it uses) so I think the default is OK. But if you > want to change it before pushing, that's fine. > Will do that. > > >> > >> > >> >> + typename _Arg, typename... _OptLocale> > >> >> + inline basic_ostream<_CharT, _Traits>& > >> >> + __chrono_write(basic_ostream<_CharT, _Traits>& __os, > >> >> + const _Arg& __arg, const _OptLocale&... __loc) > >> >> + { > >> >> + static_assert(sizeof...(_OptLocale) <= 1); > >> >> + constexpr auto __fs > >> >> + = __format::__formatter_chrono<_CharT>::_S_empty_fs; > >> >> > >> >Nice trick for storing a function pointer. I really like it. > >> > >> We could just make _S_empty_spec public, and then use that instead of > >> _S_empty_fs(), right? > > > > Passing char const*, trigger format_string constructor from that, that > will perform > > a compile time check for the format string. That will increase compile > time for no > > good reason. > > Oh yes, of course. > > > > >> > >> > >> That seems simpler to me. > >> > >> constexpr auto __fs = > __format::__formatter_chrono<_CharT>::_S_empty_spec; > >> > >> and then just use __fs instead of __fs() > > > > We could do that if we then use vformat, and > make_format_args/make_wformat_args, > > to avoid compile-time checks. > > We could change std::format to std::vformat, but there's no > std:vformat_to_n. > > So the patch is OK as-is. Could you push it please? > I will handle that. Thanks for review. > If you want to remove the =128 default that's OK, your call. > > >> > >> > >> >> + constexpr size_t __bufsize = _BufSize; > >> >> + _CharT __buf[__bufsize]; > >> >> + auto __res = std::format_to_n(__buf, __bufsize, __loc..., > >> >> + __fs(), __arg); > >> >> + if (static_cast<size_t>(__res.size) <= __bufsize) [[likely]] > >> >> + return std::__ostream_insert(__os, __buf, __res.size); > >> >> + auto __s = std::format(__loc..., __fs(), __arg); > >> >> + return std::__ostream_insert(__os, __s.data(), __s.size()); > >> >> + } > >> >> + > >> >> } // namespace __detail > >> >> /// @endcond > >> >> > >> >> @@ -3629,14 +3655,7 @@ namespace __detail > >> >> inline basic_ostream<_CharT, _Traits>& > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, const day& __d) > >> >> { > >> >> - using _Ctx = __format::__format_context<_CharT>; > >> >> - using _Str = basic_string_view<_CharT>; > >> >> - _Str __s = _GLIBCXX_WIDEN("{:02d} is not a valid day"); > >> >> - if (__d.ok()) > >> >> - __s = __s.substr(0, 6); > >> >> - auto __u = (unsigned)__d; > >> >> - __os << std::vformat(__s, make_format_args<_Ctx>(__u)); > >> >> - return __os; > >> >> + return __detail::__chrono_write<32>(__os, __d); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits, > >> >> @@ -3657,18 +3676,7 @@ namespace __detail > >> >> inline basic_ostream<_CharT, _Traits>& > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, const month& > __m) > >> >> { > >> >> - using _Ctx = __format::__format_context<_CharT>; > >> >> - using _Str = basic_string_view<_CharT>; > >> >> - _Str __s = _GLIBCXX_WIDEN("{:L%b}{} is not a valid month"); > >> >> - if (__m.ok()) > >> >> - __os << std::vformat(__os.getloc(), __s.substr(0, 6), > >> >> - make_format_args<_Ctx>(__m)); > >> >> - else > >> >> - { > >> >> - auto __u = (unsigned)__m; > >> >> - __os << std::vformat(__s.substr(6), > make_format_args<_Ctx>(__u)); > >> >> - } > >> >> - return __os; > >> >> + return __detail::__chrono_write(__os, __m, __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits, > >> >> @@ -3689,18 +3697,7 @@ namespace __detail > >> >> inline basic_ostream<_CharT, _Traits>& > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, const year& > __y) > >> >> { > >> >> - using _Ctx = __format::__format_context<_CharT>; > >> >> - using _Str = basic_string_view<_CharT>; > >> >> - _Str __s = _GLIBCXX_WIDEN("-{:04d} is not a valid year"); > >> >> - if (__y.ok()) > >> >> - __s = __s.substr(0, 7); > >> >> - int __i = (int)__y; > >> >> - if (__i >= 0) [[likely]] > >> >> - __s.remove_prefix(1); > >> >> - else > >> >> - __i = -__i; > >> >> - __os << std::vformat(__s, make_format_args<_Ctx>(__i)); > >> >> - return __os; > >> >> + return __detail::__chrono_write<32>(__os, __y); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits, > >> >> @@ -3721,18 +3718,7 @@ namespace __detail > >> >> inline basic_ostream<_CharT, _Traits>& > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday& > __wd) > >> >> { > >> >> - using _Ctx = __format::__format_context<_CharT>; > >> >> - using _Str = basic_string_view<_CharT>; > >> >> - _Str __s = _GLIBCXX_WIDEN("{:L%a}{} is not a valid weekday"); > >> >> - if (__wd.ok()) > >> >> - __os << std::vformat(__os.getloc(), __s.substr(0, 6), > >> >> - make_format_args<_Ctx>(__wd)); > >> >> - else > >> >> - { > >> >> - auto __c = __wd.c_encoding(); > >> >> - __os << std::vformat(__s.substr(6), > make_format_args<_Ctx>(__c)); > >> >> - } > >> >> - return __os; > >> >> + return __detail::__chrono_write(__os, __wd, __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits, > >> >> @@ -3754,23 +3740,7 @@ namespace __detail > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, > >> >> const weekday_indexed& __wdi) > >> >> { > >> >> - // The standard says to format wdi.weekday() and wdi.index() > using > >> >> - // either "{:L}[{}]" or "{:L}[{} is not a valid index]". The > {:L} > >> >> spec > >> >> - // means to format the weekday using ostringstream, so just > do that. > >> >> - basic_stringstream<_CharT> __os2; > >> >> - __os2.imbue(__os.getloc()); > >> >> - __os2 << __wdi.weekday(); > >> >> - const auto __i = __wdi.index(); > >> >> - basic_string_view<_CharT> __s > >> >> - = _GLIBCXX_WIDEN("[ is not a valid index]"); > >> >> - __os2 << __s[0]; > >> >> - __os2 << std::format(_GLIBCXX_WIDEN("{}"), __i); > >> >> - if (__i >= 1 && __i <= 5) > >> >> - __os2 << __s.back(); > >> >> - else > >> >> - __os2 << __s.substr(1); > >> >> - __os << __os2.view(); > >> >> - return __os; > >> >> + return __detail::__chrono_write(__os, __wdi, __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits> > >> >> @@ -3778,29 +3748,14 @@ namespace __detail > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, > >> >> const weekday_last& __wdl) > >> >> { > >> >> - // As above, just write straight to a stringstream, as if by > >> >> "{:L}[last]" > >> >> - basic_stringstream<_CharT> __os2; > >> >> - __os2.imbue(__os.getloc()); > >> >> - __os2 << __wdl.weekday() << _GLIBCXX_WIDEN("[last]"); > >> >> - __os << __os2.view(); > >> >> - return __os; > >> >> + return __detail::__chrono_write(__os, __wdl, __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits> > >> >> inline basic_ostream<_CharT, _Traits>& > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, const > month_day& > >> >> __md) > >> >> { > >> >> - // As above, just write straight to a stringstream, as if by > >> >> "{:L}/{}" > >> >> - basic_stringstream<_CharT> __os2; > >> >> - __os2.imbue(__os.getloc()); > >> >> - __os2 << __md.month(); > >> >> - if constexpr (is_same_v<_CharT, char>) > >> >> - __os2 << '/'; > >> >> - else > >> >> - __os2 << L'/'; > >> >> - __os2 << __md.day(); > >> >> - __os << __os2.view(); > >> >> - return __os; > >> >> + return __detail::__chrono_write(__os, __md, __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits, > >> >> @@ -3824,12 +3779,7 @@ namespace __detail > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, > >> >> const month_day_last& __mdl) > >> >> { > >> >> - // As above, just write straight to a stringstream, as if by > >> >> "{:L}/last" > >> >> - basic_stringstream<_CharT> __os2; > >> >> - __os2.imbue(__os.getloc()); > >> >> - __os2 << __mdl.month() << _GLIBCXX_WIDEN("/last"); > >> >> - __os << __os2.view(); > >> >> - return __os; > >> >> + return __detail::__chrono_write(__os, __mdl, __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits> > >> >> @@ -3837,17 +3787,7 @@ namespace __detail > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, > >> >> const month_weekday& __mwd) > >> >> { > >> >> - // As above, just write straight to a stringstream, as if by > >> >> "{:L}/{:L}" > >> >> - basic_stringstream<_CharT> __os2; > >> >> - __os2.imbue(__os.getloc()); > >> >> - __os2 << __mwd.month(); > >> >> - if constexpr (is_same_v<_CharT, char>) > >> >> - __os2 << '/'; > >> >> - else > >> >> - __os2 << L'/'; > >> >> - __os2 << __mwd.weekday_indexed(); > >> >> - __os << __os2.view(); > >> >> - return __os; > >> >> + return __detail::__chrono_write(__os, __mwd, __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits> > >> >> @@ -3855,34 +3795,14 @@ namespace __detail > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, > >> >> const month_weekday_last& __mwdl) > >> >> { > >> >> - // As above, just write straight to a stringstream, as if by > >> >> "{:L}/{:L}" > >> >> - basic_stringstream<_CharT> __os2; > >> >> - __os2.imbue(__os.getloc()); > >> >> - __os2 << __mwdl.month(); > >> >> - if constexpr (is_same_v<_CharT, char>) > >> >> - __os2 << '/'; > >> >> - else > >> >> - __os2 << L'/'; > >> >> - __os2 << __mwdl.weekday_last(); > >> >> - __os << __os2.view(); > >> >> - return __os; > >> >> + return __detail::__chrono_write(__os, __mwdl, __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits> > >> >> inline basic_ostream<_CharT, _Traits>& > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, const > year_month& > >> >> __ym) > >> >> { > >> >> - // As above, just write straight to a stringstream, as if by > >> >> "{}/{:L}" > >> >> - basic_stringstream<_CharT> __os2; > >> >> - __os2.imbue(__os.getloc()); > >> >> - __os2 << __ym.year(); > >> >> - if constexpr (is_same_v<_CharT, char>) > >> >> - __os2 << '/'; > >> >> - else > >> >> - __os2 << L'/'; > >> >> - __os2 << __ym.month(); > >> >> - __os << __os2.view(); > >> >> - return __os; > >> >> + return __detail::__chrono_write(__os, __ym, __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits, > >> >> @@ -3906,12 +3826,7 @@ namespace __detail > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, > >> >> const year_month_day& __ymd) > >> >> { > >> >> - using _Ctx = __format::__format_context<_CharT>; > >> >> - using _Str = basic_string_view<_CharT>; > >> >> - _Str __s = _GLIBCXX_WIDEN("{:%F} is not a valid date"); > >> >> - __os << std::vformat(__ymd.ok() ? __s.substr(0, 5) : __s, > >> >> - make_format_args<_Ctx>(__ymd)); > >> >> - return __os; > >> >> + return __detail::__chrono_write<64>(__os, __ymd); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits, > >> >> @@ -3936,17 +3851,7 @@ namespace __detail > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, > >> >> const year_month_day_last& __ymdl) > >> >> { > >> >> - // As above, just write straight to a stringstream, as if by > >> >> "{}/{:L}" > >> >> - basic_stringstream<_CharT> __os2; > >> >> - __os2.imbue(__os.getloc()); > >> >> - __os2 << __ymdl.year(); > >> >> - if constexpr (is_same_v<_CharT, char>) > >> >> - __os2 << '/'; > >> >> - else > >> >> - __os2 << L'/'; > >> >> - __os2 << __ymdl.month_day_last(); > >> >> - __os << __os2.view(); > >> >> - return __os; > >> >> + return __detail::__chrono_write(__os, __ymdl, __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits> > >> >> @@ -3954,19 +3859,7 @@ namespace __detail > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, > >> >> const year_month_weekday& __ymwd) > >> >> { > >> >> - // As above, just write straight to a stringstream, as if by > >> >> - // "{}/{:L}/{:L}" > >> >> - basic_stringstream<_CharT> __os2; > >> >> - __os2.imbue(__os.getloc()); > >> >> - _CharT __slash; > >> >> - if constexpr (is_same_v<_CharT, char>) > >> >> - __slash = '/'; > >> >> - else > >> >> - __slash = L'/'; > >> >> - __os2 << __ymwd.year() << __slash << __ymwd.month() << __slash > >> >> - << __ymwd.weekday_indexed(); > >> >> - __os << __os2.view(); > >> >> - return __os; > >> >> + return __detail::__chrono_write(__os, __ymwd, __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits> > >> >> @@ -3974,19 +3867,7 @@ namespace __detail > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, > >> >> const year_month_weekday_last& __ymwdl) > >> >> { > >> >> - // As above, just write straight to a stringstream, as if by > >> >> - // "{}/{:L}/{:L}" > >> >> - basic_stringstream<_CharT> __os2; > >> >> - __os2.imbue(__os.getloc()); > >> >> - _CharT __slash; > >> >> - if constexpr (is_same_v<_CharT, char>) > >> >> - __slash = '/'; > >> >> - else > >> >> - __slash = L'/'; > >> >> - __os2 << __ymwdl.year() << __slash << __ymwdl.month() << > __slash > >> >> - << __ymwdl.weekday_last(); > >> >> - __os << __os2.view(); > >> >> - return __os; > >> >> + return __detail::__chrono_write(__os, __ymwdl, __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits, typename _Duration> > >> >> @@ -3994,7 +3875,7 @@ namespace __detail > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, > >> >> const hh_mm_ss<_Duration>& __hms) > >> >> { > >> >> - return __os << format(__os.getloc(), _GLIBCXX_WIDEN("{:L%T}"), > >> >> __hms); > >> >> + return __detail::__chrono_write<64>(__os, __hms, > __os.getloc()); > >> >> } > >> >> > >> >> #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI > >> >> @@ -4003,7 +3884,7 @@ namespace __detail > >> >> basic_ostream<_CharT, _Traits>& > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, const > sys_info& __i) > >> >> { > >> >> - return __os << std::format(__os.getloc(), > _GLIBCXX_WIDEN("{}"), > >> >> __i); > >> >> + return __detail::__chrono_write(__os, __i, __os.getloc()); > >> >> } > >> >> > >> >> /// Writes a local_info object to an ostream in an unspecified > format. > >> >> @@ -4011,20 +3892,7 @@ namespace __detail > >> >> basic_ostream<_CharT, _Traits>& > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, const > local_info& > >> >> __li) > >> >> { > >> >> - __os << __format::_Separators<_CharT>::_S_squares()[0]; > >> >> - if (__li.result == local_info::unique) > >> >> - __os << __li.first; > >> >> - else > >> >> - { > >> >> - if (__li.result == local_info::nonexistent) > >> >> - __os << _GLIBCXX_WIDEN("nonexistent"); > >> >> - else > >> >> - __os << _GLIBCXX_WIDEN("ambiguous"); > >> >> - __os << _GLIBCXX_WIDEN(" local time between ") << > __li.first; > >> >> - __os << _GLIBCXX_WIDEN(" and ") << __li.second; > >> >> - } > >> >> - __os << __format::_Separators<_CharT>::_S_squares()[1]; > >> >> - return __os; > >> >> + return __detail::__chrono_write<256>(__os, __li); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits, typename _Duration, > >> >> @@ -4033,8 +3901,7 @@ namespace __detail > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, > >> >> const zoned_time<_Duration, _TimeZonePtr>& __t) > >> >> { > >> >> - __os << format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T %Z}"), > __t); > >> >> - return __os; > >> >> + return __detail::__chrono_write(__os, __t, __os.getloc()); > >> >> } > >> >> #endif > >> >> > >> >> @@ -4045,16 +3912,14 @@ namespace __detail > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, > >> >> const sys_time<_Duration>& __tp) > >> >> { > >> >> - __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F > %T}"), > >> >> __tp); > >> >> - return __os; > >> >> + return __detail::__chrono_write<64>(__os, __tp, > __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits> > >> >> inline basic_ostream<_CharT, _Traits>& > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, const > sys_days& __dp) > >> >> { > >> >> - __os << year_month_day{__dp}; > >> >> - return __os; > >> >> + return __detail::__chrono_write<32>(__os, __dp); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits, typename _Duration, > >> >> @@ -4090,8 +3955,7 @@ namespace __detail > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, > >> >> const utc_time<_Duration>& __t) > >> >> { > >> >> - __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F > %T}"), > >> >> __t); > >> >> - return __os; > >> >> + return __detail::__chrono_write<64>(__os, __t, __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits, typename _Duration, > >> >> @@ -4125,8 +3989,7 @@ namespace __detail > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, > >> >> const tai_time<_Duration>& __t) > >> >> { > >> >> - __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F > %T}"), > >> >> __t); > >> >> - return __os; > >> >> + return __detail::__chrono_write<64>(__os, __t, __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits, typename _Duration, > >> >> @@ -4164,8 +4027,7 @@ namespace __detail > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, > >> >> const gps_time<_Duration>& __t) > >> >> { > >> >> - __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F > %T}"), > >> >> __t); > >> >> - return __os; > >> >> + return __detail::__chrono_write<64>(__os, __t, __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits, typename _Duration, > >> >> @@ -4202,8 +4064,7 @@ namespace __detail > >> >> operator<<(basic_ostream<_CharT, _Traits>& __os, > >> >> const file_time<_Duration>& __t) > >> >> { > >> >> - __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F > %T}"), > >> >> __t); > >> >> - return __os; > >> >> + return __detail::__chrono_write<64>(__os, __t, __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits, typename _Duration, > >> >> @@ -4228,8 +4089,7 @@ namespace __detail > >> >> // 4257. Stream insertion for chrono::local_time should be > constrained > >> >> requires requires(const sys_time<_Duration>& __st) { __os << > __st; } > >> >> { > >> >> - __os << sys_time<_Duration>{__lt.time_since_epoch()}; > >> >> - return __os; > >> >> + return __detail::__chrono_write<64>(__os, __lt, > __os.getloc()); > >> >> } > >> >> > >> >> template<typename _CharT, typename _Traits, typename _Duration, > >> >> -- > >> >> 2.34.1 > >> >> > >> >> > >> > >
