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

Reply via email to