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