On Thu, 26 Jun 2025 at 14:19, Tomasz Kamiński <[email protected]> wrote:
>
> This patch extract calls to _M_locale_fmt and construction of the struct tm,
> from the functions dedicated to each specifier, to main format loop in
> _M_format_to functions. This removes duplicated code repeated for specifiers.
>
> To allow _M_locale_fmt to only be called if localized formatting is enabled
> ('L' is present in chrono-format-spec), we provide a implementations for
> locale specific specifiers (%c, %r, %x, %X) that produces the same result
> as locale::classic():
> * %c is implemented as separate _M_c method
> * %r is implemented as separate _M_r method
> * %x is implemented together with %D, as they provide same behavior,
> * %X is implemented together with %R as _M_R_X, as both of them do not
> include
> subseconds.
>
> The handling of subseconds was also extracted to _M_subsecs function that is
> used by _M_S and _M_T specifier. The _M_T is now implemented in terms of
> _M_R_X (printing time without subseconds) and _M_subs.
>
> The __mod responsible for triggering localized formatting was removed from
> method handling most of specifiers, except:
> * _M_S (for %S) for which it determines if subseconds should be included,
> * _M_z (for %z) for which it determines if ':' is used as separator.
>
> PR libstdc++/110739
>
> libstdc++-v3/ChangeLog:
>
> * include/bits/chrono_io.h (__formatter_chrono::_M_use_locale_fmt):
> Define.
> (__formatter_chrono::_M_locale_fmt): Moved to front of the class.
> (__formatter_chrono::_M_format_to): Construct and initialize
> struct tm and call _M_locale_fmt if needed.
> (__formatter_chrono::_M_c_r_x_X): Split into separate methods.
> (__formatter_chrono::_M_c, __formatter_chrono::_M_r): Define.
> (__formatter_chrono::_M_D): Renamed to _M_D_x.
> (__formatter_chrono::_M_D_x): Renamed from _M_D.
> (__formatter_chrono::_M_R_T): Split into _M_R_X and _M_T.
> (__formatter_chrono::_M_R_X): Extracted from _M_R_T.
> (__formatter_chrono::_M_T): Define in terms of _M_R_X and _M_subsecs.
> (__formatter_chrono::_M_subsecs): Extracted from _M_S.
> (__formatter_chrono::_M_S): Replaced __mod with __subs argument,
> removed _M_locale_fmt call, and delegate to _M_subsecs.
> (__formatter_chrono::_M_C_y_Y, __formatter_chrono::_M_d_e)
> (__formatter_chrono::_M_H_I, __formatter_chrono::_M_m)
> (__formatter_chrono::_M_u_w, __formatter_chrono::_M_U_V_W): Remove
> __mod argument and call to _M_locale_fmt.
>
> Reviewed-by: Jonathan Wakely <[email protected]>
> Signed-off-by: Tomasz Kamiński <[email protected]>
> ---
> Changes in v3:
> - restored missing comment in _M_S
> - increment __out before calling _M_C_y_Y in _M_c
OK for trunk, thanks
>
> libstdc++-v3/include/bits/chrono_io.h | 338 +++++++++++++-------------
> 1 file changed, 171 insertions(+), 167 deletions(-)
>
> diff --git a/libstdc++-v3/include/bits/chrono_io.h
> b/libstdc++-v3/include/bits/chrono_io.h
> index 8811eaa5b3b..9e21152e398 100644
> --- a/libstdc++-v3/include/bits/chrono_io.h
> +++ b/libstdc++-v3/include/bits/chrono_io.h
> @@ -908,6 +908,40 @@ namespace __format
> return __format::__write(std::move(__out), __s);
> }
>
> + [[__gnu__::__always_inline__]]
> + static bool
> + _S_localized_spec(_CharT __conv, _CharT __mod)
> + {
> + switch (__conv)
> + {
> + case 'c':
> + case 'r':
> + case 'x':
> + case 'X':
> + return true;
> + case 'z':
> + return false;
> + default:
> + return (bool)__mod;
> + };
> + }
> +
> + // Use the formatting locale's std::time_put facet to produce
> + // a locale-specific representation.
> + template<typename _Iter>
> + _Iter
> + _M_locale_fmt(_Iter __out, const locale& __loc, const struct tm& __tm,
> + char __fmt, char __mod) const
> + {
> + basic_ostringstream<_CharT> __os;
> + __os.imbue(__loc);
> + const auto& __tp = use_facet<time_put<_CharT>>(__loc);
> + __tp.put(__os, __os, _S_space, &__tm, __fmt, __mod);
> + if (__os)
> + __out = _M_write(std::move(__out), __loc, __os.view());
> + return __out;
> + }
> +
> template<typename _Out, typename _FormatContext>
> _Out
> _M_format_to(const _ChronoData<_CharT>& __t, _Out __out,
> @@ -925,6 +959,36 @@ namespace __format
> return std::move(__out);
> };
>
> + struct tm __tm{};
> + bool __use_locale_fmt = false;
> + if (_M_spec._M_localized && _M_spec._M_locale_specific)
> + if (__fc.locale() != locale::classic())
> + {
> + __use_locale_fmt = true;
> +
> + __tm.tm_year = (int)__t._M_year - 1900;
> + __tm.tm_yday = __t._M_day_of_year.count();
> + __tm.tm_mon = (unsigned)__t._M_month - 1;
> + __tm.tm_mday = (unsigned)__t._M_day;
> + __tm.tm_wday = __t._M_weekday.c_encoding();
> + __tm.tm_hour = __t._M_hours.count();
> + __tm.tm_min = __t._M_minutes.count();
> + __tm.tm_sec = __t._M_seconds.count();
> +
> + // Some locales use %Z in their %c format but we don't want
> strftime
> + // to use the system's local time zone (from /etc/localtime
> or $TZ)
> + // as the output for %Z. Setting tm_isdst to -1 says there is
> no
> + // time zone info available for the time in __tm.
> + __tm.tm_isdst = -1;
> +
> +#ifdef _GLIBCXX_USE_STRUCT_TM_TM_ZONE
> + // POSIX.1-2024 adds tm.tm_zone which will be used for %Z.
> + // BSD has had tm_zone since 1987 but as char* so cast away
> const.
> + if (__t._M_zone_cstr)
> + __tm.tm_zone = const_cast<char*>(__t._M_zone_cstr);
> +#endif
> + }
> +
> // Characters to output for "%n", "%t" and "%%" specifiers.
> constexpr const _CharT* __literals = _GLIBCXX_WIDEN("\n\t%");
>
> @@ -934,7 +998,10 @@ namespace __format
> do
> {
> _CharT __c = *__first++;
> - switch (__c)
> + if (__use_locale_fmt && _S_localized_spec(__c, __mod))
> [[unlikely]]
> + __out = _M_locale_fmt(std::move(__out), __fc.locale(),
> + __tm, __c, __mod);
> + else switch (__c)
> {
> // %\0 is extension for handling weekday index
> case '\0':
> @@ -950,22 +1017,20 @@ namespace __format
> __out = _M_b_B(__t._M_month, std::move(__out), __fc, __c ==
> 'B');
> break;
> case 'c':
> - case 'r':
> - case 'x':
> - case 'X':
> - __out = _M_c_r_x_X(__t, std::move(__out), __fc, __c, __mod);
> + __out = _M_c(__t, std::move(__out), __fc);
> break;
> case 'C':
> case 'y':
> case 'Y':
> - __out = _M_C_y_Y(__t._M_year, std::move(__out), __fc, __c,
> __mod);
> + __out = _M_C_y_Y(__t._M_year, std::move(__out), __fc, __c);
> break;
> case 'd':
> case 'e':
> - __out = _M_d_e(__t._M_day, std::move(__out), __fc, __c,
> __mod == 'O');
> + __out = _M_d_e(__t._M_day, std::move(__out), __fc, __c);
> break;
> case 'D':
> - __out = _M_D(__t, std::move(__out), __fc);
> + case 'x':
> + __out = _M_D_x(__t, std::move(__out), __fc);
> break;
> case 'F':
> __out = _M_F(__t, std::move(__out), __fc);
> @@ -976,16 +1041,16 @@ namespace __format
> break;
> case 'H':
> case 'I':
> - __out = _M_H_I(__t._M_hours, __print_sign(), __fc, __c,
> __mod == 'O');
> + __out = _M_H_I(__t._M_hours, __print_sign(), __fc, __c);
> break;
> case 'j':
> __out = _M_j(__t, __print_sign(), __fc);
> break;
> case 'm':
> - __out = _M_m(__t._M_month, std::move(__out), __fc, __mod ==
> 'O');
> + __out = _M_m(__t._M_month, std::move(__out), __fc);
> break;
> case 'M':
> - __out = _M_M(__t._M_minutes, __print_sign(), __fc, __mod ==
> 'O');
> + __out = _M_M(__t._M_minutes, __print_sign(), __fc);
> break;
> case 'p':
> __out = _M_p(__t._M_hours, std::move(__out), __fc);
> @@ -996,22 +1061,27 @@ namespace __format
> case 'Q':
> __out = _M_Q(__t, __print_sign(), __fc);
> break;
> + case 'r':
> + __out = _M_r(__t, __print_sign(), __fc);
> + break;
> case 'R':
> + case 'X':
> + __out = _M_R_X(__t, __print_sign(), __fc, __c != 'R');
> + break;
> case 'T':
> - __out = _M_R_T(__t, __print_sign(), __fc, __c == 'T');
> + __out = _M_T(__t, __print_sign(), __fc);
> break;
> case 'S':
> - __out = _M_S(__t, __print_sign(), __fc, __mod == 'O');
> + __out = _M_S(__t, __print_sign(), __fc, __mod != 'O');
> break;
> case 'u':
> case 'w':
> - __out = _M_u_w(__t._M_weekday, std::move(__out), __fc, __c,
> __mod == 'O');
> + __out = _M_u_w(__t._M_weekday, std::move(__out), __fc, __c);
> break;
> case 'U':
> case 'V':
> case 'W':
> - __out = _M_U_V_W(__t, std::move(__out), __fc, __c,
> - __mod == 'O');
> + __out = _M_U_V_W(__t, std::move(__out), __fc, __c);
> break;
> case 'z':
> __out = _M_z(__t._M_zone_offset, std::move(__out), __fc,
> (bool)__mod);
> @@ -1134,50 +1204,27 @@ namespace __format
>
> template<typename _FormatContext>
> typename _FormatContext::iterator
> - _M_c_r_x_X(const _ChronoData<_CharT>& __t, typename
> _FormatContext::iterator __out,
> - _FormatContext& __ctx, _CharT __conv, _CharT __mod) const
> + _M_c(const _ChronoData<_CharT>& __t, typename
> _FormatContext::iterator __out,
> + _FormatContext& __ctx) const
> {
> - // %c Locale's date and time representation.
> - // %Ec Locale's alternate date and time representation.
> - // %r Locale's 12-hour clock time.
> - // %x Locale's date rep
> - // %Ex Locale's alternative date representation.
> - // %X Locale's time rep
> - // %EX Locale's alternative time representation.
> -
> - using namespace chrono;
> - struct tm __tm{};
> -
> - // Some locales use %Z in their %c format but we don't want strftime
> - // to use the system's local time zone (from /etc/localtime or $TZ)
> - // as the output for %Z. Setting tm_isdst to -1 says there is no
> - // time zone info available for the time in __tm.
> - __tm.tm_isdst = -1;
> -
> -#ifdef _GLIBCXX_USE_STRUCT_TM_TM_ZONE
> - // POSIX.1-2024 adds tm.tm_zone which will be used for %Z.
> - // BSD has had tm_zone since 1987 but as char* so cast away const.
> - if (__t._M_zone_cstr)
> - __tm.tm_zone = const_cast<char*>(__t._M_zone_cstr);
> -#endif
> -
> - __tm.tm_year = (int)__t._M_year - 1900;
> - __tm.tm_yday = __t._M_day_of_year.count();
> - __tm.tm_mon = (unsigned)__t._M_month - 1;
> - __tm.tm_mday = (unsigned)__t._M_day;
> - __tm.tm_wday = __t._M_weekday.c_encoding();
> - __tm.tm_hour = __t._M_hours.count();
> - __tm.tm_min = __t._M_minutes.count();
> - __tm.tm_sec = __t._M_seconds.count();
> -
> - return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
> - __conv, __mod);
> + // %c Locale's date and time representation, for C-locale: %a %b
> %e %T %Y
> + // %Ec Locale's alternate date and time representation, for
> C-locale same as above
> +
> + __out = _M_a_A(__t._M_weekday, std::move(__out), __ctx, false);
> + *__out = _S_space;
> + __out = _M_b_B(__t._M_month, std::move(++__out), __ctx, false);
> + *__out = _S_space;
> + __out = _M_d_e(__t._M_day, std::move(++__out), __ctx, 'e');
> + *__out = _S_space;
> + __out = _M_R_X(__t, std::move(++__out), __ctx, true);
> + *__out = _S_space;
> + return _M_C_y_Y(__t._M_year, std::move(++__out), __ctx, 'Y');
> }
>
> template<typename _FormatContext>
> typename _FormatContext::iterator
> _M_C_y_Y(chrono::year __y, typename _FormatContext::iterator __out,
> - _FormatContext& __ctx, _CharT __conv, _CharT __mod = 0) const
> + _FormatContext& __ctx, _CharT __conv) const
> {
> // %C Year divided by 100 using floored division.
> // %EC Locale's alternative preresentation of the century (era
> name).
> @@ -1187,15 +1234,6 @@ namespace __format
> // %Y Year as a decimal number.
> // %EY Locale's alternative full year representation.
>
> - if (__mod && _M_spec._M_localized) [[unlikely]]
> - if (auto __loc = __ctx.locale(); __loc != locale::classic())
> - {
> - struct tm __tm{};
> - __tm.tm_year = (int)__y - 1900;
> - return _M_locale_fmt(std::move(__out), __loc, __tm,
> - __conv, __mod);
> - }
> -
> int __yi = (int)__y;
> const bool __is_neg = __yi < 0;
> __yi = __builtin_abs(__yi);
> @@ -1237,9 +1275,13 @@ namespace __format
>
> template<typename _FormatContext>
> typename _FormatContext::iterator
> - _M_D(const _ChronoData<_CharT>& __t, typename
> _FormatContext::iterator __out,
> - _FormatContext&) const
> + _M_D_x(const _ChronoData<_CharT>& __t, typename
> _FormatContext::iterator __out,
> + _FormatContext&) const
> {
> + // %D Equivalent to %m/%d/%y
> + // %x Locale's date rep, for C-locale: %m/%d/%y
> + // %Ex Locale's alternative date representation, for C-locale same
> as above
> +
> auto __di = (unsigned)__t._M_day;
> auto __mi = (unsigned)__t._M_month;
> auto __yi = __builtin_abs((int)__t._M_year) % 100;
> @@ -1269,7 +1311,7 @@ namespace __format
> template<typename _FormatContext>
> typename _FormatContext::iterator
> _M_d_e(chrono::day __d, typename _FormatContext::iterator __out,
> - _FormatContext& __ctx, _CharT __conv, bool __mod = false) const
> + _FormatContext& __ctx, _CharT __conv) const
> {
> // %d The day of month as a decimal number.
> // %Od Locale's alternative representation.
> @@ -1278,15 +1320,6 @@ namespace __format
>
> unsigned __i = (unsigned)__d;
>
> - if (__mod && _M_spec._M_localized) [[unlikely]]
> - if (auto __loc = __ctx.locale(); __loc != locale::classic())
> - {
> - struct tm __tm{};
> - __tm.tm_mday = __i;
> - return _M_locale_fmt(std::move(__out), __loc, __tm,
> - (char)__conv, 'O');
> - }
> -
> _CharT __buf[3];
> auto __sv = _S_str_d2(__buf, __i);
> if (__conv == _CharT('e') && __i < 10)
> @@ -1362,7 +1395,7 @@ namespace __format
> template<typename _FormatContext>
> typename _FormatContext::iterator
> _M_H_I(chrono::hours __h, typename _FormatContext::iterator __out,
> - _FormatContext& __ctx, _CharT __conv, bool __mod = false) const
> + _FormatContext& __ctx, _CharT __conv) const
> {
> // %H The hour (24-hour clock) as a decimal number.
> // %OH Locale's alternative representation.
> @@ -1371,15 +1404,6 @@ namespace __format
>
> int __i = __h.count();
>
> - if (__mod && _M_spec._M_localized) [[unlikely]]
> - if (auto __loc = __ctx.locale(); __loc != locale::classic())
> - {
> - struct tm __tm{};
> - __tm.tm_hour = __i;
> - return _M_locale_fmt(std::move(__out), __loc, __tm,
> - (char)__conv, 'O');
> - }
> -
> if (__conv == _CharT('I'))
> {
> __i %= 12;
> @@ -1411,22 +1435,13 @@ namespace __format
> template<typename _FormatContext>
> typename _FormatContext::iterator
> _M_m(chrono::month __m, typename _FormatContext::iterator __out,
> - _FormatContext& __ctx, bool __mod) const
> + _FormatContext& __ctx) const
> {
> // %m month as a decimal number.
> // %Om Locale's alternative representation.
>
> auto __i = (unsigned)__m;
>
> - if (__mod && _M_spec._M_localized) [[unlikely]] // %Om
> - if (auto __loc = __ctx.locale(); __loc != locale::classic())
> - {
> - struct tm __tm{};
> - __tm.tm_mon = __i - 1;
> - return _M_locale_fmt(std::move(__out), __loc, __tm,
> - 'm', 'O');
> - }
> -
> _CharT __buf[3];
> return __format::__write(std::move(__out), _S_str_d2(__buf, __i));
> }
> @@ -1434,22 +1449,12 @@ namespace __format
> template<typename _FormatContext>
> typename _FormatContext::iterator
> _M_M(chrono::minutes __m, typename _FormatContext::iterator __out,
> - _FormatContext& __ctx, bool __mod) const
> + _FormatContext& __ctx) const
> {
> // %M The minute as a decimal number.
> // %OM Locale's alternative representation.
>
> auto __i = __m.count();
> -
> - if (__mod && _M_spec._M_localized) [[unlikely]] // %OM
> - if (auto __loc = __ctx.locale(); __loc != locale::classic())
> - {
> - struct tm __tm{};
> - __tm.tm_min = __i;
> - return _M_locale_fmt(std::move(__out), __loc, __tm,
> - 'M', 'O');
> - }
> -
> return __format::__write(std::move(__out), _S_two_digits(__i));
> }
>
> @@ -1490,17 +1495,42 @@ namespace __format
>
> template<typename _FormatContext>
> typename _FormatContext::iterator
> - _M_R_T(const _ChronoData<_CharT>& __t, typename
> _FormatContext::iterator __out,
> + _M_r(const _ChronoData<_CharT>& __t, typename
> _FormatContext::iterator __out,
> + _FormatContext& __ctx) const
> + {
> + // %r Locale's 12-hour clock time, for C-locale: %I:%M:%S %p
> + auto __hi = __t._M_hours.count() % 12;
> + if (__hi == 0)
> + __hi = 12;
> +
> + _CharT __buf[9];
> + __buf[2] = _S_colon;
> + __buf[5] = _S_colon;
> + __buf[8] = _S_space;
> + _S_fill_two_digits(__buf, __hi);
> + _S_fill_two_digits(__buf + 3, __t._M_minutes.count());
> + _S_fill_two_digits(__buf + 6, __t._M_seconds.count());
> +
> + __string_view __sv(__buf, 9);
> + __out = __format::__write(std::move(__out), __sv);
> + return _M_p(__t._M_hours, std::move(__out), __ctx);
> + }
> +
> + template<typename _FormatContext>
> + typename _FormatContext::iterator
> + _M_R_X(const _ChronoData<_CharT>& __t, typename
> _FormatContext::iterator __out,
> _FormatContext& __ctx, bool __secs) const
> {
> - // %R Equivalent to %H:%M
> - // %T Equivalent to %H:%M:%S
> + // %R Equivalent to %H:%M
> + // %X Locale's time rep, for C-locale: %H:%M:%S (without
> subseconds)
> + // %EX Locale's alternative time representation, for C-locale same
> as above
> +
> auto __hi = __t._M_hours.count();
>
> - _CharT __buf[6];
> + _CharT __buf[8];
> __buf[2] = _S_colon;
> __buf[5] = _S_colon;
> - __string_view __sv(__buf, 5 + __secs);
> + __string_view __sv(__buf, 8);
>
> if (__hi >= 100) [[unlikely]]
> {
> @@ -1511,39 +1541,40 @@ namespace __format
> _S_fill_two_digits(__buf, __hi);
>
> _S_fill_two_digits(__buf + 3, __t._M_minutes.count());
> - __out = __format::__write(std::move(__out), __sv);
> if (__secs)
> - __out = _M_S(__t, std::move(__out), __ctx);
> - return __out;
> + _S_fill_two_digits(__buf + 6, __t._M_seconds.count());
> + else
> + __sv.remove_suffix(3);
> +
> + return __format::__write(std::move(__out), __sv);
> }
>
> template<typename _FormatContext>
> typename _FormatContext::iterator
> _M_S(const _ChronoData<_CharT>& __t, typename
> _FormatContext::iterator __out,
> - _FormatContext& __ctx, bool __mod = false) const
> + _FormatContext& __ctx, bool __subs = true) const
> {
> // %S Seconds as a decimal number.
> // %OS The locale's alternative representation.
> auto __s = __t._M_seconds;
>
> - if (__mod && _M_spec._M_localized) [[unlikely]] // %OS
> - if (auto __loc = __ctx.locale(); __loc != locale::classic())
> - {
> - struct tm __tm{};
> - __tm.tm_sec = (int)__s.count();
> - return _M_locale_fmt(std::move(__out), __loc, __tm,
> - 'S', 'O');
> - }
> -
> __out = __format::__write(std::move(__out),
> - _S_two_digits(__s.count()));
> + _S_two_digits(__s.count()));
> + if (__subs)
> + __out = _M_subsecs(__t, std::move(__out), __ctx);
> + return __out;
> + }
>
> + template<typename _FormatContext>
> + typename _FormatContext::iterator
> + _M_subsecs(const _ChronoData<_CharT>& __t,
> + typename _FormatContext::iterator __out,
> + _FormatContext& __ctx) const
> + {
> unsigned __prec = _M_spec._M_prec_kind != _WP_none
> ? _M_spec._M_get_precision(__ctx)
> : _M_spec._M_prec;
> -
> - // %OS formats don't include subseconds
> - if (__prec == 0 || __mod)
> + if (__prec == 0)
> return __out;
>
> _CharT __dot = _S_dot;
> @@ -1597,25 +1628,25 @@ namespace __format
>
> // %t handled in _M_format
>
> + template<typename _FormatContext>
> + typename _FormatContext::iterator
> + _M_T(const _ChronoData<_CharT>& __t, typename
> _FormatContext::iterator __out,
> + _FormatContext& __ctx) const
> + {
> + // %T Equivalent to %H:%M:%S, with subseconds
> + __out = _M_R_X(__t, std::move(__out), __ctx, true);
> + return _M_subsecs(__t, std::move(__out), __ctx);
> + }
> +
> template<typename _FormatContext>
> typename _FormatContext::iterator
> _M_u_w(chrono::weekday __wd, typename _FormatContext::iterator __out,
> - _FormatContext& __ctx, _CharT __conv, bool __mod = false) const
> + _FormatContext& __ctx, _CharT __conv) const
> {
> // %u ISO weekday as a decimal number (1-7), where Monday is 1.
> // %Ou Locale's alternative numeric rep.
> // %w Weekday as a decimal number (0-6), where Sunday is 0.
> // %Ow Locale's alternative numeric rep.
> -
> - if (__mod && _M_spec._M_localized) [[unlikely]]
> - if (auto __loc = __ctx.locale(); __loc != locale::classic())
> - {
> - struct tm __tm{};
> - __tm.tm_wday = __wd.c_encoding();
> - return _M_locale_fmt(std::move(__out), __loc, __tm,
> - (char)__conv, 'O');
> - }
> -
> unsigned __wdi = __conv == 'u' ? __wd.iso_encoding()
> : __wd.c_encoding();
> _CharT __buf[3];
> @@ -1625,7 +1656,7 @@ namespace __format
> template<typename _FormatContext>
> typename _FormatContext::iterator
> _M_U_V_W(const _ChronoData<_CharT>& __t, typename
> _FormatContext::iterator __out,
> - _FormatContext& __ctx, _CharT __conv, bool __mod = false)
> const
> + _FormatContext& __ctx, _CharT __conv) const
> {
> // %U Week number of the year as a decimal number, from first
> Sunday.
> // %OU Locale's alternative numeric rep.
> @@ -1635,17 +1666,6 @@ namespace __format
> // %OW Locale's alternative numeric rep.
> using namespace chrono;
>
> - if (__mod && _M_spec._M_localized) [[unlikely]]
> - if (auto __loc = __ctx.locale(); __loc != locale::classic())
> - {
> - struct tm __tm{};
> - __tm.tm_year = (int)__t._M_year - 1900;
> - __tm.tm_yday = __t._M_day_of_year.count();
> - __tm.tm_wday = __t._M_weekday.c_encoding();
> - return _M_locale_fmt(std::move(__out), __loc, __tm,
> - (char)__conv, 'O');
> - }
> -
> auto __d = __t._M_ldays;
> local_days __first; // First day of week 1.
> if (__conv == 'V') // W01 begins on Monday before first Thursday.
> @@ -1757,22 +1777,6 @@ namespace __format
> __buf[2] = _S_chars[__n % 10];
> return __string_view(__buf.data(), 3);
> }
> -
> - // Use the formatting locale's std::time_put facet to produce
> - // a locale-specific representation.
> - template<typename _Iter>
> - _Iter
> - _M_locale_fmt(_Iter __out, const locale& __loc, const struct tm& __tm,
> - char __fmt, char __mod) const
> - {
> - basic_ostringstream<_CharT> __os;
> - __os.imbue(__loc);
> - const auto& __tp = use_facet<time_put<_CharT>>(__loc);
> - __tp.put(__os, __os, _S_space, &__tm, __fmt, __mod);
> - if (__os)
> - __out = _M_write(std::move(__out), __loc, __os.view());
> - return __out;
> - }
> };
>
> template<typename _CharT>
> --
> 2.49.0
>