On Fri, Jun 6, 2025 at 1:02 PM Tomasz Kamiński <tkami...@redhat.com> wrote:

> This patch change implementation of the formatters for the calendar types,
> so they no longer delegate to operator<< for ostream in case of empty
> chrono-spec.
> Instead of that, we define the behavior of the in terms of format
> specifiers,
> that format specifiers are supplied by each formatter as argument to
> _M_parse
> Similary is formatter constructor it's __formatter_chrono from revalant
> default
> spec, so we preserve functionality of calling format on default cosntructed
> formatters.
>
> Expressing  the existing functionality of the operaetor ostream, requires
> providing two additional features:
>  * printing "is not a valid sth" for !ok objects,
>  * printing a weekday index in the month.
>
> The formatter functionality is enabled by setting spec _M_debug
> (corresponding
> to '?') that is currently unused. This is currently supported only for
> subset of format specifiers used by the ostream operators. In future, we
> could
> make this user configurable (by adding '?' after 'L') and cover all flags.
>
> For the handling of the weekday index (for weekday_indexed, month_weekday,
> year_month_weekday), we need to introduce an new format specifier. To not
> conflict with future extension we use '%\0' (embedded null) as this
> character
> cannot be placed in valid format spec.
>
> Finally, the format strings for calendar types subsets each other, e.g.
> year_month_weekday_last ("%Y/%b/%a[last])" contains month_weekday_last,
> weekday_last, weekday, e.t.c.. We introduce a _ChronoFormats class that
> provide
> consteval accessors to format specs, internally sharing they
> representations.
>
> libstdc++-v3/ChangeLog:
>
>         * include/bits/chrono_io.h (__format::_ChronoFormats): Define.
>         (__formatter_chrono::__formatter_chrono())
>         (__formatter_chrono::__formatter_chrono(_ChronoSpec<_CharT>)):
> Define.
>         (__formatter_chrono::_M_parse): Add parameter with default spec,
>         namd merge it with new values. Handle '%\0' as weekday index
>         specifier.
>         (__formatter_chrono::_M_a_A, __formatter_chrono::_M_b_B)
>         (__formatter_chrono::_M_C_y_Y, __formatter_chrono::_M_d_e)
>         (__formatter_chrono::_M_F): Support _M_debug flag.
>         (__formatter_chrono::_M_wi, __formatter_chrono::_S_weekday_index):
>         Define.
>         (std::formatter<chrono::day, _CharT>)
>         (std::formatter<chrono::month, _CharT>)
>         (std::formatter<chrono::year, _CharT>)
>         (std::formatter<chrono::weekday, _CharT>)
>         (std::formatter<chrono::weekday_indexed, _CharT>)
>         (std::formatter<chrono::weekday_last, _CharT>)
>         (std::formatter<chrono::month_day, _CharT>)
>         (std::formatter<chrono::month_day_last, _CharT>)
>         (std::formatter<chrono::month_weekday, _CharT>)
>         (std::formatter<chrono::month_weekday_last, _CharT>)
>         (std::formatter<chrono::year_month, _CharT>)
>         (std::formatter<chrono::year_month_day, _CharT>)
>         (std::formatter<chrono::year_month_day_last, _CharT>)
>         (std::formatter<chrono::year_month_weekday, _CharT>)
>         (std::formatter<chrono::year_month_weekday_last, _CharT>):
>         Define __defSpec, and pass it as argument to _M_prase and
>         constructor of __formatter_chrono.
> ---
>  libstdc++-v3/include/bits/chrono_io.h | 430 +++++++++++++++++++++++---
>  1 file changed, 381 insertions(+), 49 deletions(-)
>
> diff --git a/libstdc++-v3/include/bits/chrono_io.h
> b/libstdc++-v3/include/bits/chrono_io.h
> index c5c5e4bae53..e36cf1ffd31 100644
> --- a/libstdc++-v3/include/bits/chrono_io.h
> +++ b/libstdc++-v3/include/bits/chrono_io.h
> @@ -238,6 +238,93 @@ namespace __format
>    operator|=(_ChronoParts& __x, _ChronoParts __y) noexcept
>    { return __x = __x | __y; }
>
> +  template<typename _CharT>
> +  struct _ChronoFormats
> +  {
> +    using _String_view = basic_string_view<_CharT>;
> +
> +    static consteval
> +    _String_view
> +    _S_f() noexcept
> +    { return _GLIBCXX_WIDEN("%F"); }
> +
> +    static consteval
> +    _String_view
> +    _S_ymd() noexcept
> +    { return _GLIBCXX_WIDEN("%Y/%b/%d"); }
> +
> +    static consteval
> +    _String_view
> +    _S_ym() noexcept
> +    { return _S_ymd().substr(0, 5); }
> +
> +    static consteval
> +    _String_view
> +    _S_md() noexcept
> +    { return _S_ymd().substr(3); }
> +
> +    static consteval
> +    _String_view
> +    _S_y() noexcept
> +    { return _S_ymd().substr(0, 2); }
> +
> +    static consteval
> +    _String_view
> +    _S_m() noexcept
> +    { return _S_ymd().substr(3, 2); }
> +
> +    static consteval
> +    _String_view
> +    _S_d() noexcept
> +    { return _S_ymd().substr(6, 2); }
> +
> +    static consteval
> +    _String_view
> +    _S_ymwi() noexcept
> +    // %\0 is extension for handling weekday index
> +    { return _String_view(_GLIBCXX_WIDEN("%Y/%b/%a[%\0]"), 12); }
> +
> +    static consteval
> +    _String_view
> +    _S_mwi() noexcept
> +    { return _S_ymwi().substr(3); }
> +
> +    static consteval
> +    _String_view
> +    _S_wi() noexcept
> +    { return _S_ymwi().substr(6); }
> +
> +    static consteval
> +    _String_view
> +    _S_w() noexcept
> +    { return _S_ymwi().substr(6, 2); }
> +
> +    static consteval
> +    _String_view
> +    _S_ymwl() noexcept
> +    { return _GLIBCXX_WIDEN("%Y/%b/%a[last]"); }
> +
> +    static consteval
> +    _String_view
> +    _S_mwl() noexcept
> +    { return _S_ymwl().substr(3); }
> +
> +    static consteval
> +    _String_view
> +    _S_wl() noexcept
> +    { return _S_ymwl().substr(6); }
> +
> +    static consteval
> +    _String_view
> +    _S_yml() noexcept
> +    { return _GLIBCXX_WIDEN("%Y/%b/last"); }
> +
> +    static consteval
> +    _String_view
> +    _S_ml() noexcept
> +    { return _S_yml().substr(3); }
> +  };
> +
>    // TODO rename this to chrono::__formatter? or
> chrono::__detail::__formatter?
>    template<typename _CharT>
>      struct __formatter_chrono
> @@ -245,49 +332,69 @@ namespace __format
>        using __string_view = basic_string_view<_CharT>;
>        using __string = basic_string<_CharT>;
>
> +      __formatter_chrono() = default;
> +
> +      constexpr explicit
> +      __formatter_chrono(_ChronoSpec<_CharT> __spec) noexcept
> +      : _M_spec(__spec)
> +      { }
> +
>        template<typename _ParseContext>
>         constexpr typename _ParseContext::iterator
> -       _M_parse(_ParseContext& __pc, _ChronoParts __parts)
> +       _M_parse(_ParseContext& __pc, _ChronoParts __parts,
> +                const _ChronoSpec<_CharT>& __def = {})
>         {
>           auto __first = __pc.begin();
>           auto __last = __pc.end();
>
>           _ChronoSpec<_CharT> __spec{};
>
This part could also be implemented as, let me know which version do you
prefer:
      using __string_view = basic_string_view<_CharT>;
       using __string = basic_string<_CharT>;

+      __formatter_chrono() = default;
+
+      constexpr explicit
+      __formatter_chrono(_ChronoSpec<_CharT> __spec) noexcept
+      : _M_spec(__spec)
+      { }
+
       template<typename _ParseContext>
        constexpr typename _ParseContext::iterator
-       _M_parse(_ParseContext& __pc, _ChronoParts __parts)
+       _M_parse(_ParseContext& __pc, _ChronoParts __parts,
+                const _ChronoSpec<_CharT>& __def = {})
        {
          auto __first = __pc.begin();
          auto __last = __pc.end();

-         _ChronoSpec<_CharT> __spec{};
+         _ChronoSpec<_CharT> __spec = __def;

          auto __finalize = [this, &__spec] {
            _M_spec = __spec;
@@ -285,6 +380,7 @@ namespace __format
                return __first;
            }

+         __spec._M_localized = false;
          __first = __spec._M_parse_locale(__first, __last);
          if (__finished())
            return __first;
@@ -307,6 +403,7 @@ namespace __format
          // against __parts (so fail for %Y if no year in parts).
          // Save range in __spec._M_chrono_specs.

+         __spec._M_debug = false;
          const auto __chrono_specs = __first++; // Skip leading '%'
          if (*__chrono_specs != '%')
            __throw_format_error("chrono format error: no '%' at

>
> -         auto __finalize = [this, &__spec] {
> -           _M_spec = __spec;
> +         auto __apply_default = [&] {
> +           _M_spec = __def;
> +           if (__spec._M_align != _Align_default)
> +             {
> +               _M_spec._M_align = __spec._M_align;
> +               _M_spec._M_fill = __spec._M_fill;
> +             }
> +           if (__spec._M_width_kind != _WP_none)
> +             {
> +               _M_spec._M_width_kind = __spec._M_width_kind;
> +               _M_spec._M_width = __spec._M_width;
> +             }
> +           if (__spec._M_prec_kind != _WP_none)
> +             {
> +               _M_spec._M_prec_kind = __spec._M_prec_kind;
> +               _M_spec._M_prec = __spec._M_prec;
> +             }
> +           _M_spec._M_localized |= __spec._M_localized;
> +           return __first;
>           };
>
>           auto __finished = [&] {
> -           if (__first == __last || *__first == '}')
> -             {
> -               __finalize();
> -               return true;
> -             }
> -           return false;
> +           return __first == __last || *__first == '}';
>           };
>
>           if (__finished())
> -           return __first;
> +           return __apply_default();
>
>           __first = __spec._M_parse_fill_and_align(__first, __last);
>           if (__finished())
> -           return __first;
> +           return __apply_default();
>
>           __first = __spec._M_parse_width(__first, __last, __pc);
>           if (__finished())
> -           return __first;
> +           return __apply_default();
>
>           if (__parts & _ChronoParts::_Duration)
>             {
>               __first = __spec._M_parse_precision(__first, __last, __pc);
>               if (__finished())
> -               return __first;
> +               return __apply_default();
>             }
>
>           __first = __spec._M_parse_locale(__first, __last);
>           if (__finished())
> -           return __first;
> +           return __apply_default();
>
>           // Everything up to the end of the string or the first '}' is a
>           // chrono-specs string. Check it is valid.
> @@ -562,6 +669,10 @@ namespace __format
>               _CharT __c = *__first++;
>               switch (__c)
>                 {
> +               // %\0 is extension for handling weekday index
> +               case '\0':
> +                 __out = _M_wi(__t, std::move(__out), __fc);
> +                 break;
>                 case 'a':
>                 case 'A':
>                   __out = _M_a_A(__t, std::move(__out), __fc, __c == 'A');
> @@ -816,6 +927,22 @@ namespace __format
>           return __format::__write(std::move(__out), __s);
>         }
>
> +      template<typename _Tp, typename _FormatContext>
> +       typename _FormatContext::iterator
> +       _M_wi(const _Tp& __t, typename _FormatContext::iterator __out,
> +              _FormatContext& __ctx) const
> +       {
> +         // %\0 Extension to format weekday index, used only by empty
> format spec
> +         unsigned __wi = _S_weekday_index(__t);
> +
> +         _CharT __buf[3];
> +         __out = __format::__write(std::move(__out), _S_str_d1(__buf,
> __wi));
> +         if (_M_spec._M_debug && (__wi < 1 || __wi > 5))
> +           __out = __format::__write(std::move(__out),
> +                     __string_view(_GLIBCXX_WIDEN(" is not a valid
> index")));
> +         return std::move(__out);
> +       }
> +
>        template<typename _Tp, typename _FormatContext>
>         typename _FormatContext::iterator
>         _M_a_A(const _Tp& __t, typename _FormatContext::iterator __out,
> @@ -825,7 +952,16 @@ namespace __format
>           // %A Locale's full weekday name.
>           chrono::weekday __wd = _S_weekday(__t);
>           if (!__wd.ok())
> -           __throw_format_error("format error: invalid weekday");
> +           {
> +             if (!_M_spec._M_debug)
> +               __throw_format_error("format error: invalid weekday");
> +
> +             _CharT __buf[3];
> +             __out = __format::__write(std::move(__out),
> +                                       _S_str_d1(__buf,
> __wd.c_encoding()));
> +             return __format::__write(std::move(__out),
> +                       __string_view(_GLIBCXX_WIDEN(" is not a valid
> weekday")));
> +           }
>
>           locale __loc = _M_locale(__ctx);
>           const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
> @@ -847,7 +983,17 @@ namespace __format
>           // %B Locale's full month name.
>           chrono::month __m = _S_month(__t);
>           if (!__m.ok())
> -           __throw_format_error("format error: invalid month");
> +           {
> +             if (!_M_spec._M_debug)
> +               __throw_format_error("format error: invalid month");
> +
> +             _CharT __buf[3];
> +             __out = __format::__write(std::move(__out),
> +                                       _S_str_d1(__buf, (unsigned)__m));
> +             return __format::__write(std::move(__out),
> +                       __string_view(_GLIBCXX_WIDEN(" is not a valid
> month")));
> +           }
> +
>           locale __loc = _M_locale(__ctx);
>           const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
>           const _CharT* __months[12];
> @@ -974,7 +1120,11 @@ namespace __format
>                 }
>               __out = __format::__write(std::move(__out), __sv);
>             }
> -        return std::move(__out);
> +
> +         if (_M_spec._M_debug && __conv == 'Y' && !__y.ok()) [[unlikely]]
> +           __out = __format::__write(std::move(__out),
> +                     __string_view(_GLIBCXX_WIDEN(" is not a valid
> year")));
> +         return __out;
>         }
>
>        template<typename _Tp, typename _FormatContext>
> @@ -1039,7 +1189,12 @@ namespace __format
>               __buf[0] = _S_space;
>               __sv = {__buf, 2};
>             }
> -         return __format::__write(std::move(__out), __sv);
> +
> +         __out = __format::__write(std::move(__out), __sv);
> +         if (_M_spec._M_debug && !__d.ok()) [[unlikely]]
> +           __out = __format::__write(std::move(__out),
> +                     __string_view(_GLIBCXX_WIDEN(" is not a valid
> day")));
> +         return std::move(__out);
>         }
>
>        template<typename _Tp, typename _FormatContext>
> @@ -1076,6 +1231,10 @@ namespace __format
>               _S_fill_two_digits(__buf + 9, __di);
>               __out = __format::__write(std::move(__out), __sv);
>             }
> +
> +         if (_M_spec._M_debug && !__ymd.ok())
> +           __out = __format::__write(std::move(__out),
> +                     __string_view(_GLIBCXX_WIDEN(" is not a valid
> date")));
>           return std::move(__out);
>         }
>
> @@ -1757,6 +1916,20 @@ namespace __format
>             return weekday(_S_days(__t));
>         }
>
> +      template<typename _Tp>
> +       static unsigned
> +       _S_weekday_index(const _Tp& __t)
> +       {
> +         using namespace ::std::chrono;
> +
> +         if constexpr (is_same_v<_Tp, weekday_indexed>)
> +           return __t.index();
> +         else if constexpr (requires { __t.weekday_indexed(); })
> +           return __t.weekday_indexed().index();
> +         else
> +           return ((unsigned)_S_day(__t) + 6) / 7;
> +       }
> +
>        // Remove subsecond precision from a time_point.
>        template<typename _Tp>
>         static auto
> @@ -1851,7 +2024,7 @@ namespace __format
>      {
>        constexpr typename basic_format_parse_context<_CharT>::iterator
>        parse(basic_format_parse_context<_CharT>& __pc)
> -      { return _M_f._M_parse(__pc, __format::_Day); }
> +      { return _M_f._M_parse(__pc, __format::_Day, __defSpec); }
>
>        template<typename _Out>
>         typename basic_format_context<_Out, _CharT>::iterator
> @@ -1860,7 +2033,15 @@ namespace __format
>         { return _M_f._M_format(__t, __fc); }
>
>      private:
> -      __format::__formatter_chrono<_CharT> _M_f;
> +      static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
> +       {
> +         __format::_ChronoSpec<_CharT> __res{};
> +         __res._M_debug = true;
> +         __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_d();
> +         return __res;
> +       }();
> +
> +      __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>      };
>
>    template<__format::__char _CharT>
> @@ -1868,7 +2049,7 @@ namespace __format
>      {
>        constexpr typename basic_format_parse_context<_CharT>::iterator
>        parse(basic_format_parse_context<_CharT>& __pc)
> -      { return _M_f._M_parse(__pc, __format::_Month); }
> +      { return _M_f._M_parse(__pc, __format::_Month, __defSpec); }
>
>        template<typename _Out>
>         typename basic_format_context<_Out, _CharT>::iterator
> @@ -1877,7 +2058,17 @@ namespace __format
>         { return _M_f._M_format(__t, __fc); }
>
>      private:
> -      __format::__formatter_chrono<_CharT> _M_f;
> +      static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
> +       {
> +         __format::_ChronoSpec<_CharT> __res{};
> +         __res._M_debug = true;
> +         __res._M_localized = true;
> +         __res._M_locale_specific = true;
> +         __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_m();
> +         return __res;
> +       }();
> +
> +      __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>      };
>
>    template<__format::__char _CharT>
> @@ -1885,7 +2076,7 @@ namespace __format
>      {
>        constexpr typename basic_format_parse_context<_CharT>::iterator
>        parse(basic_format_parse_context<_CharT>& __pc)
> -      { return _M_f._M_parse(__pc, __format::_Year); }
> +      { return _M_f._M_parse(__pc, __format::_Year, __defSpec); }
>
>        template<typename _Out>
>         typename basic_format_context<_Out, _CharT>::iterator
> @@ -1894,7 +2085,15 @@ namespace __format
>         { return _M_f._M_format(__t, __fc); }
>
>      private:
> -      __format::__formatter_chrono<_CharT> _M_f;
> +      static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
> +       {
> +         __format::_ChronoSpec<_CharT> __res{};
> +         __res._M_debug = true;
> +         __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_y();
> +         return __res;
> +       }();
> +
> +      __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>      };
>
>    template<__format::__char _CharT>
> @@ -1902,7 +2101,7 @@ namespace __format
>      {
>        constexpr typename basic_format_parse_context<_CharT>::iterator
>        parse(basic_format_parse_context<_CharT>& __pc)
> -      { return _M_f._M_parse(__pc, __format::_Weekday); }
> +      { return _M_f._M_parse(__pc, __format::_Weekday, __defSpec); }
>
>        template<typename _Out>
>         typename basic_format_context<_Out, _CharT>::iterator
> @@ -1911,7 +2110,17 @@ namespace __format
>         { return _M_f._M_format(__t, __fc); }
>
>      private:
> -      __format::__formatter_chrono<_CharT> _M_f;
> +      static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
> +       {
> +         __format::_ChronoSpec<_CharT> __res{};
> +         __res._M_debug = true;
> +         __res._M_localized = true;
> +         __res._M_locale_specific = true;
> +         __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_w();
> +         return __res;
> +       }();
> +
> +      __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>      };
>
>    template<__format::__char _CharT>
> @@ -1919,7 +2128,7 @@ namespace __format
>      {
>        constexpr typename basic_format_parse_context<_CharT>::iterator
>        parse(basic_format_parse_context<_CharT>& __pc)
> -      { return _M_f._M_parse(__pc, __format::_Weekday); }
> +      { return _M_f._M_parse(__pc, __format::_Weekday, __defSpec); }
>
>        template<typename _Out>
>         typename basic_format_context<_Out, _CharT>::iterator
> @@ -1928,7 +2137,17 @@ namespace __format
>         { return _M_f._M_format(__t, __fc); }
>
>      private:
> -      __format::__formatter_chrono<_CharT> _M_f;
> +      static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
> +       {
> +         __format::_ChronoSpec<_CharT> __res{};
> +         __res._M_debug = true;
> +         __res._M_localized = true;
> +         __res._M_locale_specific = true;
> +         __res._M_chrono_specs =
> __format::_ChronoFormats<_CharT>::_S_wi();
> +         return __res;
> +       }();
> +
> +      __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>      };
>
>    template<__format::__char _CharT>
> @@ -1936,7 +2155,7 @@ namespace __format
>      {
>        constexpr typename basic_format_parse_context<_CharT>::iterator
>        parse(basic_format_parse_context<_CharT>& __pc)
> -      { return _M_f._M_parse(__pc, __format::_Weekday); }
> +      { return _M_f._M_parse(__pc, __format::_Weekday, __defSpec); }
>
>        template<typename _Out>
>         typename basic_format_context<_Out, _CharT>::iterator
> @@ -1945,7 +2164,17 @@ namespace __format
>         { return _M_f._M_format(__t, __fc); }
>
>      private:
> -      __format::__formatter_chrono<_CharT> _M_f;
> +      static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
> +       {
> +         __format::_ChronoSpec<_CharT> __res{};
> +         __res._M_debug = true;
> +         __res._M_localized = true;
> +         __res._M_locale_specific = true;
> +         __res._M_chrono_specs =
> __format::_ChronoFormats<_CharT>::_S_wl();
> +         return __res;
> +       }();
> +
> +      __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>      };
>
>    template<__format::__char _CharT>
> @@ -1953,7 +2182,10 @@ namespace __format
>      {
>        constexpr typename basic_format_parse_context<_CharT>::iterator
>        parse(basic_format_parse_context<_CharT>& __pc)
> -      { return _M_f._M_parse(__pc, __format::_Month|__format::_Day); }
> +      {
> +       return _M_f._M_parse(__pc, __format::_Month|__format::_Day,
> +                            __defSpec);
> +      }
>
>        template<typename _Out>
>         typename basic_format_context<_Out, _CharT>::iterator
> @@ -1962,7 +2194,17 @@ namespace __format
>         { return _M_f._M_format(__t, __fc); }
>
>      private:
> -      __format::__formatter_chrono<_CharT> _M_f;
> +      static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
> +       {
> +         __format::_ChronoSpec<_CharT> __res{};
> +         __res._M_debug = true;
> +         __res._M_localized = true;
> +         __res._M_locale_specific = true;
> +         __res._M_chrono_specs =
> __format::_ChronoFormats<_CharT>::_S_md();
> +         return __res;
> +       }();
> +
> +      __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>      };
>
>    template<__format::__char _CharT>
> @@ -1970,7 +2212,10 @@ namespace __format
>      {
>        constexpr typename basic_format_parse_context<_CharT>::iterator
>        parse(basic_format_parse_context<_CharT>& __pc)
> -      { return _M_f._M_parse(__pc, __format::_Month|__format::_Day); }
> +      {
> +       return _M_f._M_parse(__pc, __format::_Month|__format::_Day,
> +                            __defSpec);
> +      }
>
>        template<typename _Out>
>         typename basic_format_context<_Out, _CharT>::iterator
> @@ -1979,7 +2224,17 @@ namespace __format
>         { return _M_f._M_format(__t, __fc); }
>
>      private:
> -      __format::__formatter_chrono<_CharT> _M_f;
> +       static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
> +       {
> +         __format::_ChronoSpec<_CharT> __res{};
> +         __res._M_debug = true;
> +         __res._M_localized = true;
> +         __res._M_locale_specific = true;
> +         __res._M_chrono_specs =
> __format::_ChronoFormats<_CharT>::_S_ml();
> +         return __res;
> +       }();
> +
> +      __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>      };
>
>    template<__format::__char _CharT>
> @@ -1987,7 +2242,10 @@ namespace __format
>      {
>        constexpr typename basic_format_parse_context<_CharT>::iterator
>        parse(basic_format_parse_context<_CharT>& __pc)
> -      { return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday); }
> +      {
> +       return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday,
> +                            __defSpec);
> +      }
>
>        template<typename _Out>
>         typename basic_format_context<_Out, _CharT>::iterator
> @@ -1996,7 +2254,17 @@ namespace __format
>         { return _M_f._M_format(__t, __fc); }
>
>      private:
> -      __format::__formatter_chrono<_CharT> _M_f;
> +      static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
> +       {
> +         __format::_ChronoSpec<_CharT> __res{};
> +         __res._M_debug = true;
> +         __res._M_localized = true;
> +         __res._M_locale_specific = true;
> +         __res._M_chrono_specs =
> __format::_ChronoFormats<_CharT>::_S_mwi();
> +         return __res;
> +       }();
> +
> +      __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>      };
>
>    template<__format::__char _CharT>
> @@ -2004,7 +2272,10 @@ namespace __format
>      {
>        constexpr typename basic_format_parse_context<_CharT>::iterator
>        parse(basic_format_parse_context<_CharT>& __pc)
> -      { return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday); }
> +      {
> +       return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday,
> +                            __defSpec);
> +      }
>
>        template<typename _Out>
>         typename basic_format_context<_Out, _CharT>::iterator
> @@ -2013,7 +2284,17 @@ namespace __format
>         { return _M_f._M_format(__t, __fc); }
>
>      private:
> -      __format::__formatter_chrono<_CharT> _M_f;
> +       static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
> +       {
> +         __format::_ChronoSpec<_CharT> __res{};
> +         __res._M_debug = true;
> +         __res._M_localized = true;
> +         __res._M_locale_specific = true;
> +         __res._M_chrono_specs =
> __format::_ChronoFormats<_CharT>::_S_mwl();
> +         return __res;
> +       }();
> +
> +      __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>      };
>
>    template<__format::__char _CharT>
> @@ -2021,7 +2302,10 @@ namespace __format
>      {
>        constexpr typename basic_format_parse_context<_CharT>::iterator
>        parse(basic_format_parse_context<_CharT>& __pc)
> -      { return _M_f._M_parse(__pc, __format::_Year|__format::_Month); }
> +      {
> +       return _M_f._M_parse(__pc, __format::_Year|__format::_Month,
> +                            __defSpec);
> +      }
>
>        template<typename _Out>
>         typename basic_format_context<_Out, _CharT>::iterator
> @@ -2030,7 +2314,17 @@ namespace __format
>         { return _M_f._M_format(__t, __fc); }
>
>      private:
> -      __format::__formatter_chrono<_CharT> _M_f;
> +       static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
> +       {
> +         __format::_ChronoSpec<_CharT> __res{};
> +         __res._M_debug = true;
> +         __res._M_localized = true;
> +         __res._M_locale_specific = true;
> +         __res._M_chrono_specs =
> __format::_ChronoFormats<_CharT>::_S_ym();
> +         return __res;
> +       }();
> +
> +      __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>      };
>
>    template<__format::__char _CharT>
> @@ -2038,7 +2332,7 @@ namespace __format
>      {
>        constexpr typename basic_format_parse_context<_CharT>::iterator
>        parse(basic_format_parse_context<_CharT>& __pc)
> -      { return _M_f._M_parse(__pc, __format::_Date); }
> +      { return _M_f._M_parse(__pc, __format::_Date, __defSpec); }
>
>        template<typename _Out>
>         typename basic_format_context<_Out, _CharT>::iterator
> @@ -2047,7 +2341,15 @@ namespace __format
>         { return _M_f._M_format(__t, __fc); }
>
>      private:
> -      __format::__formatter_chrono<_CharT> _M_f;
> +      static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
> +       {
> +         __format::_ChronoSpec<_CharT> __res{};
> +         __res._M_debug = true;
> +         __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_f();
> +         return __res;
> +       }();
> +
> +      __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>      };
>
>    template<__format::__char _CharT>
> @@ -2055,7 +2357,7 @@ namespace __format
>      {
>        constexpr typename basic_format_parse_context<_CharT>::iterator
>        parse(basic_format_parse_context<_CharT>& __pc)
> -      { return _M_f._M_parse(__pc, __format::_Date); }
> +      { return _M_f._M_parse(__pc, __format::_Date, __defSpec); }
>
>        template<typename _Out>
>         typename basic_format_context<_Out, _CharT>::iterator
> @@ -2064,7 +2366,17 @@ namespace __format
>         { return _M_f._M_format(__t, __fc); }
>
>      private:
> -      __format::__formatter_chrono<_CharT> _M_f;
> +       static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
> +       {
> +         __format::_ChronoSpec<_CharT> __res{};
> +         __res._M_debug = true;
> +         __res._M_localized = true;
> +         __res._M_locale_specific = true;
> +         __res._M_chrono_specs =
> __format::_ChronoFormats<_CharT>::_S_yml();
> +         return __res;
> +       }();
> +
> +      __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>      };
>
>    template<__format::__char _CharT>
> @@ -2072,7 +2384,7 @@ namespace __format
>      {
>        constexpr typename basic_format_parse_context<_CharT>::iterator
>        parse(basic_format_parse_context<_CharT>& __pc)
> -      { return _M_f._M_parse(__pc, __format::_Date); }
> +      { return _M_f._M_parse(__pc, __format::_Date, __defSpec); }
>
>        template<typename _Out>
>         typename basic_format_context<_Out, _CharT>::iterator
> @@ -2081,7 +2393,17 @@ namespace __format
>         { return _M_f._M_format(__t, __fc); }
>
>      private:
> -      __format::__formatter_chrono<_CharT> _M_f;
> +       static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
> +       {
> +         __format::_ChronoSpec<_CharT> __res{};
> +         __res._M_debug = true;
> +         __res._M_localized = true;
> +         __res._M_locale_specific = true;
> +         __res._M_chrono_specs =
> __format::_ChronoFormats<_CharT>::_S_ymwi();
> +         return __res;
> +       }();
> +
> +      __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>      };
>
>    template<__format::__char _CharT>
> @@ -2089,7 +2411,7 @@ namespace __format
>      {
>        constexpr typename basic_format_parse_context<_CharT>::iterator
>        parse(basic_format_parse_context<_CharT>& __pc)
> -      { return _M_f._M_parse(__pc, __format::_Date); }
> +      { return _M_f._M_parse(__pc, __format::_Date, __defSpec); }
>
>        template<typename _Out>
>         typename basic_format_context<_Out, _CharT>::iterator
> @@ -2098,7 +2420,17 @@ namespace __format
>         { return _M_f._M_format(__t, __fc); }
>
>      private:
> -      __format::__formatter_chrono<_CharT> _M_f;
> +       static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
> +       {
> +         __format::_ChronoSpec<_CharT> __res{};
> +         __res._M_debug = true;
> +         __res._M_localized = true;
> +         __res._M_locale_specific = true;
> +         __res._M_chrono_specs =
> __format::_ChronoFormats<_CharT>::_S_ymwl();
> +         return __res;
> +       }();
> +
> +      __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>      };
>
>    template<typename _Rep, typename _Period, __format::__char _CharT>
> @@ -2947,7 +3279,7 @@ namespace __detail
>        // n.b. only decimal separator is locale dependent for specifiers
>        // used below, as sys_info uses seconds and minutes duration, the
>        // output is locale-independent.
> -      constexpr auto* __fs
> +      constexpr auto* __fs
>         = _GLIBCXX_WIDEN("[{0:%F %T},{1:%F %T},{2:%T},{3:%Q%q},{0:%Z}]");
>        local_seconds __lb(__i.begin.time_since_epoch());
>        __os << std::format(__fs, local_time_format(__lb, &__i.abbrev),
> --
> 2.49.0
>
>

Reply via email to