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{}; - 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