Home | History | Annotate | Line # | Download | only in bits
      1 // <chrono> Formatting -*- C++ -*-
      2 
      3 // Copyright The GNU Toolchain Authors.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file include/bits/chrono_io.h
     26  *  This is an internal header file, included by other library headers.
     27  *  Do not attempt to use it directly. @headername{chrono}
     28  */
     29 
     30 #ifndef _GLIBCXX_CHRONO_IO_H
     31 #define _GLIBCXX_CHRONO_IO_H 1
     32 
     33 #pragma GCC system_header
     34 
     35 #if __cplusplus >= 202002L
     36 
     37 #include <sstream> // ostringstream
     38 #include <iomanip> // setw, setfill
     39 #include <format>
     40 #include <charconv> // from_chars
     41 
     42 #include <bits/streambuf_iterator.h>
     43 
     44 namespace std _GLIBCXX_VISIBILITY(default)
     45 {
     46 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     47 
     48 namespace chrono
     49 {
     50 /// @addtogroup chrono
     51 /// @{
     52 
     53 /// @cond undocumented
     54 namespace __detail
     55 {
     56   // STATICALLY-WIDEN, see C++20 [time.general]
     57   // It doesn't matter for format strings (which can only be char or wchar_t)
     58   // but this returns the narrow string for anything that isn't wchar_t. This
     59   // is done because const char* can be inserted into any ostream type, and
     60   // will be widened at runtime if necessary.
     61   template<typename _CharT>
     62     consteval auto
     63     _Widen(const char* __narrow, const wchar_t* __wide)
     64     {
     65       if constexpr (is_same_v<_CharT, wchar_t>)
     66 	return __wide;
     67       else
     68 	return __narrow;
     69     }
     70 #define _GLIBCXX_WIDEN_(C, S) ::std::chrono::__detail::_Widen<C>(S, L##S)
     71 #define _GLIBCXX_WIDEN(S) _GLIBCXX_WIDEN_(_CharT, S)
     72 
     73   template<typename _Period, typename _CharT>
     74     constexpr basic_string_view<_CharT>
     75     __units_suffix() noexcept
     76     {
     77       // The standard say these are all narrow strings, which would need to
     78       // be widened at run-time when inserted into a wide stream. We use
     79       // STATICALLY-WIDEN to widen at compile-time.
     80 #define _GLIBCXX_UNITS_SUFFIX(period, suffix) \
     81     if constexpr (is_same_v<_Period, period>) \
     82       return _GLIBCXX_WIDEN(suffix);	      \
     83     else
     84 
     85       _GLIBCXX_UNITS_SUFFIX(atto,  "as")
     86       _GLIBCXX_UNITS_SUFFIX(femto, "fs")
     87       _GLIBCXX_UNITS_SUFFIX(pico,  "ps")
     88       _GLIBCXX_UNITS_SUFFIX(nano,  "ns")
     89       _GLIBCXX_UNITS_SUFFIX(milli, "ms")
     90 #if _GLIBCXX_USE_ALT_MICROSECONDS_SUFFIX
     91       // Deciding this at compile-time is wrong, maybe use nl_langinfo(CODESET)
     92       // to check runtime environment and return u8"\u00b5s", "\xb5s", or "us".
     93       _GLIBCXX_UNITS_SUFFIX(micro, "\u00b5s")
     94 #else
     95       _GLIBCXX_UNITS_SUFFIX(micro, "us")
     96 #endif
     97       _GLIBCXX_UNITS_SUFFIX(centi, "cs")
     98       _GLIBCXX_UNITS_SUFFIX(deci,  "ds")
     99       _GLIBCXX_UNITS_SUFFIX(ratio<1>, "s")
    100       _GLIBCXX_UNITS_SUFFIX(deca,  "das")
    101       _GLIBCXX_UNITS_SUFFIX(hecto, "hs")
    102       _GLIBCXX_UNITS_SUFFIX(kilo,  "ks")
    103       _GLIBCXX_UNITS_SUFFIX(mega,  "Ms")
    104       _GLIBCXX_UNITS_SUFFIX(giga,  "Gs")
    105       _GLIBCXX_UNITS_SUFFIX(tera,  "Ts")
    106       _GLIBCXX_UNITS_SUFFIX(tera,  "Ts")
    107       _GLIBCXX_UNITS_SUFFIX(peta,  "Ps")
    108       _GLIBCXX_UNITS_SUFFIX(exa,   "Es")
    109       _GLIBCXX_UNITS_SUFFIX(ratio<60>,    "min")
    110       _GLIBCXX_UNITS_SUFFIX(ratio<3600>,  "h")
    111       _GLIBCXX_UNITS_SUFFIX(ratio<86400>, "d")
    112 #undef _GLIBCXX_UNITS_SUFFIX
    113 	return {};
    114     }
    115 
    116   template<typename _Period, typename _CharT, typename _Out>
    117     inline _Out
    118     __fmt_units_suffix(_Out __out) noexcept
    119     {
    120       if (auto __s = __detail::__units_suffix<_Period, _CharT>(); __s.size())
    121 	return __format::__write(std::move(__out), __s);
    122       else if constexpr (_Period::den == 1)
    123 	return std::format_to(std::move(__out), _GLIBCXX_WIDEN("[{}]s"),
    124 			      (uintmax_t)_Period::num);
    125       else
    126 	return std::format_to(std::move(__out), _GLIBCXX_WIDEN("[{}/{}]s"),
    127 			      (uintmax_t)_Period::num,
    128 			      (uintmax_t)_Period::den);
    129     }
    130 } // namespace __detail
    131 /// @endcond
    132 
    133   /** Write a `chrono::duration` to an ostream.
    134    *
    135    * @since C++20
    136    */
    137   template<typename _CharT, typename _Traits,
    138 	   typename _Rep, typename _Period>
    139     inline basic_ostream<_CharT, _Traits>&
    140     operator<<(std::basic_ostream<_CharT, _Traits>& __os,
    141 	       const duration<_Rep, _Period>& __d)
    142     {
    143       using _Out = ostreambuf_iterator<_CharT, _Traits>;
    144       using period = typename _Period::type;
    145       std::basic_ostringstream<_CharT, _Traits> __s;
    146       __s.flags(__os.flags());
    147       __s.imbue(__os.getloc());
    148       __s.precision(__os.precision());
    149       __s << __d.count();
    150       __detail::__fmt_units_suffix<period, _CharT>(_Out(__s));
    151       __os << std::move(__s).str();
    152       return __os;
    153     }
    154 
    155 /// @cond undocumented
    156 namespace __detail
    157 {
    158   // An unspecified type returned by `chrono::local_time_format`.
    159   template<typename _Duration>
    160     struct __local_time_fmt
    161     {
    162       local_time<_Duration> _M_time;
    163       const string* _M_abbrev;
    164       const seconds* _M_offset_sec;
    165     };
    166 
    167   struct __local_fmt_t;
    168 }
    169 /// @endcond
    170 
    171   /** Return an object that asssociates timezone info with a local time.
    172    *
    173    * A `chrono::local_time` object has no timezone associated with it. This
    174    * function creates an object that allows formatting a `local_time` as
    175    * though it refers to a timezone with the given abbreviated name and
    176    * offset from UTC.
    177    *
    178    * @since C++20
    179    */
    180   template<typename _Duration>
    181     inline __detail::__local_time_fmt<_Duration>
    182     local_time_format(local_time<_Duration> __time,
    183 		      const string* __abbrev = nullptr,
    184 		      const seconds* __offset_sec = nullptr)
    185     { return {__time, __abbrev, __offset_sec}; }
    186 
    187   /// @}
    188 } // namespace chrono
    189 
    190 /// @cond undocumented
    191 namespace __format
    192 {
    193   [[noreturn,__gnu__::__always_inline__]]
    194   inline void
    195   __no_timezone_available()
    196   { __throw_format_error("format error: no timezone available for %Z or %z"); }
    197 
    198   [[noreturn,__gnu__::__always_inline__]]
    199   inline void
    200   __not_valid_for_duration()
    201   { __throw_format_error("format error: chrono-format-spec not valid for "
    202 			 "chrono::duration"); }
    203 
    204   [[noreturn,__gnu__::__always_inline__]]
    205   inline void
    206   __invalid_chrono_spec()
    207   { __throw_format_error("format error: chrono-format-spec not valid for "
    208 			 "argument type"); }
    209 
    210   template<typename _CharT>
    211     struct _ChronoSpec : _Spec<_CharT>
    212     {
    213       basic_string_view<_CharT> _M_chrono_specs;
    214     };
    215 
    216   // Represents the information provided by a chrono type.
    217   // e.g. month_weekday has month and weekday but no year or time of day,
    218   // hh_mm_ss has time of day but no date, sys_time is time_point+timezone.
    219   enum _ChronoParts {
    220     _Year = 1, _Month = 2, _Day = 4, _Weekday = 8, _TimeOfDay = 16,
    221     _TimeZone = 32,
    222     _Date = _Year | _Month | _Day | _Weekday,
    223     _DateTime = _Date | _TimeOfDay,
    224     _ZonedDateTime = _DateTime | _TimeZone,
    225     _Duration = 128 // special case
    226   };
    227 
    228   constexpr _ChronoParts
    229   operator|(_ChronoParts __x, _ChronoParts __y) noexcept
    230   { return static_cast<_ChronoParts>((int)__x | (int)__y); }
    231 
    232   constexpr _ChronoParts&
    233   operator|=(_ChronoParts& __x, _ChronoParts __y) noexcept
    234   { return __x = __x | __y; }
    235 
    236   // TODO rename this to chrono::__formatter? or chrono::__detail::__formatter?
    237   template<typename _CharT>
    238     struct __formatter_chrono
    239     {
    240       using __string_view = basic_string_view<_CharT>;
    241       using __string = basic_string<_CharT>;
    242 
    243       template<typename _ParseContext>
    244 	constexpr typename _ParseContext::iterator
    245 	_M_parse(_ParseContext& __pc, _ChronoParts __parts)
    246 	{
    247 	  auto __first = __pc.begin();
    248 	  auto __last = __pc.end();
    249 
    250 	  _ChronoSpec<_CharT> __spec{};
    251 
    252 	  auto __finalize = [this, &__spec] {
    253 	    _M_spec = __spec;
    254 	  };
    255 
    256 	  auto __finished = [&] {
    257 	    if (__first == __last || *__first == '}')
    258 	      {
    259 		__finalize();
    260 		return true;
    261 	      }
    262 	    return false;
    263 	  };
    264 
    265 	  if (__finished())
    266 	    return __first;
    267 
    268 	  __first = __spec._M_parse_fill_and_align(__first, __last);
    269 	  if (__finished())
    270 	    return __first;
    271 
    272 	  __first = __spec._M_parse_width(__first, __last, __pc);
    273 	  if (__finished())
    274 	    return __first;
    275 
    276 	  if (__parts & _ChronoParts::_Duration)
    277 	    {
    278 	      __first = __spec._M_parse_precision(__first, __last, __pc);
    279 	      if (__finished())
    280 		return __first;
    281 	    }
    282 
    283 	  __first = __spec._M_parse_locale(__first, __last);
    284 	  if (__finished())
    285 	    return __first;
    286 
    287 	  // Everything up to the end of the string or the first '}' is a
    288 	  // chrono-specs string. Check it is valid.
    289 	  {
    290 	    __string_view __str(__first, __last - __first);
    291 	    auto __end = __str.find('}');
    292 	    if (__end != __str.npos)
    293 	      {
    294 		__str.remove_suffix(__str.length() - __end);
    295 		__last = __first + __end;
    296 	      }
    297 	    if (__str.find('{') != __str.npos)
    298 	      __throw_format_error("chrono format error: '{' in chrono-specs");
    299 	  }
    300 
    301 	  // Parse chrono-specs in [first,last), checking each conversion-spec
    302 	  // against __parts (so fail for %Y if no year in parts).
    303 	  // Save range in __spec._M_chrono_specs.
    304 
    305 	  const auto __chrono_specs = __first++; // Skip leading '%'
    306 	  if (*__chrono_specs != '%')
    307 	    __throw_format_error("chrono format error: no '%' at start of "
    308 				     "chrono-specs");
    309 
    310 	  _CharT __mod{};
    311 	  bool __conv = true;
    312 	  int __needed = 0;
    313 
    314 	  while (__first != __last)
    315 	    {
    316 	      enum _Mods { _Mod_none, _Mod_E, _Mod_O, _Mod_E_O };
    317 	      _Mods __allowed_mods = _Mod_none;
    318 
    319 	      _CharT __c = *__first++;
    320 	      switch (__c)
    321 		{
    322 		case 'a':
    323 		case 'A':
    324 		  __needed = _Weekday;
    325 		  break;
    326 		case 'b':
    327 		case 'h':
    328 		case 'B':
    329 		  __needed = _Month;
    330 		  break;
    331 		case 'c':
    332 		  __needed = _DateTime;
    333 		  __allowed_mods = _Mod_E;
    334 		  break;
    335 		case 'C':
    336 		  __needed = _Year;
    337 		  __allowed_mods = _Mod_E;
    338 		  break;
    339 		case 'd':
    340 		case 'e':
    341 		  __needed = _Day;
    342 		  __allowed_mods = _Mod_O;
    343 		  break;
    344 		case 'D':
    345 		case 'F':
    346 		  __needed = _Date;
    347 		  break;
    348 		case 'g':
    349 		case 'G':
    350 		  __needed = _Date;
    351 		  break;
    352 		case 'H':
    353 		case 'I':
    354 		  __needed = _TimeOfDay;
    355 		  __allowed_mods = _Mod_O;
    356 		  break;
    357 		case 'j':
    358 		  if (!(__parts & _Duration))
    359 		    __needed = _Date;
    360 		  break;
    361 		case 'm':
    362 		  __needed = _Month;
    363 		  __allowed_mods = _Mod_O;
    364 		  break;
    365 		case 'M':
    366 		  __needed = _TimeOfDay;
    367 		  __allowed_mods = _Mod_O;
    368 		  break;
    369 		case 'p':
    370 		case 'r':
    371 		case 'R':
    372 		case 'T':
    373 		  __needed = _TimeOfDay;
    374 		  break;
    375 		case 'q':
    376 		case 'Q':
    377 		  __needed = _Duration;
    378 		  break;
    379 		case 'S':
    380 		  __needed = _TimeOfDay;
    381 		  __allowed_mods = _Mod_O;
    382 		  break;
    383 		case 'u':
    384 		case 'w':
    385 		  __needed = _Weekday;
    386 		  __allowed_mods = _Mod_O;
    387 		  break;
    388 		case 'U':
    389 		case 'V':
    390 		case 'W':
    391 		  __needed = _Date;
    392 		  __allowed_mods = _Mod_O;
    393 		  break;
    394 		case 'x':
    395 		  __needed = _Date;
    396 		  __allowed_mods = _Mod_E;
    397 		  break;
    398 		case 'X':
    399 		  __needed = _TimeOfDay;
    400 		  __allowed_mods = _Mod_E;
    401 		  break;
    402 		case 'y':
    403 		  __needed = _Year;
    404 		  __allowed_mods = _Mod_E_O;
    405 		  break;
    406 		case 'Y':
    407 		  __needed = _Year;
    408 		  __allowed_mods = _Mod_E;
    409 		  break;
    410 		case 'z':
    411 		  __needed = _TimeZone;
    412 		  __allowed_mods = _Mod_E_O;
    413 		  break;
    414 		case 'Z':
    415 		  __needed = _TimeZone;
    416 		  break;
    417 		case 'n':
    418 		case 't':
    419 		case '%':
    420 		  break;
    421 		case 'O':
    422 		case 'E':
    423 		  if (__mod) [[unlikely]]
    424 		    {
    425 		      __allowed_mods = _Mod_none;
    426 		      break;
    427 		    }
    428 		  __mod = __c;
    429 		  continue;
    430 		default:
    431 		  __throw_format_error("chrono format error: invalid "
    432 				       " specifier in chrono-specs");
    433 		}
    434 
    435 	      if ((__mod == 'E' && !(__allowed_mods & _Mod_E))
    436 		    || (__mod == 'O' && !(__allowed_mods & _Mod_O)))
    437 		__throw_format_error("chrono format error: invalid "
    438 				     " modifier in chrono-specs");
    439 	      __mod = _CharT();
    440 
    441 	      if ((__parts & __needed) != __needed)
    442 		__throw_format_error("chrono format error: format argument "
    443 				     "does not contain the information "
    444 				     "required by the chrono-specs");
    445 
    446 	      // Scan for next '%', ignoring literal-chars before it.
    447 	      size_t __pos = __string_view(__first, __last - __first).find('%');
    448 	      if (__pos == 0)
    449 		++__first;
    450 	      else
    451 		{
    452 		  if (__pos == __string_view::npos)
    453 		    {
    454 		      __first = __last;
    455 		      __conv = false;
    456 		    }
    457 		  else
    458 		    __first += __pos + 1;
    459 		}
    460 	    }
    461 
    462 	  // Check for a '%' conversion-spec without a type.
    463 	  if (__conv || __mod != _CharT())
    464 	    __throw_format_error("chrono format error: unescaped '%' in "
    465 				 "chrono-specs");
    466 
    467 	  _M_spec = __spec;
    468 	  _M_spec._M_chrono_specs
    469 		 = __string_view(__chrono_specs, __first - __chrono_specs);
    470 
    471 	  return __first;
    472 	}
    473 
    474       // TODO this function template is instantiated for every different _Tp.
    475       // Consider creating a polymorphic interface for calendar types so
    476       // that we instantiate fewer different specializations. Similar to
    477       // _Sink_iter for std::format. Replace each _S_year, _S_day etc. with
    478       // member functions of that type.
    479       template<typename _Tp, typename _FormatContext>
    480 	typename _FormatContext::iterator
    481 	_M_format(const _Tp& __t, _FormatContext& __fc,
    482 		  bool __is_neg = false) const
    483 	{
    484 	  auto __first = _M_spec._M_chrono_specs.begin();
    485 	  const auto __last = _M_spec._M_chrono_specs.end();
    486 	  if (__first == __last)
    487 	    return _M_format_to_ostream(__t, __fc, __is_neg);
    488 
    489 	  _Sink_iter<_CharT> __out;
    490 	  __format::_Str_sink<_CharT> __sink;
    491 	  bool __write_direct = false;
    492 	  if constexpr (is_same_v<typename _FormatContext::iterator,
    493 				  _Sink_iter<_CharT>>)
    494 	    {
    495 	      if (_M_spec._M_width_kind == __format::_WP_none)
    496 		{
    497 		  __out = __fc.out();
    498 		  __write_direct = true;
    499 		}
    500 	      else
    501 		__out = __sink.out();
    502 	    }
    503 	  else
    504 	    __out = __sink.out();
    505 
    506 	  // formatter<duration> passes the correct value of __is_neg
    507 	  // for durations but for hh_mm_ss we decide it here.
    508 	  if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>)
    509 	    __is_neg = __t.is_negative();
    510 
    511 	  auto __print_sign = [&__is_neg, &__out] {
    512 	    if constexpr (chrono::__is_duration_v<_Tp>
    513 			    || __is_specialization_of<_Tp, chrono::hh_mm_ss>)
    514 	      if (__is_neg)
    515 		{
    516 		  *__out++ = _S_plus_minus[1];
    517 		  __is_neg = false;
    518 		}
    519 	    return std::move(__out);
    520 	  };
    521 
    522 	  // Characters to output for "%n", "%t" and "%%" specifiers.
    523 	  constexpr const _CharT* __literals = _GLIBCXX_WIDEN("\n\t%");
    524 
    525 	  ++__first; // Skip leading '%' at start of chrono-specs.
    526 
    527 	  _CharT __mod{};
    528 	  do
    529 	    {
    530 	      _CharT __c = *__first++;
    531 	      switch (__c)
    532 		{
    533 		case 'a':
    534 		case 'A':
    535 		  __out = _M_a_A(__t, std::move(__out), __fc, __c == 'A');
    536 		  break;
    537 		case 'b':
    538 		case 'h':
    539 		case 'B':
    540 		  __out = _M_b_B(__t, std::move(__out), __fc, __c == 'B');
    541 		  break;
    542 		case 'c':
    543 		  __out = _M_c(__t, std::move(__out), __fc, __mod == 'E');
    544 		  break;
    545 		case 'C':
    546 		case 'y':
    547 		case 'Y':
    548 		  __out = _M_C_y_Y(__t, std::move(__out), __fc, __c, __mod);
    549 		  break;
    550 		case 'd':
    551 		case 'e':
    552 		  __out = _M_d_e(__t, std::move(__out), __fc, __c, __mod == 'O');
    553 		  break;
    554 		case 'D':
    555 		  __out = _M_D(__t, std::move(__out), __fc);
    556 		  break;
    557 		case 'F':
    558 		  __out = _M_F(__t, std::move(__out), __fc);
    559 		  break;
    560 		case 'g':
    561 		case 'G':
    562 		  __out = _M_g_G(__t, std::move(__out), __fc, __c == 'G');
    563 		  break;
    564 		case 'H':
    565 		case 'I':
    566 		  __out = _M_H_I(__t, __print_sign(), __fc, __c, __mod == 'O');
    567 		  break;
    568 		case 'j':
    569 		  __out = _M_j(__t, __print_sign(), __fc);
    570 		  break;
    571 		case 'm':
    572 		  __out = _M_m(__t, std::move(__out), __fc, __mod == 'O');
    573 		  break;
    574 		case 'M':
    575 		  __out = _M_M(__t, __print_sign(), __fc, __mod == 'O');
    576 		  break;
    577 		case 'p':
    578 		  __out = _M_p(__t, std::move(__out), __fc);
    579 		  break;
    580 		case 'q':
    581 		  __out = _M_q(__t, std::move(__out), __fc);
    582 		  break;
    583 		case 'Q':
    584 		  // %Q The duration's numeric value.
    585 		  if constexpr (chrono::__is_duration_v<_Tp>)
    586 		    __out = std::format_to(__print_sign(), _S_empty_spec,
    587 					   __t.count());
    588 		  else
    589 		    __throw_format_error("chrono format error: argument is "
    590 					 "not a duration");
    591 		  break;
    592 		case 'r':
    593 		  __out = _M_r(__t, __print_sign(), __fc);
    594 		  break;
    595 		case 'R':
    596 		case 'T':
    597 		  __out = _M_R_T(__t, __print_sign(), __fc, __c == 'T');
    598 		  break;
    599 		case 'S':
    600 		  __out = _M_S(__t, __print_sign(), __fc, __mod == 'O');
    601 		  break;
    602 		case 'u':
    603 		case 'w':
    604 		  __out = _M_u_w(__t, std::move(__out), __fc, __c, __mod == 'O');
    605 		  break;
    606 		case 'U':
    607 		case 'V':
    608 		case 'W':
    609 		  __out = _M_U_V_W(__t, std::move(__out), __fc, __c,
    610 				   __mod == 'O');
    611 		  break;
    612 		case 'x':
    613 		  __out = _M_x(__t, std::move(__out), __fc, __mod == 'E');
    614 		  break;
    615 		case 'X':
    616 		  __out = _M_X(__t, __print_sign(), __fc, __mod == 'E');
    617 		  break;
    618 		case 'z':
    619 		  __out = _M_z(__t, std::move(__out), __fc, (bool)__mod);
    620 		  break;
    621 		case 'Z':
    622 		  __out = _M_Z(__t, std::move(__out), __fc);
    623 		  break;
    624 		case 'n':
    625 		  *__out++ = __literals[0];
    626 		  break;
    627 		case 't':
    628 		  *__out++ = __literals[1];
    629 		  break;
    630 		case '%':
    631 		  *__out++ = __literals[2];
    632 		  break;
    633 		case 'O':
    634 		case 'E':
    635 		  __mod = __c;
    636 		  continue;
    637 		case '}':
    638 		  __first = __last;
    639 		  break;
    640 		}
    641 	      __mod = _CharT();
    642 	      // Scan for next '%' and write out everything before it.
    643 	      __string_view __str(__first, __last - __first);
    644 	      size_t __pos = __str.find('%');
    645 	      if (__pos == 0)
    646 		++__first;
    647 	      else
    648 		{
    649 		  if (__pos == __str.npos)
    650 		    __first = __last;
    651 		  else
    652 		    {
    653 		      __str.remove_suffix(__str.length() - __pos);
    654 		      __first += __pos + 1;
    655 		    }
    656 		  __out = __format::__write(std::move(__out), __str);
    657 		}
    658 	    }
    659 	  while (__first != __last);
    660 
    661 	  if constexpr (is_same_v<typename _FormatContext::iterator,
    662 				  _Sink_iter<_CharT>>)
    663 	    if (__write_direct)
    664 	      return __out;
    665 
    666 	  auto __str = std::move(__sink).get();
    667 	  return __format::__write_padded_as_spec(__str, __str.size(),
    668 						  __fc, _M_spec);
    669 	}
    670 
    671       _ChronoSpec<_CharT> _M_spec;
    672 
    673     private:
    674       // Return the formatting locale.
    675       template<typename _FormatContext>
    676 	std::locale
    677 	_M_locale(_FormatContext& __fc) const
    678 	{
    679 	  if (!_M_spec._M_localized)
    680 	    return std::locale::classic();
    681 	  else
    682 	    return __fc.locale();
    683 	}
    684 
    685       // Format for empty chrono-specs, e.g. "{}" (C++20 [time.format] p6).
    686       // TODO: consider moving body of every operator<< into this function
    687       // and use std::format("{}", t) to implement those operators. That
    688       // would avoid std::format("{}", t) calling operator<< which calls
    689       // std::format again.
    690       template<typename _Tp, typename _FormatContext>
    691 	typename _FormatContext::iterator
    692 	_M_format_to_ostream(const _Tp& __t, _FormatContext& __fc,
    693 			     bool __is_neg) const
    694 	{
    695 	  using ::std::chrono::__detail::__utc_leap_second;
    696 	  using ::std::chrono::__detail::__local_time_fmt;
    697 
    698 	  if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
    699 	    return _M_format_to_ostream(__t._M_time, __fc, false);
    700 	  else
    701 	    {
    702 	      basic_ostringstream<_CharT> __os;
    703 	      __os.imbue(_M_locale(__fc));
    704 
    705 	      if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
    706 		__os << __t._M_date << ' ' << __t._M_time;
    707 	      else if constexpr (chrono::__is_time_point_v<_Tp>)
    708 		{
    709 		  // Need to be careful here because not all specializations
    710 		  // of chrono::sys_time can be written to an ostream.
    711 		  // For the specializations of time_point that can be
    712 		  // formatted with an empty chrono-specs, either it's a
    713 		  // sys_time with period greater or equal to days:
    714 		  if constexpr (is_convertible_v<_Tp, chrono::sys_days>)
    715 		    __os << _S_date(__t);
    716 		  else // Or it's formatted as "{:L%F %T}":
    717 		    {
    718 		      auto __days = chrono::floor<chrono::days>(__t);
    719 		      __os << chrono::year_month_day(__days) << ' '
    720 			 << chrono::hh_mm_ss(__t - __days);
    721 		    }
    722 		}
    723 	      else
    724 		{
    725 		  if constexpr (chrono::__is_duration_v<_Tp>)
    726 		    if (__is_neg) [[unlikely]]
    727 		      __os << _S_plus_minus[1];
    728 		  __os << __t;
    729 		}
    730 
    731 	      auto __str = std::move(__os).str();
    732 	      return __format::__write_padded_as_spec(__str, __str.size(),
    733 						      __fc, _M_spec);
    734 	    }
    735 	}
    736 
    737       static constexpr const _CharT* _S_chars
    738 	= _GLIBCXX_WIDEN("0123456789+-:/ {}");
    739       static constexpr const _CharT* _S_plus_minus = _S_chars + 10;
    740       static constexpr _CharT _S_colon = _S_chars[12];
    741       static constexpr _CharT _S_slash = _S_chars[13];
    742       static constexpr _CharT _S_space = _S_chars[14];
    743       static constexpr const _CharT* _S_empty_spec = _S_chars + 15;
    744 
    745       template<typename _Tp, typename _FormatContext>
    746 	typename _FormatContext::iterator
    747 	_M_a_A(const _Tp& __t, typename _FormatContext::iterator __out,
    748 	       _FormatContext& __ctx, bool __full) const
    749 	{
    750 	  // %a Locale's abbreviated weekday name.
    751 	  // %A Locale's full weekday name.
    752 	  chrono::weekday __wd = _S_weekday(__t);
    753 	  if (!__wd.ok())
    754 	    __throw_format_error("format error: invalid weekday");
    755 
    756 	  locale __loc = _M_locale(__ctx);
    757 	  const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
    758 	  const _CharT* __days[7];
    759 	  if (__full)
    760 	    __tp._M_days(__days);
    761 	  else
    762 	    __tp._M_days_abbreviated(__days);
    763 	  __string_view __str(__days[__wd.c_encoding()]);
    764 	  return __format::__write(std::move(__out), __str);
    765 	}
    766 
    767       template<typename _Tp, typename _FormatContext>
    768 	typename _FormatContext::iterator
    769 	_M_b_B(const _Tp& __t, typename _FormatContext::iterator __out,
    770 	       _FormatContext& __ctx, bool __full) const
    771 	{
    772 	  // %b Locale's abbreviated month name.
    773 	  // %B Locale's full month name.
    774 	  chrono::month __m = _S_month(__t);
    775 	  if (!__m.ok())
    776 	    __throw_format_error("format error: invalid month");
    777 	  locale __loc = _M_locale(__ctx);
    778 	  const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
    779 	  const _CharT* __months[12];
    780 	  if (__full)
    781 	    __tp._M_months(__months);
    782 	  else
    783 	    __tp._M_months_abbreviated(__months);
    784 	  __string_view __str(__months[(unsigned)__m - 1]);
    785 	  return __format::__write(std::move(__out), __str);
    786 	}
    787 
    788       template<typename _Tp, typename _FormatContext>
    789 	typename _FormatContext::iterator
    790 	_M_c(const _Tp& __tt, typename _FormatContext::iterator __out,
    791 	     _FormatContext& __ctx, bool __mod = false) const
    792 	{
    793 	  // %c  Locale's date and time representation.
    794 	  // %Ec Locale's alternate date and time representation.
    795 
    796 	  basic_string<_CharT> __fmt;
    797 	  auto __t = _S_floor_seconds(__tt);
    798 	  locale __loc = _M_locale(__ctx);
    799 	  const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
    800 	  const _CharT* __formats[2];
    801 	  __tp._M_date_time_formats(__formats);
    802 	  if (*__formats[__mod]) [[likely]]
    803 	    {
    804 	      __fmt = _GLIBCXX_WIDEN("{:L}");
    805 	      __fmt.insert(3u, __formats[__mod]);
    806 	    }
    807 	  else
    808 	    __fmt = _GLIBCXX_WIDEN("{:L%a %b %e %T %Y}");
    809 	  return std::vformat_to(std::move(__out), __loc, __fmt,
    810 				 std::make_format_args<_FormatContext>(__t));
    811 	}
    812 
    813       template<typename _Tp, typename _FormatContext>
    814 	typename _FormatContext::iterator
    815 	_M_C_y_Y(const _Tp& __t, typename _FormatContext::iterator __out,
    816 	       _FormatContext& __ctx, _CharT __conv, _CharT __mod = 0) const
    817 	{
    818 	  // %C  Year divided by 100 using floored division.
    819 	  // %EC Locale's alternative preresentation of the century (era name).
    820 	  // %y  Last two decimal digits of the year.
    821 	  // %Oy Locale's alternative representation.
    822 	  // %Ey Locale's alternative representation of offset from %EC.
    823 	  // %Y  Year as a decimal number.
    824 	  // %EY Locale's alternative full year representation.
    825 
    826 	  chrono::year __y = _S_year(__t);
    827 
    828 	  if (__mod) [[unlikely]]
    829 	    {
    830 	      struct tm __tm{};
    831 	      __tm.tm_year = (int)__y - 1900;
    832 	      return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
    833 				   __conv, __mod);
    834 	    }
    835 
    836 	  basic_string<_CharT> __s;
    837 	  int __yi = (int)__y;
    838 	  const bool __is_neg = __yi < 0;
    839 	  __yi = __builtin_abs(__yi);
    840 
    841 	  if (__conv == 'Y' || __conv == 'C')
    842 	    {
    843 	      int __ci = __yi / 100;
    844 	      if (__is_neg) [[unlikely]]
    845 		{
    846 		  __s.assign(1, _S_plus_minus[1]);
    847 		  // For floored division -123//100 is -2 and -100//100 is -1
    848 		  if (__conv == 'C' && (__ci * 100) != __yi)
    849 		    ++__ci;
    850 		}
    851 	      if (__ci >= 100) [[unlikely]]
    852 		{
    853 		  __s += std::format(_S_empty_spec, __ci / 100);
    854 		  __ci %= 100;
    855 		}
    856 	      __s += _S_two_digits(__ci);
    857 	    }
    858 
    859 	  if (__conv == 'Y' || __conv == 'y')
    860 	    __s += _S_two_digits(__yi % 100);
    861 
    862 	  return __format::__write(std::move(__out), __string_view(__s));
    863 	}
    864 
    865       template<typename _Tp, typename _FormatContext>
    866 	typename _FormatContext::iterator
    867 	_M_D(const _Tp& __t, typename _FormatContext::iterator __out,
    868 	     _FormatContext&) const
    869 	{
    870 	  auto __ymd = _S_date(__t);
    871 	  basic_string<_CharT> __s;
    872 #if ! _GLIBCXX_USE_CXX11_ABI
    873 	  __s.reserve(8);
    874 #endif
    875 	  __s = _S_two_digits((unsigned)__ymd.month());
    876 	  __s += _S_slash;
    877 	  __s += _S_two_digits((unsigned)__ymd.day());
    878 	  __s += _S_slash;
    879 	  __s += _S_two_digits(__builtin_abs((int)__ymd.year()) % 100);
    880 	  return __format::__write(std::move(__out), __string_view(__s));
    881 	}
    882 
    883       template<typename _Tp, typename _FormatContext>
    884 	typename _FormatContext::iterator
    885 	_M_d_e(const _Tp& __t, typename _FormatContext::iterator __out,
    886 	       _FormatContext& __ctx, _CharT __conv, bool __mod = false) const
    887 	{
    888 	  // %d  The day of month as a decimal number.
    889 	  // %Od Locale's alternative representation.
    890 	  // %e  Day of month as decimal number, padded with space.
    891 	  // %Oe Locale's alternative digits.
    892 
    893 	  chrono::day __d = _S_day(__t);
    894 	  unsigned __i = (unsigned)__d;
    895 
    896 	  if (__mod) [[unlikely]]
    897 	    {
    898 	      struct tm __tm{};
    899 	      __tm.tm_mday = __i;
    900 	      return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
    901 				   (char)__conv, 'O');
    902 	    }
    903 
    904 	  auto __sv = _S_two_digits(__i);
    905 	  _CharT __buf[2];
    906 	  if (__conv == _CharT('e') && __i < 10)
    907 	    {
    908 	      __buf[0] = _S_space;
    909 	      __buf[1] = __sv[1];
    910 	      __sv = {__buf, 2};
    911 	    }
    912 	  return __format::__write(std::move(__out), __sv);
    913 	}
    914 
    915       template<typename _Tp, typename _FormatContext>
    916 	typename _FormatContext::iterator
    917 	_M_F(const _Tp& __t, typename _FormatContext::iterator __out,
    918 	     _FormatContext&) const
    919 	{
    920 	  auto __ymd = _S_date(__t);
    921 	  auto __s = std::format(_GLIBCXX_WIDEN("{:04d}-  -  "),
    922 				 (int)__ymd.year());
    923 	  auto __sv = _S_two_digits((unsigned)__ymd.month());
    924 	  __s[__s.size() - 5] = __sv[0];
    925 	  __s[__s.size() - 4] = __sv[1];
    926 	  __sv = _S_two_digits((unsigned)__ymd.day());
    927 	  __s[__s.size() - 2] = __sv[0];
    928 	  __s[__s.size() - 1] = __sv[1];
    929 	  __sv = __s;
    930 	  return __format::__write(std::move(__out), __sv);
    931 	}
    932 
    933       template<typename _Tp, typename _FormatContext>
    934 	typename _FormatContext::iterator
    935 	_M_g_G(const _Tp& __t, typename _FormatContext::iterator __out,
    936 	     _FormatContext& __ctx, bool __full) const
    937 	{
    938 	  // %g last two decimal digits of the ISO week-based year.
    939 	  // %G ISO week-based year.
    940 	  using namespace chrono;
    941 	  auto __d = _S_days(__t);
    942 	  // Move to nearest Thursday:
    943 	  __d -= (weekday(__d) - Monday) - days(3);
    944 	  // ISO week-based year is the year that contains that Thursday:
    945 	  year __y = year_month_day(__d).year();
    946 	  return _M_C_y_Y(__y, std::move(__out), __ctx, "yY"[__full]);
    947 	}
    948 
    949       template<typename _Tp, typename _FormatContext>
    950 	typename _FormatContext::iterator
    951 	_M_H_I(const _Tp& __t, typename _FormatContext::iterator __out,
    952 	       _FormatContext& __ctx, _CharT __conv, bool __mod = false) const
    953 	{
    954 	  // %H  The hour (24-hour clock) as a decimal number.
    955 	  // %OH Locale's alternative representation.
    956 	  // %I  The hour (12-hour clock) as a decimal number.
    957 	  // %OI Locale's alternative representation.
    958 
    959 	  const auto __hms = _S_hms(__t);
    960 	  int __i = __hms.hours().count();
    961 
    962 	  if (__mod) [[unlikely]]
    963 	    {
    964 	      struct tm __tm{};
    965 	      __tm.tm_hour = __i;
    966 	      return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
    967 				   (char)__conv, 'O');
    968 	    }
    969 
    970 	  if (__conv == _CharT('I'))
    971 	    {
    972 	      if (__i == 0)
    973 		__i = 12;
    974 	      else if (__i > 12)
    975 		__i -= 12;
    976 	    }
    977 	  return __format::__write(std::move(__out), _S_two_digits(__i));
    978 	}
    979 
    980       template<typename _Tp, typename _FormatContext>
    981 	typename _FormatContext::iterator
    982 	_M_j(const _Tp& __t, typename _FormatContext::iterator __out,
    983 	     _FormatContext&) const
    984 	{
    985 	  if constexpr (chrono::__is_duration_v<_Tp>)
    986 	    {
    987 	      // Decimal number of days, without padding.
    988 	      unsigned __d = chrono::duration_cast<chrono::days>(__t).count();
    989 	      return std::format_to(std::move(__out), _S_empty_spec, __d);
    990 	    }
    991 	  else
    992 	    {
    993 	      // Day of the year as a decimal number, padding with zero.
    994 	      using namespace chrono;
    995 	      auto __day = _S_days(__t);
    996 	      auto __ymd = _S_date(__t);
    997 	      days __d;
    998 	      // See "Calculating Ordinal Dates" at
    999 	      // https://github.com/HowardHinnant/date/wiki/Examples-and-Recipes
   1000 	      if constexpr (is_same_v<typename decltype(__day)::clock, local_t>)
   1001 		__d = __day - local_days(__ymd.year()/January/0);
   1002 	      else
   1003 		__d = __day - sys_days(__ymd.year()/January/0);
   1004 	      return std::format_to(std::move(__out), _GLIBCXX_WIDEN("{:03d}"),
   1005 				    __d.count());
   1006 	    }
   1007 	}
   1008 
   1009       template<typename _Tp, typename _FormatContext>
   1010 	typename _FormatContext::iterator
   1011 	_M_m(const _Tp& __t, typename _FormatContext::iterator __out,
   1012 	     _FormatContext& __ctx, bool __mod) const
   1013 	{
   1014 	  // %m  month as a decimal number.
   1015 	  // %Om Locale's alternative representation.
   1016 
   1017 	  auto __m = _S_month(__t);
   1018 	  auto __i = (unsigned)__m;
   1019 
   1020 	  if (__mod) [[unlikely]] // %Om
   1021 	    {
   1022 	      struct tm __tm{};
   1023 	      __tm.tm_mon = __i - 1;
   1024 	      return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
   1025 				   'm', 'O');
   1026 	    }
   1027 
   1028 	  return __format::__write(std::move(__out), _S_two_digits(__i));
   1029 	}
   1030 
   1031       template<typename _Tp, typename _FormatContext>
   1032 	typename _FormatContext::iterator
   1033 	_M_M(const _Tp& __t, typename _FormatContext::iterator __out,
   1034 	     _FormatContext& __ctx, bool __mod) const
   1035 	{
   1036 	  // %M  The minute as a decimal number.
   1037 	  // %OM Locale's alternative representation.
   1038 
   1039 	  auto __m = _S_hms(__t).minutes();
   1040 	  auto __i = __m.count();
   1041 
   1042 	  if (__mod) [[unlikely]] // %OM
   1043 	    {
   1044 	      struct tm __tm{};
   1045 	      __tm.tm_min = __i;
   1046 	      return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
   1047 				   'M', 'O');
   1048 	    }
   1049 
   1050 	  return __format::__write(std::move(__out), _S_two_digits(__i));
   1051 	}
   1052 
   1053       template<typename _Tp, typename _FormatContext>
   1054 	typename _FormatContext::iterator
   1055 	_M_p(const _Tp& __t, typename _FormatContext::iterator __out,
   1056 	     _FormatContext& __ctx) const
   1057 	{
   1058 	  // %p The locale's equivalent of the AM/PM designations.
   1059 	  auto __hms = _S_hms(__t);
   1060 	  locale __loc = _M_locale(__ctx);
   1061 	  const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
   1062 	  const _CharT* __ampm[2];
   1063 	  __tp._M_am_pm(__ampm);
   1064 	  return std::format_to(std::move(__out), _S_empty_spec,
   1065 				__ampm[__hms.hours().count() >= 12]);
   1066 	}
   1067 
   1068       template<typename _Tp, typename _FormatContext>
   1069 	typename _FormatContext::iterator
   1070 	_M_q(const _Tp&, typename _FormatContext::iterator __out,
   1071 	     _FormatContext&) const
   1072 	{
   1073 	  // %q The duration's unit suffix
   1074 	  if constexpr (!chrono::__is_duration_v<_Tp>)
   1075 	    __throw_format_error("format error: argument is not a duration");
   1076 	  else
   1077 	    {
   1078 	      namespace __d = chrono::__detail;
   1079 	      using period = typename _Tp::period;
   1080 	      return __d::__fmt_units_suffix<period, _CharT>(std::move(__out));
   1081 	    }
   1082 	}
   1083 
   1084       // %Q handled in _M_format
   1085 
   1086       template<typename _Tp, typename _FormatContext>
   1087 	typename _FormatContext::iterator
   1088 	_M_r(const _Tp& __tt, typename _FormatContext::iterator __out,
   1089 	     _FormatContext& __ctx) const
   1090 	{
   1091 	  // %r locale's 12-hour clock time.
   1092 	  auto __t = _S_floor_seconds(__tt);
   1093 	  locale __loc = _M_locale(__ctx);
   1094 	  const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
   1095 	  const _CharT* __ampm_fmt;
   1096 	  __tp._M_am_pm_format(&__ampm_fmt);
   1097 	  basic_string<_CharT> __fmt(_S_empty_spec);
   1098 	  __fmt.insert(1u, 1u, _S_colon);
   1099 	  __fmt.insert(2u, __ampm_fmt);
   1100 	  return std::vformat_to(std::move(__out), __fmt,
   1101 				 std::make_format_args<_FormatContext>(__t));
   1102 	}
   1103 
   1104       template<typename _Tp, typename _FormatContext>
   1105 	typename _FormatContext::iterator
   1106 	_M_R_T(const _Tp& __t, typename _FormatContext::iterator __out,
   1107 	       _FormatContext& __ctx, bool __secs) const
   1108 	{
   1109 	  // %R Equivalent to %H:%M
   1110 	  // %T Equivalent to %H:%M:%S
   1111 	  auto __hms = _S_hms(__t);
   1112 
   1113 	  auto __s = std::format(_GLIBCXX_WIDEN("{:02d}:00"),
   1114 				 __hms.hours().count());
   1115 	  auto __sv = _S_two_digits(__hms.minutes().count());
   1116 	  __s[__s.size() - 2] = __sv[0];
   1117 	  __s[__s.size() - 1] = __sv[1];
   1118 	  __sv = __s;
   1119 	  __out = __format::__write(std::move(__out), __sv);
   1120 	  if (__secs)
   1121 	    {
   1122 	      *__out++ = _S_colon;
   1123 	      __out = _M_S(__hms, std::move(__out), __ctx);
   1124 	    }
   1125 	  return __out;
   1126 	}
   1127 
   1128       template<typename _Tp, typename _FormatContext>
   1129 	typename _FormatContext::iterator
   1130 	_M_S(const _Tp& __t, typename _FormatContext::iterator __out,
   1131 	     _FormatContext& __ctx, bool __mod = false) const
   1132 	{
   1133 	  // %S  Seconds as a decimal number.
   1134 	  // %OS The locale's alternative representation.
   1135 	  auto __hms = _S_hms(__t);
   1136 
   1137 	  if (__mod) [[unlikely]] // %OS
   1138 	    {
   1139 	      struct tm __tm{};
   1140 	      __tm.tm_sec = (int)__hms.seconds().count();
   1141 	      return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
   1142 				   'S', 'O');
   1143 	    }
   1144 
   1145 	  if constexpr (__hms.fractional_width == 0)
   1146 	    __out = __format::__write(std::move(__out),
   1147 				      _S_two_digits(__hms.seconds().count()));
   1148 	  else
   1149 	    {
   1150 	      locale __loc = _M_locale(__ctx);
   1151 	      auto __s = __hms.seconds();
   1152 	      auto __ss = __hms.subseconds();
   1153 	      using rep = typename decltype(__ss)::rep;
   1154 	      if constexpr (is_floating_point_v<rep>)
   1155 		{
   1156 		  chrono::duration<rep> __fs = __s + __ss;
   1157 		  __out = std::format_to(std::move(__out), __loc,
   1158 					 _GLIBCXX_WIDEN("{:#0{}.{}Lf}"),
   1159 					 __fs.count(),
   1160 					 3 + __hms.fractional_width,
   1161 					 __hms.fractional_width);
   1162 		}
   1163 	      else
   1164 		{
   1165 		  const auto& __np
   1166 		    = use_facet<numpunct<_CharT>>(__loc);
   1167 		  __out = __format::__write(std::move(__out),
   1168 					    _S_two_digits(__s.count()));
   1169 		  *__out++ = __np.decimal_point();
   1170 		  if constexpr (is_integral_v<rep>)
   1171 		    __out = std::format_to(std::move(__out),
   1172 					   _GLIBCXX_WIDEN("{:0{}}"),
   1173 					   __ss.count(),
   1174 					   __hms.fractional_width);
   1175 		  else
   1176 		    {
   1177 		      auto __str = std::format(_S_empty_spec, __ss.count());
   1178 		      __out = std::format_to(_GLIBCXX_WIDEN("{:0>{}s}"),
   1179 					     __str,
   1180 					     __hms.fractional_width);
   1181 		    }
   1182 		}
   1183 	    }
   1184 	  return __out;
   1185 	}
   1186 
   1187       // %t handled in _M_format
   1188 
   1189       template<typename _Tp, typename _FormatContext>
   1190 	typename _FormatContext::iterator
   1191 	_M_u_w(const _Tp& __t, typename _FormatContext::iterator __out,
   1192 	       _FormatContext& __ctx, _CharT __conv, bool __mod = false) const
   1193 	{
   1194 	  // %u  ISO weekday as a decimal number (1-7), where Monday is 1.
   1195 	  // %Ou Locale's alternative numeric rep.
   1196 	  // %w  Weekday as a decimal number (0-6), where Sunday is 0.
   1197 	  // %Ow Locale's alternative numeric rep.
   1198 
   1199 	  chrono::weekday __wd = _S_weekday(__t);
   1200 
   1201 	  if (__mod) [[unlikely]]
   1202 	    {
   1203 	      struct tm __tm{};
   1204 	      __tm.tm_wday = __wd.c_encoding();
   1205 	      return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
   1206 				   (char)__conv, 'O');
   1207 	    }
   1208 
   1209 	  unsigned __wdi = __conv == 'u' ? __wd.iso_encoding()
   1210 					 : __wd.c_encoding();
   1211 	  const _CharT __d = _S_digit(__wdi);
   1212 	  return __format::__write(std::move(__out), __string_view(&__d, 1));
   1213 	}
   1214 
   1215       template<typename _Tp, typename _FormatContext>
   1216 	typename _FormatContext::iterator
   1217 	_M_U_V_W(const _Tp& __t, typename _FormatContext::iterator __out,
   1218 		 _FormatContext& __ctx, _CharT __conv, bool __mod = false) const
   1219 	{
   1220 	  // %U  Week number of the year as a decimal number, from first Sunday.
   1221 	  // %OU Locale's alternative numeric rep.
   1222 	  // %V  ISO week-based week number as a decimal number.
   1223 	  // %OV Locale's alternative numeric rep.
   1224 	  // %W  Week number of the year as a decimal number, from first Monday.
   1225 	  // %OW Locale's alternative numeric rep.
   1226 	  using namespace chrono;
   1227 	  auto __d = _S_days(__t);
   1228 	  using _TDays = decltype(__d); // Either sys_days or local_days.
   1229 
   1230 	  if (__mod) [[unlikely]]
   1231 	    {
   1232 	      const year_month_day __ymd(__d);
   1233 	      const year __y = __ymd.year();
   1234 	      struct tm __tm{};
   1235 	      __tm.tm_year = (int)__y - 1900;
   1236 	      __tm.tm_yday = (__d - _TDays(__y/January/1)).count();
   1237 	      __tm.tm_wday = weekday(__d).c_encoding();
   1238 	      return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
   1239 				   (char)__conv, 'O');
   1240 	    }
   1241 
   1242 	  _TDays __first; // First day of week 1.
   1243 	  if (__conv == 'V') // W01 begins on Monday before first Thursday.
   1244 	    {
   1245 	      // Move to nearest Thursday:
   1246 	      __d -= (weekday(__d) - Monday) - days(3);
   1247 	      // ISO week of __t is number of weeks since January 1 of the
   1248 	      // same year as that nearest Thursday.
   1249 	      __first = _TDays(year_month_day(__d).year()/January/1);
   1250 	    }
   1251 	  else
   1252 	    {
   1253 	      year __y;
   1254 	      if constexpr (requires { __t.year(); })
   1255 		__y = __t.year();
   1256 	      else
   1257 		__y = year_month_day(__d).year();
   1258 	      const weekday __weekstart = __conv == 'U' ? Sunday : Monday;
   1259 	      __first = _TDays(__y/January/__weekstart[1]);
   1260 	    }
   1261 	  auto __weeks = chrono::floor<weeks>(__d - __first);
   1262 	  __string_view __sv = _S_two_digits(__weeks.count() + 1);
   1263 	  return __format::__write(std::move(__out), __sv);
   1264 	}
   1265 
   1266       template<typename _Tp, typename _FormatContext>
   1267 	typename _FormatContext::iterator
   1268 	_M_x(const _Tp& __t, typename _FormatContext::iterator __out,
   1269 	     _FormatContext& __ctx, bool __mod = false) const
   1270 	{
   1271 	  // %x  Locale's date rep
   1272 	  // %Ex Locale's alternative date representation.
   1273 	  locale __loc = _M_locale(__ctx);
   1274 	  const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
   1275 	  const _CharT* __date_reps[2];
   1276 	  __tp._M_date_formats(__date_reps);
   1277 	  const _CharT* __rep = __date_reps[__mod];
   1278 	  if (!*__rep)
   1279 	    return _M_D(__t, std::move(__out), __ctx);
   1280 
   1281 	  basic_string<_CharT> __fmt(_S_empty_spec);
   1282 	  __fmt.insert(1u, 1u, _S_colon);
   1283 	  __fmt.insert(2u, __rep);
   1284 	  return std::vformat_to(std::move(__out), __fmt,
   1285 				 std::make_format_args<_FormatContext>(__t));
   1286 	}
   1287 
   1288       template<typename _Tp, typename _FormatContext>
   1289 	typename _FormatContext::iterator
   1290 	_M_X(const _Tp& __tt, typename _FormatContext::iterator __out,
   1291 	     _FormatContext& __ctx, bool __mod = false) const
   1292 	{
   1293 	  // %X  Locale's time rep
   1294 	  // %EX Locale's alternative time representation.
   1295 	  auto __t = _S_floor_seconds(__tt);
   1296 	  locale __loc = _M_locale(__ctx);
   1297 	  const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
   1298 	  const _CharT* __time_reps[2];
   1299 	  __tp._M_time_formats(__time_reps);
   1300 	  const _CharT* __rep = __time_reps[__mod];
   1301 	  if (!*__rep)
   1302 	    return _M_R_T(__t, std::move(__out), __ctx, true);
   1303 
   1304 	  basic_string<_CharT> __fmt(_S_empty_spec);
   1305 	  __fmt.insert(1u, 1u, _S_colon);
   1306 	  __fmt.insert(2u, __rep);
   1307 	  return std::vformat_to(std::move(__out), __fmt,
   1308 				 std::make_format_args<_FormatContext>(__t));
   1309 	}
   1310 
   1311       template<typename _Tp, typename _FormatContext>
   1312 	typename _FormatContext::iterator
   1313 	_M_z(const _Tp& __t, typename _FormatContext::iterator __out,
   1314 	     _FormatContext&, bool __mod = false) const
   1315 	{
   1316 	  using ::std::chrono::__detail::__utc_leap_second;
   1317 	  using ::std::chrono::__detail::__local_time_fmt;
   1318 
   1319 	  auto __utc = __mod ? __string_view(_GLIBCXX_WIDEN("+00:00"), 6)
   1320 			     : __string_view(_GLIBCXX_WIDEN("+0000"), 5);
   1321 
   1322 	  if constexpr (chrono::__is_time_point_v<_Tp>)
   1323 	    {
   1324 	      if constexpr (is_same_v<typename _Tp::clock,
   1325 				      chrono::system_clock>)
   1326 		return __format::__write(std::move(__out), __utc);
   1327 	    }
   1328 	  else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
   1329 	    {
   1330 	      if (__t._M_offset_sec)
   1331 		{
   1332 		  auto __sv = __utc;
   1333 		  basic_string<_CharT> __s;
   1334 		  if (*__t._M_offset_sec != 0s)
   1335 		    {
   1336 		      chrono:: hh_mm_ss __hms(*__t._M_offset_sec);
   1337 		      __s = _S_plus_minus[__hms.is_negative()];
   1338 		      __s += _S_two_digits(__hms.hours().count());
   1339 		      if (__mod)
   1340 			__s += _S_colon;
   1341 		      __s += _S_two_digits(__hms.minutes().count());
   1342 		      __sv = __s;
   1343 		    }
   1344 		  return __format::__write(std::move(__out), __sv);
   1345 		}
   1346 	    }
   1347 	  else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
   1348 	    return __format::__write(std::move(__out), __utc);
   1349 
   1350 	  __no_timezone_available();
   1351 	}
   1352 
   1353       template<typename _Tp, typename _FormatContext>
   1354 	typename _FormatContext::iterator
   1355 	_M_Z(const _Tp& __t, typename _FormatContext::iterator __out,
   1356 	     _FormatContext& __ctx) const
   1357 	{
   1358 	  using ::std::chrono::__detail::__utc_leap_second;
   1359 	  using ::std::chrono::__detail::__local_time_fmt;
   1360 
   1361 	  __string_view __utc(_GLIBCXX_WIDEN("UTC"), 3);
   1362 	  if constexpr (chrono::__is_time_point_v<_Tp>)
   1363 	    {
   1364 	      if constexpr (is_same_v<typename _Tp::clock,
   1365 				      chrono::system_clock>)
   1366 		return __format::__write(std::move(__out), __utc);
   1367 	    }
   1368 	  else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
   1369 	    {
   1370 	      if (__t._M_abbrev)
   1371 		{
   1372 		  string_view __sv = *__t._M_abbrev;
   1373 		  if constexpr (is_same_v<_CharT, char>)
   1374 		    return __format::__write(std::move(__out), __sv);
   1375 		  else
   1376 		    {
   1377 		      // TODO use resize_and_overwrite
   1378 		      basic_string<_CharT> __ws(__sv.size(), _CharT());
   1379 		      auto& __ct = use_facet<ctype<_CharT>>(_M_locale(__ctx));
   1380 		      __ct.widen(__sv.begin(), __sv.end(), __ws.data());
   1381 		      __string_view __wsv = __ws;
   1382 		      return __format::__write(std::move(__out), __wsv);
   1383 		    }
   1384 		}
   1385 	    }
   1386 	  else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
   1387 	    return __format::__write(std::move(__out), __utc);
   1388 
   1389 	  __no_timezone_available();
   1390 	}
   1391 
   1392       // %% handled in _M_format
   1393 
   1394       // A single digit character in the range '0'..'9'.
   1395       static _CharT
   1396       _S_digit(int __n) noexcept
   1397       {
   1398 	// Extra 9s avoid past-the-end read on bad input.
   1399 	return _GLIBCXX_WIDEN("0123456789999999")[__n & 0xf];
   1400       }
   1401 
   1402       // A string view of two digit characters, "00".."99".
   1403       static basic_string_view<_CharT>
   1404       _S_two_digits(int __n) noexcept
   1405       {
   1406 	return {
   1407 	  _GLIBCXX_WIDEN("0001020304050607080910111213141516171819"
   1408 			 "2021222324252627282930313233343536373839"
   1409 			 "4041424344454647484950515253545556575859"
   1410 			 "6061626364656667686970717273747576777879"
   1411 			 "8081828384858687888990919293949596979899"
   1412 			 "9999999999999999999999999999999999999999"
   1413 			 "9999999999999999") + 2 * (__n & 0x7f),
   1414 	  2
   1415 	};
   1416       }
   1417 
   1418       // Accessors for the components of chrono types:
   1419 
   1420       // Returns a hh_mm_ss.
   1421       template<typename _Tp>
   1422 	static decltype(auto)
   1423 	_S_hms(const _Tp& __t)
   1424 	{
   1425 	  using ::std::chrono::__detail::__utc_leap_second;
   1426 	  using ::std::chrono::__detail::__local_time_fmt;
   1427 
   1428 	  if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>)
   1429 	    return __t;
   1430 	  else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
   1431 	    return __t._M_time;
   1432 	  else if constexpr (chrono::__is_duration_v<_Tp>)
   1433 	    return chrono::hh_mm_ss<_Tp>(__t);
   1434 	  else if constexpr (chrono::__is_time_point_v<_Tp>)
   1435 	    return chrono::hh_mm_ss(__t - chrono::floor<chrono::days>(__t));
   1436 	  else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
   1437 	    return _S_hms(__t._M_time);
   1438 	  else
   1439 	    {
   1440 	      __invalid_chrono_spec();
   1441 	      return chrono::hh_mm_ss<chrono::seconds>();
   1442 	    }
   1443 	}
   1444 
   1445       // Returns a sys_days or local_days.
   1446       template<typename _Tp>
   1447 	static auto
   1448 	_S_days(const _Tp& __t)
   1449 	{
   1450 	  using namespace chrono;
   1451 	  using ::std::chrono::__detail::__utc_leap_second;
   1452 	  using ::std::chrono::__detail::__local_time_fmt;
   1453 
   1454 	  if constexpr (__is_time_point_v<_Tp>)
   1455 	    return chrono::floor<days>(__t);
   1456 	  else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
   1457 	    return __t._M_date;
   1458 	  else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
   1459 	    return chrono::floor<days>(__t._M_time);
   1460 	  else if constexpr (is_same_v<_Tp, year_month_day>
   1461 			       || is_same_v<_Tp, year_month_day_last>
   1462 			       || is_same_v<_Tp, year_month_weekday>
   1463 			       || is_same_v<_Tp, year_month_weekday_last>)
   1464 	    return sys_days(__t);
   1465 	  else
   1466 	    {
   1467 	      if constexpr (__is_duration_v<_Tp>)
   1468 		__not_valid_for_duration();
   1469 	      else
   1470 		__invalid_chrono_spec();
   1471 	      return chrono::sys_days();
   1472 	    }
   1473 	}
   1474 
   1475       // Returns a year_month_day.
   1476       template<typename _Tp>
   1477 	static chrono::year_month_day
   1478 	_S_date(const _Tp& __t)
   1479 	{
   1480 	  if constexpr (is_same_v<_Tp, chrono::year_month_day>)
   1481 	    return __t;
   1482 	  else
   1483 	    return chrono::year_month_day(_S_days(__t));
   1484 	}
   1485 
   1486       template<typename _Tp>
   1487 	static chrono::day
   1488 	_S_day(const _Tp& __t)
   1489 	{
   1490 	  using namespace chrono;
   1491 
   1492 	  if constexpr (is_same_v<_Tp, day>)
   1493 	    return __t;
   1494 	  else if constexpr (requires { __t.day(); })
   1495 	    return __t.day();
   1496 	  else
   1497 	    return _S_date(__t).day();
   1498 	}
   1499 
   1500       template<typename _Tp>
   1501 	static chrono::month
   1502 	_S_month(const _Tp& __t)
   1503 	{
   1504 	  using namespace chrono;
   1505 
   1506 	  if constexpr (is_same_v<_Tp, month>)
   1507 	    return __t;
   1508 	  else if constexpr (requires { __t.month(); })
   1509 	    return __t.month();
   1510 	  else
   1511 	    return _S_date(__t).month();
   1512 	}
   1513 
   1514       template<typename _Tp>
   1515 	static chrono::year
   1516 	_S_year(const _Tp& __t)
   1517 	{
   1518 	  using namespace chrono;
   1519 
   1520 	  if constexpr (is_same_v<_Tp, year>)
   1521 	    return __t;
   1522 	  else if constexpr (requires { __t.year(); })
   1523 	    return __t.year();
   1524 	  else
   1525 	    return _S_date(__t).year();
   1526 	}
   1527 
   1528       template<typename _Tp>
   1529 	static chrono::weekday
   1530 	_S_weekday(const _Tp& __t)
   1531 	{
   1532 	  using namespace ::std::chrono;
   1533 	  using ::std::chrono::__detail::__local_time_fmt;
   1534 
   1535 	  if constexpr (is_same_v<_Tp, weekday>)
   1536 	    return __t;
   1537 	  else if constexpr (requires { __t.weekday(); })
   1538 	    return __t.weekday();
   1539 	  else if constexpr (is_same_v<_Tp, month_weekday>)
   1540 	    return __t.weekday_indexed().weekday();
   1541 	  else if constexpr (is_same_v<_Tp, month_weekday_last>)
   1542 	    return __t.weekday_last().weekday();
   1543 	  else
   1544 	    return weekday(_S_days(__t));
   1545 	}
   1546 
   1547       // Remove subsecond precision from a time_point.
   1548       template<typename _Tp>
   1549 	static auto
   1550 	_S_floor_seconds(const _Tp& __t)
   1551 	{
   1552 	  using chrono::__detail::__local_time_fmt;
   1553 	  if constexpr (chrono::__is_time_point_v<_Tp>
   1554 			  || chrono::__is_duration_v<_Tp>)
   1555 	    {
   1556 	      if constexpr (_Tp::period::den != 1)
   1557 		return chrono::floor<chrono::seconds>(__t);
   1558 	      else
   1559 		return __t;
   1560 	    }
   1561 	  else if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>)
   1562 	    {
   1563 	      if constexpr (_Tp::fractional_width != 0)
   1564 		return chrono::floor<chrono::seconds>(__t.to_duration());
   1565 	      else
   1566 		return __t;
   1567 	    }
   1568 	  else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
   1569 	    return _S_floor_seconds(__t._M_time);
   1570 	  else
   1571 	    return __t;
   1572 	}
   1573 
   1574       // Use the formatting locale's std::time_put facet to produce
   1575       // a locale-specific representation.
   1576       template<typename _Iter>
   1577 	_Iter
   1578 	_M_locale_fmt(_Iter __out, const locale& __loc, const struct tm& __tm,
   1579 		      char __fmt, char __mod) const
   1580 	{
   1581 	  basic_ostringstream<_CharT> __os;
   1582 	  const auto& __tp = use_facet<time_put<_CharT>>(__loc);
   1583 	  __tp.put(__os, __os, _S_space, &__tm, __fmt, __mod);
   1584 	  if (__os)
   1585 	    __out = __format::__write(std::move(__out), __os.view());
   1586 	  return __out;
   1587 	}
   1588     };
   1589 
   1590 } // namespace __format
   1591 /// @endcond
   1592 
   1593   template<typename _Rep, typename _Period, typename _CharT>
   1594     struct formatter<chrono::duration<_Rep, _Period>, _CharT>
   1595     {
   1596       constexpr typename basic_format_parse_context<_CharT>::iterator
   1597       parse(basic_format_parse_context<_CharT>& __pc)
   1598       {
   1599 	using namespace __format;
   1600 	auto __it = _M_f._M_parse(__pc, _Duration|_TimeOfDay);
   1601 	if constexpr (!is_floating_point_v<_Rep>)
   1602 	  if (_M_f._M_spec._M_prec_kind != __format::_WP_none)
   1603 	    __throw_format_error("format error: invalid precision for duration");
   1604 	return __it;
   1605       }
   1606 
   1607       template<typename _Out>
   1608 	typename basic_format_context<_Out, _CharT>::iterator
   1609 	format(const chrono::duration<_Rep, _Period>& __d,
   1610 	       basic_format_context<_Out, _CharT>& __fc) const
   1611 	{
   1612 	  if constexpr (numeric_limits<_Rep>::is_signed)
   1613 	    if (__d < __d.zero()) [[unlikely]]
   1614 	      {
   1615 		if constexpr (is_integral_v<_Rep>)
   1616 		  {
   1617 		    // -d is undefined for the most negative integer.
   1618 		    // Convert duration to corresponding unsigned rep.
   1619 		    using _URep = make_unsigned_t<_Rep>;
   1620 		    auto __ucnt = -static_cast<_URep>(__d.count());
   1621 		    auto __ud = chrono::duration<_URep, _Period>(__ucnt);
   1622 		    return _M_f._M_format(__ud, __fc, true);
   1623 		  }
   1624 		else
   1625 		  return _M_f._M_format(-__d, __fc, true);
   1626 	      }
   1627 	  return _M_f._M_format(__d, __fc, false);
   1628 	}
   1629 
   1630     private:
   1631       __format::__formatter_chrono<_CharT> _M_f;
   1632     };
   1633 
   1634   template<typename _CharT>
   1635     struct formatter<chrono::day, _CharT>
   1636     {
   1637       template<typename _ParseContext>
   1638 	constexpr typename _ParseContext::iterator
   1639 	parse(_ParseContext& __pc)
   1640 	{ return _M_f._M_parse(__pc, __format::_Day); }
   1641 
   1642       template<typename _FormatContext>
   1643 	typename _FormatContext::iterator
   1644 	format(const chrono::day& __t, _FormatContext& __fc) const
   1645 	{ return _M_f._M_format(__t, __fc); }
   1646 
   1647     private:
   1648       __format::__formatter_chrono<_CharT> _M_f;
   1649     };
   1650 
   1651   template<typename _CharT>
   1652     struct formatter<chrono::month, _CharT>
   1653     {
   1654       template<typename _ParseContext>
   1655 	constexpr typename _ParseContext::iterator
   1656 	parse(_ParseContext& __pc)
   1657 	{ return _M_f._M_parse(__pc, __format::_Month); }
   1658 
   1659       template<typename _FormatContext>
   1660 	typename _FormatContext::iterator
   1661 	format(const chrono::month& __t, _FormatContext& __fc) const
   1662 	{ return _M_f._M_format(__t, __fc); }
   1663 
   1664     private:
   1665       __format::__formatter_chrono<_CharT> _M_f;
   1666     };
   1667 
   1668   template<typename _CharT>
   1669     struct formatter<chrono::year, _CharT>
   1670     {
   1671       template<typename _ParseContext>
   1672 	constexpr typename _ParseContext::iterator
   1673 	parse(_ParseContext& __pc)
   1674 	{ return _M_f._M_parse(__pc, __format::_Year); }
   1675 
   1676       template<typename _FormatContext>
   1677 	typename _FormatContext::iterator
   1678 	format(const chrono::year& __t, _FormatContext& __fc) const
   1679 	{ return _M_f._M_format(__t, __fc); }
   1680 
   1681     private:
   1682       __format::__formatter_chrono<_CharT> _M_f;
   1683     };
   1684 
   1685   template<typename _CharT>
   1686     struct formatter<chrono::weekday, _CharT>
   1687     {
   1688       template<typename _ParseContext>
   1689 	constexpr typename _ParseContext::iterator
   1690 	parse(_ParseContext& __pc)
   1691 	{ return _M_f._M_parse(__pc, __format::_Weekday); }
   1692 
   1693       template<typename _FormatContext>
   1694 	typename _FormatContext::iterator
   1695 	format(const chrono::weekday& __t, _FormatContext& __fc) const
   1696 	{ return _M_f._M_format(__t, __fc); }
   1697 
   1698     private:
   1699       __format::__formatter_chrono<_CharT> _M_f;
   1700     };
   1701 
   1702   template<typename _CharT>
   1703     struct formatter<chrono::weekday_indexed, _CharT>
   1704     {
   1705       template<typename _ParseContext>
   1706 	constexpr typename _ParseContext::iterator
   1707 	parse(_ParseContext& __pc)
   1708 	{ return _M_f._M_parse(__pc, __format::_Weekday); }
   1709 
   1710       template<typename _FormatContext>
   1711 	typename _FormatContext::iterator
   1712 	format(const chrono::weekday_indexed& __t, _FormatContext& __fc) const
   1713 	{ return _M_f._M_format(__t, __fc); }
   1714 
   1715     private:
   1716       __format::__formatter_chrono<_CharT> _M_f;
   1717     };
   1718 
   1719   template<typename _CharT>
   1720     struct formatter<chrono::weekday_last, _CharT>
   1721     {
   1722       template<typename _ParseContext>
   1723 	constexpr typename _ParseContext::iterator
   1724 	parse(_ParseContext& __pc)
   1725 	{ return _M_f._M_parse(__pc, __format::_Weekday); }
   1726 
   1727       template<typename _FormatContext>
   1728 	typename _FormatContext::iterator
   1729 	format(const chrono::weekday_last& __t, _FormatContext& __fc) const
   1730 	{ return _M_f._M_format(__t, __fc); }
   1731 
   1732     private:
   1733       __format::__formatter_chrono<_CharT> _M_f;
   1734     };
   1735 
   1736   template<typename _CharT>
   1737     struct formatter<chrono::month_day, _CharT>
   1738     {
   1739       template<typename _ParseContext>
   1740 	constexpr typename _ParseContext::iterator
   1741 	parse(_ParseContext& __pc)
   1742 	{ return _M_f._M_parse(__pc, __format::_Month|__format::_Day); }
   1743 
   1744       template<typename _FormatContext>
   1745 	typename _FormatContext::iterator
   1746 	format(const chrono::month_day& __t, _FormatContext& __fc) const
   1747 	{ return _M_f._M_format(__t, __fc); }
   1748 
   1749     private:
   1750       __format::__formatter_chrono<_CharT> _M_f;
   1751     };
   1752 
   1753   template<typename _CharT>
   1754     struct formatter<chrono::month_day_last, _CharT>
   1755     {
   1756       template<typename _ParseContext>
   1757 	constexpr typename _ParseContext::iterator
   1758 	parse(_ParseContext& __pc)
   1759 	{ return _M_f._M_parse(__pc, __format::_Month|__format::_Day); }
   1760 
   1761       template<typename _FormatContext>
   1762 	typename _FormatContext::iterator
   1763 	format(const chrono::month_day_last& __t, _FormatContext& __fc) const
   1764 	{ return _M_f._M_format(__t, __fc); }
   1765 
   1766     private:
   1767       __format::__formatter_chrono<_CharT> _M_f;
   1768     };
   1769 
   1770   template<typename _CharT>
   1771     struct formatter<chrono::month_weekday, _CharT>
   1772     {
   1773       template<typename _ParseContext>
   1774 	constexpr typename _ParseContext::iterator
   1775 	parse(_ParseContext& __pc)
   1776 	{ return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday); }
   1777 
   1778       template<typename _FormatContext>
   1779 	typename _FormatContext::iterator
   1780 	format(const chrono::month_weekday& __t, _FormatContext& __fc) const
   1781 	{ return _M_f._M_format(__t, __fc); }
   1782 
   1783     private:
   1784       __format::__formatter_chrono<_CharT> _M_f;
   1785     };
   1786 
   1787   template<typename _CharT>
   1788     struct formatter<chrono::month_weekday_last, _CharT>
   1789     {
   1790       template<typename _ParseContext>
   1791 	constexpr typename _ParseContext::iterator
   1792 	parse(_ParseContext& __pc)
   1793 	{ return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday); }
   1794 
   1795       template<typename _FormatContext>
   1796 	typename _FormatContext::iterator
   1797 	format(const chrono::month_weekday_last& __t,
   1798 	       _FormatContext& __fc) const
   1799 	{ return _M_f._M_format(__t, __fc); }
   1800 
   1801     private:
   1802       __format::__formatter_chrono<_CharT> _M_f;
   1803     };
   1804 
   1805   template<typename _CharT>
   1806     struct formatter<chrono::year_month, _CharT>
   1807     {
   1808       template<typename _ParseContext>
   1809 	constexpr typename _ParseContext::iterator
   1810 	parse(_ParseContext& __pc)
   1811 	{ return _M_f._M_parse(__pc, __format::_Year|__format::_Month); }
   1812 
   1813       template<typename _FormatContext>
   1814 	typename _FormatContext::iterator
   1815 	format(const chrono::year_month& __t, _FormatContext& __fc) const
   1816 	{ return _M_f._M_format(__t, __fc); }
   1817 
   1818     private:
   1819       __format::__formatter_chrono<_CharT> _M_f;
   1820     };
   1821 
   1822   template<typename _CharT>
   1823     struct formatter<chrono::year_month_day, _CharT>
   1824     {
   1825       template<typename _ParseContext>
   1826 	constexpr typename _ParseContext::iterator
   1827 	parse(_ParseContext& __pc)
   1828 	{ return _M_f._M_parse(__pc, __format::_Date); }
   1829 
   1830       template<typename _FormatContext>
   1831 	typename _FormatContext::iterator
   1832 	format(const chrono::year_month_day& __t, _FormatContext& __fc) const
   1833 	{ return _M_f._M_format(__t, __fc); }
   1834 
   1835     private:
   1836       __format::__formatter_chrono<_CharT> _M_f;
   1837     };
   1838 
   1839   template<typename _CharT>
   1840     struct formatter<chrono::year_month_day_last, _CharT>
   1841     {
   1842       template<typename _ParseContext>
   1843 	constexpr typename _ParseContext::iterator
   1844 	parse(_ParseContext& __pc)
   1845 	{ return _M_f._M_parse(__pc, __format::_Date); }
   1846 
   1847       template<typename _FormatContext>
   1848 	typename _FormatContext::iterator
   1849 	format(const chrono::year_month_day_last& __t,
   1850 	       _FormatContext& __fc) const
   1851 	{ return _M_f._M_format(__t, __fc); }
   1852 
   1853     private:
   1854       __format::__formatter_chrono<_CharT> _M_f;
   1855     };
   1856 
   1857   template<typename _CharT>
   1858     struct formatter<chrono::year_month_weekday, _CharT>
   1859     {
   1860       template<typename _ParseContext>
   1861 	constexpr typename _ParseContext::iterator
   1862 	parse(_ParseContext& __pc)
   1863 	{ return _M_f._M_parse(__pc, __format::_Date); }
   1864 
   1865       template<typename _FormatContext>
   1866 	typename _FormatContext::iterator
   1867 	format(const chrono::year_month_weekday& __t,
   1868 	       _FormatContext& __fc) const
   1869 	{ return _M_f._M_format(__t, __fc); }
   1870 
   1871     private:
   1872       __format::__formatter_chrono<_CharT> _M_f;
   1873     };
   1874 
   1875   template<typename _CharT>
   1876     struct formatter<chrono::year_month_weekday_last, _CharT>
   1877     {
   1878       template<typename _ParseContext>
   1879 	constexpr typename _ParseContext::iterator
   1880 	parse(_ParseContext& __pc)
   1881 	{ return _M_f._M_parse(__pc, __format::_Date); }
   1882 
   1883       template<typename _FormatContext>
   1884 	typename _FormatContext::iterator
   1885 	format(const chrono::year_month_weekday_last& __t,
   1886 	       _FormatContext& __fc) const
   1887 	{ return _M_f._M_format(__t, __fc); }
   1888 
   1889     private:
   1890       __format::__formatter_chrono<_CharT> _M_f;
   1891     };
   1892 
   1893   template<typename _Rep, typename _Period, typename _CharT>
   1894     struct formatter<chrono::hh_mm_ss<chrono::duration<_Rep, _Period>>, _CharT>
   1895     {
   1896       template<typename _ParseContext>
   1897 	constexpr typename _ParseContext::iterator
   1898 	parse(_ParseContext& __pc)
   1899 	{ return _M_f._M_parse(__pc, __format::_TimeOfDay); }
   1900 
   1901       template<typename _FormatContext>
   1902 	typename _FormatContext::iterator
   1903 	format(const chrono::hh_mm_ss<chrono::duration<_Rep, _Period>>& __t,
   1904 	       _FormatContext& __fc) const
   1905 	{ return _M_f._M_format(__t, __fc); }
   1906 
   1907     private:
   1908       __format::__formatter_chrono<_CharT> _M_f;
   1909     };
   1910 
   1911 #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
   1912   template<typename _CharT>
   1913     struct formatter<chrono::sys_info, _CharT>
   1914     {
   1915       template<typename _ParseContext>
   1916 	constexpr typename _ParseContext::iterator
   1917 	parse(_ParseContext& __pc)
   1918 	{ return _M_f._M_parse(__pc, __format::_ChronoParts{}); }
   1919 
   1920       template<typename _FormatContext>
   1921 	typename _FormatContext::iterator
   1922 	format(const chrono::sys_info& __i, _FormatContext& __fc) const
   1923 	{ return _M_f._M_format(__i, __fc); }
   1924 
   1925     private:
   1926       __format::__formatter_chrono<_CharT> _M_f;
   1927     };
   1928 
   1929   template<typename _CharT>
   1930     struct formatter<chrono::local_info, _CharT>
   1931     {
   1932       template<typename _ParseContext>
   1933 	constexpr typename _ParseContext::iterator
   1934 	parse(_ParseContext& __pc)
   1935 	{ return _M_f._M_parse(__pc, __format::_ChronoParts{}); }
   1936 
   1937       template<typename _FormatContext>
   1938 	typename _FormatContext::iterator
   1939 	format(const chrono::local_info& __i, _FormatContext& __fc) const
   1940 	{ return _M_f._M_format(__i, __fc); }
   1941 
   1942     private:
   1943       __format::__formatter_chrono<_CharT> _M_f;
   1944     };
   1945 #endif
   1946 
   1947   template<typename _Duration, typename _CharT>
   1948     struct formatter<chrono::sys_time<_Duration>, _CharT>
   1949     {
   1950       template<typename _ParseContext>
   1951 	constexpr typename _ParseContext::iterator
   1952 	parse(_ParseContext& __pc)
   1953 	{
   1954 	  auto __next = _M_f._M_parse(__pc, __format::_ZonedDateTime);
   1955 	  if constexpr (!__stream_insertable)
   1956 	    if (_M_f._M_spec._M_chrono_specs.empty())
   1957 	      __format::__invalid_chrono_spec(); // chrono-specs can't be empty
   1958 	  return __next;
   1959 	}
   1960 
   1961       template<typename _FormatContext>
   1962 	typename _FormatContext::iterator
   1963 	format(const chrono::sys_time<_Duration>& __t,
   1964 	       _FormatContext& __fc) const
   1965 	{ return _M_f._M_format(__t, __fc); }
   1966 
   1967     private:
   1968       static constexpr bool __stream_insertable
   1969 	= requires (basic_ostream<_CharT>& __os,
   1970 		    chrono::sys_time<_Duration> __t) { __os << __t; };
   1971 
   1972       __format::__formatter_chrono<_CharT> _M_f;
   1973     };
   1974 
   1975   template<typename _Duration, typename _CharT>
   1976     struct formatter<chrono::utc_time<_Duration>, _CharT>
   1977     : __format::__formatter_chrono<_CharT>
   1978     {
   1979       template<typename _ParseContext>
   1980 	constexpr typename _ParseContext::iterator
   1981 	parse(_ParseContext& __pc)
   1982 	{ return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
   1983 
   1984       template<typename _FormatContext>
   1985 	typename _FormatContext::iterator
   1986 	format(const chrono::utc_time<_Duration>& __t,
   1987 	       _FormatContext& __fc) const
   1988 	{
   1989 	  // Adjust by removing leap seconds to get equivalent sys_time.
   1990 	  // We can't just use clock_cast because we want to know if the time
   1991 	  // falls within a leap second insertion, and format seconds as "60".
   1992 	  using chrono::__detail::__utc_leap_second;
   1993 	  using chrono::seconds;
   1994 	  using chrono::sys_time;
   1995 	  using _CDur = common_type_t<_Duration, seconds>;
   1996 	  const auto __li = chrono::get_leap_second_info(__t);
   1997 	  sys_time<_CDur> __s{__t.time_since_epoch() - __li.elapsed};
   1998 	  if (!__li.is_leap_second) [[likely]]
   1999 	    return _M_f._M_format(__s, __fc);
   2000 	  else
   2001 	    return _M_f._M_format(__utc_leap_second(__s), __fc);
   2002 	}
   2003 
   2004     private:
   2005       friend formatter<chrono::__detail::__utc_leap_second<_Duration>, _CharT>;
   2006 
   2007       __format::__formatter_chrono<_CharT> _M_f;
   2008     };
   2009 
   2010   template<typename _Duration, typename _CharT>
   2011     struct formatter<chrono::tai_time<_Duration>, _CharT>
   2012     : __format::__formatter_chrono<_CharT>
   2013     {
   2014       template<typename _ParseContext>
   2015 	constexpr typename _ParseContext::iterator
   2016 	parse(_ParseContext& __pc)
   2017 	{ return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
   2018 
   2019       template<typename _FormatContext>
   2020 	typename _FormatContext::iterator
   2021 	format(const chrono::tai_time<_Duration>& __t,
   2022 	       _FormatContext& __fc) const
   2023 	{
   2024 	  // Convert to __local_time_fmt with abbrev "TAI" and offset 0s.
   2025 
   2026 	  // Offset is 1970y/January/1 - 1958y/January/1
   2027 	  constexpr chrono::days __tai_offset = chrono::days(4383);
   2028 	  using _CDur = common_type_t<_Duration, chrono::days>;
   2029 	  chrono::local_time<_CDur> __lt(__t.time_since_epoch() - __tai_offset);
   2030 	  const string __abbrev("TAI", 3);
   2031 	  const chrono::seconds __off = 0s;
   2032 	  const auto __lf = chrono::local_time_format(__lt, &__abbrev, &__off);
   2033 	  return _M_f._M_format(__lf, __fc);
   2034 	}
   2035 
   2036     private:
   2037       __format::__formatter_chrono<_CharT> _M_f;
   2038     };
   2039 
   2040   template<typename _Duration, typename _CharT>
   2041     struct formatter<chrono::gps_time<_Duration>, _CharT>
   2042     : __format::__formatter_chrono<_CharT>
   2043     {
   2044       template<typename _ParseContext>
   2045 	constexpr typename _ParseContext::iterator
   2046 	parse(_ParseContext& __pc)
   2047 	{ return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
   2048 
   2049       template<typename _FormatContext>
   2050 	typename _FormatContext::iterator
   2051 	format(const chrono::gps_time<_Duration>& __t,
   2052 	       _FormatContext& __fc) const
   2053 	{
   2054 	  // Convert to __local_time_fmt with abbrev "GPS" and offset 0s.
   2055 
   2056 	  // Offset is 1980y/January/Sunday[1] - 1970y/January/1
   2057 	  constexpr chrono::days __gps_offset = chrono::days(3657);
   2058 	  using _CDur = common_type_t<_Duration, chrono::days>;
   2059 	  chrono::local_time<_CDur> __lt(__t.time_since_epoch() + __gps_offset);
   2060 	  const string __abbrev("GPS", 3);
   2061 	  const chrono::seconds __off = 0s;
   2062 	  const auto __lf = chrono::local_time_format(__lt, &__abbrev, &__off);
   2063 	  return _M_f._M_format(__lf, __fc);
   2064 	}
   2065 
   2066     private:
   2067       __format::__formatter_chrono<_CharT> _M_f;
   2068     };
   2069 
   2070   template<typename _Duration, typename _CharT>
   2071     struct formatter<chrono::file_time<_Duration>, _CharT>
   2072     {
   2073       template<typename _ParseContext>
   2074 	constexpr typename _ParseContext::iterator
   2075 	parse(_ParseContext& __pc)
   2076 	{ return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
   2077 
   2078       template<typename _FormatContext>
   2079 	typename _FormatContext::iterator
   2080 	format(const chrono::file_time<_Duration>& __t,
   2081 	       _FormatContext& __ctx) const
   2082 	{
   2083 	  using namespace chrono;
   2084 	  return _M_f._M_format(chrono::clock_cast<system_clock>(__t), __ctx);
   2085 	}
   2086 
   2087     private:
   2088       __format::__formatter_chrono<_CharT> _M_f;
   2089     };
   2090 
   2091   template<typename _Duration, typename _CharT>
   2092     struct formatter<chrono::local_time<_Duration>, _CharT>
   2093     {
   2094       template<typename _ParseContext>
   2095 	constexpr typename _ParseContext::iterator
   2096 	parse(_ParseContext& __pc)
   2097 	{ return _M_f._M_parse(__pc, __format::_DateTime); }
   2098 
   2099       template<typename _FormatContext>
   2100 	typename _FormatContext::iterator
   2101 	format(const chrono::local_time<_Duration>& __t,
   2102 	       _FormatContext& __ctx) const
   2103 	{ return _M_f._M_format(__t, __ctx); }
   2104 
   2105     private:
   2106       __format::__formatter_chrono<_CharT> _M_f;
   2107     };
   2108 
   2109   template<typename _Duration, typename _CharT>
   2110     struct formatter<chrono::__detail::__local_time_fmt<_Duration>, _CharT>
   2111     {
   2112       template<typename _ParseContext>
   2113 	constexpr typename _ParseContext::iterator
   2114 	parse(_ParseContext& __pc)
   2115 	{ return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
   2116 
   2117       template<typename _FormatContext>
   2118 	typename _FormatContext::iterator
   2119 	format(const chrono::__detail::__local_time_fmt<_Duration>& __t,
   2120 	       _FormatContext& __ctx) const
   2121 	{ return _M_f._M_format(__t, __ctx); }
   2122 
   2123     private:
   2124       __format::__formatter_chrono<_CharT> _M_f;
   2125     };
   2126 
   2127 #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
   2128   template<typename _Duration, typename _TimeZonePtr, typename _CharT>
   2129     struct formatter<chrono::zoned_time<_Duration, _TimeZonePtr>, _CharT>
   2130     : formatter<chrono::__detail::__local_time_fmt<_Duration>, _CharT>
   2131     {
   2132       template<typename _FormatContext>
   2133 	typename _FormatContext::iterator
   2134 	format(const chrono::zoned_time<_Duration, _TimeZonePtr>& __tp,
   2135 	       _FormatContext& __ctx) const
   2136 	{
   2137 	  using chrono::__detail::__local_time_fmt;
   2138 	  using _Base = formatter<__local_time_fmt<_Duration>, _CharT>;
   2139 	  const chrono::sys_info __info = __tp.get_info();
   2140 	  const auto __lf = chrono::local_time_format(__tp.get_local_time(),
   2141 						      &__info.abbrev,
   2142 						      &__info.offset);
   2143 	  return _Base::format(__lf, __ctx);
   2144 	}
   2145     };
   2146 #endif
   2147 
   2148   // Partial specialization needed for %c formatting of __utc_leap_second.
   2149   template<typename _Duration, typename _CharT>
   2150     struct formatter<chrono::__detail::__utc_leap_second<_Duration>, _CharT>
   2151     : formatter<chrono::utc_time<_Duration>, _CharT>
   2152     {
   2153       template<typename _FormatContext>
   2154 	typename _FormatContext::iterator
   2155 	format(const chrono::__detail::__utc_leap_second<_Duration>& __t,
   2156 	       _FormatContext& __fc) const
   2157 	{ return this->_M_f._M_format(__t, __fc); }
   2158     };
   2159 
   2160 namespace chrono
   2161 {
   2162 /// @addtogroup chrono
   2163 /// @{
   2164 
   2165 /// @cond undocumented
   2166 namespace __detail
   2167 {
   2168   template<typename _Duration = seconds>
   2169     struct _Parser
   2170     {
   2171       static_assert(is_same_v<common_type_t<_Duration, seconds>, _Duration>);
   2172 
   2173       explicit
   2174       _Parser(__format::_ChronoParts __need) : _M_need(__need) { }
   2175 
   2176       _Parser(_Parser&&) = delete;
   2177       void operator=(_Parser&&) = delete;
   2178 
   2179       _Duration _M_time{}; // since midnight
   2180       sys_days _M_sys_days{};
   2181       year_month_day _M_ymd{};
   2182       weekday _M_wd{};
   2183       __format::_ChronoParts _M_need;
   2184       unsigned _M_is_leap_second : 1 {};
   2185       unsigned _M_reserved : 15 {};
   2186 
   2187       template<typename _CharT, typename _Traits, typename _Alloc>
   2188 	basic_istream<_CharT, _Traits>&
   2189 	operator()(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
   2190 		   basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
   2191 		   minutes* __offset = nullptr);
   2192 
   2193     private:
   2194       // Read an unsigned integer from the stream and return it.
   2195       // Extract no more than __n digits. Set failbit if an integer isn't read.
   2196       template<typename _CharT, typename _Traits>
   2197 	static int_least32_t
   2198 	_S_read_unsigned(basic_istream<_CharT, _Traits>& __is,
   2199 			 ios_base::iostate& __err, int __n)
   2200 	{
   2201 	  int_least32_t __val = _S_try_read_digit(__is, __err);
   2202 	  if (__val == -1) [[unlikely]]
   2203 	    __err |= ios_base::failbit;
   2204 	  else
   2205 	    {
   2206 	      int __n1 = (std::min)(__n, 9);
   2207 	      // Cannot overflow __val unless we read more than 9 digits
   2208 	      for (int __i = 1; __i < __n1; ++__i)
   2209 		if (auto __dig = _S_try_read_digit(__is, __err); __dig != -1)
   2210 		  {
   2211 		    __val *= 10;
   2212 		    __val += __dig;
   2213 		  }
   2214 
   2215 	      while (__n1++ < __n) [[unlikely]]
   2216 		if (auto __dig = _S_try_read_digit(__is, __err); __dig != -1)
   2217 		  {
   2218 		    if (__builtin_mul_overflow(__val, 10, &__val)
   2219 			  || __builtin_add_overflow(__val, __dig, &__val))
   2220 		      {
   2221 			__err |= ios_base::failbit;
   2222 			return -1;
   2223 		      }
   2224 		  }
   2225 	    }
   2226 	  return __val;
   2227 	}
   2228 
   2229       // Read an unsigned integer from the stream and return it.
   2230       // Extract no more than __n digits. Set failbit if an integer isn't read.
   2231       template<typename _CharT, typename _Traits>
   2232 	static int_least32_t
   2233 	_S_read_signed(basic_istream<_CharT, _Traits>& __is,
   2234 			 ios_base::iostate& __err, int __n)
   2235 	{
   2236 	  auto __sign = __is.peek();
   2237 	  if (__sign == '-' || __sign == '+')
   2238 	    (void) __is.get();
   2239 	  int_least32_t __val = _S_read_unsigned(__is, __err, __n);
   2240 	  if (__err & ios_base::failbit)
   2241 	    {
   2242 	      if (__sign == '-') [[unlikely]]
   2243 		__val *= -1;
   2244 	    }
   2245 	  return __val;
   2246 	}
   2247 
   2248       // Read a digit from the stream and return it, or return -1.
   2249       // If no digit is read eofbit will be set (but not failbit).
   2250       template<typename _CharT, typename _Traits>
   2251 	static int_least32_t
   2252 	_S_try_read_digit(basic_istream<_CharT, _Traits>& __is,
   2253 			  ios_base::iostate& __err)
   2254 	{
   2255 	  int_least32_t __val = -1;
   2256 	  auto __i = __is.peek();
   2257 	  if (!_Traits::eq_int_type(__i, _Traits::eof())) [[likely]]
   2258 	    {
   2259 	      _CharT __c = _Traits::to_char_type(__i);
   2260 	      if (_CharT('0') <= __c && __c <= _CharT('9')) [[likely]]
   2261 		{
   2262 		  (void) __is.get();
   2263 		  __val = __c - _CharT('0');
   2264 		}
   2265 	    }
   2266 	  else
   2267 	    __err |= ios_base::eofbit;
   2268 	  return __val;
   2269 	}
   2270 
   2271       // Read the specified character and return true.
   2272       // If the character is not found, set failbit and return false.
   2273       template<typename _CharT, typename _Traits>
   2274 	static bool
   2275 	_S_read_chr(basic_istream<_CharT, _Traits>& __is,
   2276 		    ios_base::iostate& __err, _CharT __c)
   2277 	{
   2278 	  auto __i = __is.peek();
   2279 	  if (_Traits::eq_int_type(__i, _Traits::eof()))
   2280 	    __err |= ios_base::eofbit;
   2281 	  else if (_Traits::to_char_type(__i) == __c) [[likely]]
   2282 	    {
   2283 	      (void) __is.get();
   2284 	      return true;
   2285 	    }
   2286 	  __err |= ios_base::failbit;
   2287 	  return false;
   2288 	}
   2289     };
   2290 
   2291   template<typename _Duration>
   2292     using _Parser_t = _Parser<common_type_t<_Duration, seconds>>;
   2293 
   2294 } // namespace __detail
   2295 /// @endcond
   2296 
   2297   template<typename _CharT, typename _Traits, typename _Rep, typename _Period,
   2298 	   typename _Alloc = allocator<_CharT>>
   2299     inline basic_istream<_CharT, _Traits>&
   2300     from_stream(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
   2301 		duration<_Rep, _Period>& __d,
   2302 		basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
   2303 		minutes* __offset = nullptr)
   2304     {
   2305       auto __need = __format::_ChronoParts::_TimeOfDay;
   2306       __detail::_Parser_t<duration<_Rep, _Period>> __p(__need);
   2307       if (__p(__is, __fmt, __abbrev, __offset))
   2308 	__d = chrono::duration_cast<duration<_Rep, _Period>>(__p._M_time);
   2309       return __is;
   2310     }
   2311 
   2312   template<typename _CharT, typename _Traits>
   2313     inline basic_ostream<_CharT, _Traits>&
   2314     operator<<(basic_ostream<_CharT, _Traits>& __os, const day& __d)
   2315     {
   2316       using _Ctx = __format::__format_context<_CharT>;
   2317       using _Str = basic_string_view<_CharT>;
   2318       _Str __s = _GLIBCXX_WIDEN("{:02d} is not a valid day");
   2319       if (__d.ok())
   2320 	__s = __s.substr(0, 6);
   2321       auto __u = (unsigned)__d;
   2322       __os << std::vformat(__s, make_format_args<_Ctx>(__u));
   2323       return __os;
   2324     }
   2325 
   2326   template<typename _CharT, typename _Traits,
   2327 	   typename _Alloc = allocator<_CharT>>
   2328     inline basic_istream<_CharT, _Traits>&
   2329     from_stream(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
   2330 		day& __d,
   2331 		basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
   2332 		minutes* __offset = nullptr)
   2333     {
   2334       __detail::_Parser<> __p(__format::_ChronoParts::_Day);
   2335       if (__p(__is, __fmt, __abbrev, __offset))
   2336 	__d = __p._M_ymd.day();
   2337       return __is;
   2338     }
   2339 
   2340   template<typename _CharT, typename _Traits>
   2341     inline basic_ostream<_CharT, _Traits>&
   2342     operator<<(basic_ostream<_CharT, _Traits>& __os, const month& __m)
   2343     {
   2344       using _Ctx = __format::__format_context<_CharT>;
   2345       using _Str = basic_string_view<_CharT>;
   2346       _Str __s = _GLIBCXX_WIDEN("{:L%b}{} is not a valid month");
   2347       if (__m.ok())
   2348 	__os << std::vformat(__os.getloc(), __s.substr(0, 6),
   2349 			     make_format_args<_Ctx>(__m));
   2350       else
   2351 	{
   2352 	  auto __u = (unsigned)__m;
   2353 	  __os << std::vformat(__s.substr(6), make_format_args<_Ctx>(__u));
   2354 	}
   2355       return __os;
   2356     }
   2357 
   2358   template<typename _CharT, typename _Traits,
   2359 	   typename _Alloc = allocator<_CharT>>
   2360     inline basic_istream<_CharT, _Traits>&
   2361     from_stream(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
   2362 		month& __m,
   2363 		basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
   2364 		minutes* __offset = nullptr)
   2365     {
   2366       __detail::_Parser<> __p(__format::_ChronoParts::_Month);
   2367       if (__p(__is, __fmt, __abbrev, __offset))
   2368 	__m = __p._M_ymd.month();
   2369       return __is;
   2370     }
   2371 
   2372   template<typename _CharT, typename _Traits>
   2373     inline basic_ostream<_CharT, _Traits>&
   2374     operator<<(basic_ostream<_CharT, _Traits>& __os, const year& __y)
   2375     {
   2376       using _Ctx = __format::__format_context<_CharT>;
   2377       using _Str = basic_string_view<_CharT>;
   2378       _Str __s = _GLIBCXX_WIDEN("-{:04d} is not a valid year");
   2379       if (__y.ok())
   2380 	__s = __s.substr(0, 7);
   2381       int __i = (int)__y;
   2382       if (__i >= 0) [[likely]]
   2383 	__s.remove_prefix(1);
   2384       else
   2385 	__i = -__i;
   2386       __os << std::vformat(__s, make_format_args<_Ctx>(__i));
   2387       return __os;
   2388     }
   2389 
   2390   template<typename _CharT, typename _Traits,
   2391 	   typename _Alloc = allocator<_CharT>>
   2392     inline basic_istream<_CharT, _Traits>&
   2393     from_stream(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
   2394 		year& __y,
   2395 		basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
   2396 		minutes* __offset = nullptr)
   2397     {
   2398       __detail::_Parser<> __p(__format::_ChronoParts::_Year);
   2399       if (__p(__is, __fmt, __abbrev, __offset))
   2400 	__y = __p._M_ymd.year();
   2401       return __is;
   2402     }
   2403 
   2404   template<typename _CharT, typename _Traits>
   2405     inline basic_ostream<_CharT, _Traits>&
   2406     operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday& __wd)
   2407     {
   2408       using _Ctx = __format::__format_context<_CharT>;
   2409       using _Str = basic_string_view<_CharT>;
   2410       _Str __s = _GLIBCXX_WIDEN("{:L%a}{} is not a valid weekday");
   2411       if (__wd.ok())
   2412 	__os << std::vformat(__os.getloc(), __s.substr(0, 6),
   2413 			     make_format_args<_Ctx>(__wd));
   2414       else
   2415 	{
   2416 	  auto __c = __wd.c_encoding();
   2417 	  __os << std::vformat(__s.substr(6), make_format_args<_Ctx>(__c));
   2418 	}
   2419       return __os;
   2420     }
   2421 
   2422   template<typename _CharT, typename _Traits,
   2423 	   typename _Alloc = allocator<_CharT>>
   2424     inline basic_istream<_CharT, _Traits>&
   2425     from_stream(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
   2426 		weekday& __wd,
   2427 		basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
   2428 		minutes* __offset = nullptr)
   2429     {
   2430       __detail::_Parser<> __p(__format::_ChronoParts::_Weekday);
   2431       if (__p(__is, __fmt, __abbrev, __offset))
   2432 	__wd = __p._M_wd;
   2433       return __is;
   2434     }
   2435 
   2436   template<typename _CharT, typename _Traits>
   2437     inline basic_ostream<_CharT, _Traits>&
   2438     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2439 	       const weekday_indexed& __wdi)
   2440     {
   2441       // The standard says to format wdi.weekday() and wdi.index() using
   2442       // either "{:L}[{}]" or "{:L}[{} is not a valid index]". The {:L} spec
   2443       // means to format the weekday using ostringstream, so just do that.
   2444       basic_stringstream<_CharT> __os2;
   2445       __os2.imbue(__os.getloc());
   2446       __os2 << __wdi.weekday();
   2447       const auto __i = __wdi.index();
   2448       basic_string_view<_CharT> __s
   2449 	= _GLIBCXX_WIDEN("[ is not a valid index]");
   2450       __os2 << __s[0];
   2451       __os2 << std::format(_GLIBCXX_WIDEN("{}"), __i);
   2452       if (__i >= 1 && __i <= 5)
   2453 	__os2 << __s.back();
   2454       else
   2455 	__os2 << __s.substr(1);
   2456       __os << __os2.view();
   2457       return __os;
   2458     }
   2459 
   2460   template<typename _CharT, typename _Traits>
   2461     inline basic_ostream<_CharT, _Traits>&
   2462     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2463 	       const weekday_last& __wdl)
   2464     {
   2465       // As above, just write straight to a stringstream, as if by "{:L}[last]"
   2466       basic_stringstream<_CharT> __os2;
   2467       __os2.imbue(__os.getloc());
   2468       __os2 << __wdl.weekday() << _GLIBCXX_WIDEN("[last]");
   2469       __os << __os2.view();
   2470       return __os;
   2471     }
   2472 
   2473   template<typename _CharT, typename _Traits>
   2474     inline basic_ostream<_CharT, _Traits>&
   2475     operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day& __md)
   2476     {
   2477       // As above, just write straight to a stringstream, as if by "{:L}/{}"
   2478       basic_stringstream<_CharT> __os2;
   2479       __os2.imbue(__os.getloc());
   2480       __os2 << __md.month();
   2481       if constexpr (is_same_v<_CharT, char>)
   2482 	__os2 << '/';
   2483       else
   2484 	__os2 << L'/';
   2485       __os2 << __md.day();
   2486       __os << __os2.view();
   2487       return __os;
   2488     }
   2489 
   2490   template<typename _CharT, typename _Traits,
   2491 	   typename _Alloc = allocator<_CharT>>
   2492     inline basic_istream<_CharT, _Traits>&
   2493     from_stream(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
   2494 		month_day& __md,
   2495 		basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
   2496 		minutes* __offset = nullptr)
   2497     {
   2498       using __format::_ChronoParts;
   2499       auto __need = _ChronoParts::_Month | _ChronoParts::_Day;
   2500       __detail::_Parser<> __p(__need);
   2501       if (__p(__is, __fmt, __abbrev, __offset))
   2502 	__md = month_day(__p._M_ymd.month(), __p._M_ymd.day());
   2503       return __is;
   2504     }
   2505 
   2506   template<typename _CharT, typename _Traits>
   2507     inline basic_ostream<_CharT, _Traits>&
   2508     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2509 	       const month_day_last& __mdl)
   2510     {
   2511       // As above, just write straight to a stringstream, as if by "{:L}/last"
   2512       basic_stringstream<_CharT> __os2;
   2513       __os2.imbue(__os.getloc());
   2514       __os2 << __mdl.month() << _GLIBCXX_WIDEN("/last");
   2515       __os << __os2.view();
   2516       return __os;
   2517     }
   2518 
   2519   template<typename _CharT, typename _Traits>
   2520     inline basic_ostream<_CharT, _Traits>&
   2521     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2522 	       const month_weekday& __mwd)
   2523     {
   2524       // As above, just write straight to a stringstream, as if by "{:L}/{:L}"
   2525       basic_stringstream<_CharT> __os2;
   2526       __os2.imbue(__os.getloc());
   2527       __os2 << __mwd.month();
   2528       if constexpr (is_same_v<_CharT, char>)
   2529 	__os2 << '/';
   2530       else
   2531 	__os2 << L'/';
   2532       __os2 << __mwd.weekday_indexed();
   2533       __os << __os2.view();
   2534       return __os;
   2535     }
   2536 
   2537   template<typename _CharT, typename _Traits>
   2538     inline basic_ostream<_CharT, _Traits>&
   2539     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2540 	       const month_weekday_last& __mwdl)
   2541     {
   2542       // As above, just write straight to a stringstream, as if by "{:L}/{:L}"
   2543       basic_stringstream<_CharT> __os2;
   2544       __os2.imbue(__os.getloc());
   2545       __os2 << __mwdl.month();
   2546       if constexpr (is_same_v<_CharT, char>)
   2547 	__os2 << '/';
   2548       else
   2549 	__os2 << L'/';
   2550       __os2 << __mwdl.weekday_last();
   2551       __os << __os2.view();
   2552       return __os;
   2553     }
   2554 
   2555   template<typename _CharT, typename _Traits>
   2556     inline basic_ostream<_CharT, _Traits>&
   2557     operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month& __ym)
   2558     {
   2559       // As above, just write straight to a stringstream, as if by "{}/{:L}"
   2560       basic_stringstream<_CharT> __os2;
   2561       __os2.imbue(__os.getloc());
   2562       __os2 << __ym.year();
   2563       if constexpr (is_same_v<_CharT, char>)
   2564 	__os2 << '/';
   2565       else
   2566 	__os2 << L'/';
   2567       __os2 << __ym.month();
   2568       __os << __os2.view();
   2569       return __os;
   2570     }
   2571 
   2572   template<typename _CharT, typename _Traits,
   2573 	   typename _Alloc = allocator<_CharT>>
   2574     inline basic_istream<_CharT, _Traits>&
   2575     from_stream(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
   2576 		year_month& __ym,
   2577 		basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
   2578 		minutes* __offset = nullptr)
   2579     {
   2580       using __format::_ChronoParts;
   2581       auto __need = _ChronoParts::_Year | _ChronoParts::_Month;
   2582       __detail::_Parser<> __p(__need);
   2583       if (__p(__is, __fmt, __abbrev, __offset))
   2584 	__ym = year_month(__p._M_ymd.year(), __p._M_ymd.month());
   2585       return __is;
   2586     }
   2587 
   2588   template<typename _CharT, typename _Traits>
   2589     inline basic_ostream<_CharT, _Traits>&
   2590     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2591 	       const year_month_day& __ymd)
   2592     {
   2593       using _Ctx = __format::__format_context<_CharT>;
   2594       using _Str = basic_string_view<_CharT>;
   2595       _Str __s = _GLIBCXX_WIDEN("{:%F} is not a valid date");
   2596       __os << std::vformat(__ymd.ok() ? __s.substr(0, 5) : __s,
   2597 			   make_format_args<_Ctx>(__ymd));
   2598       return __os;
   2599     }
   2600 
   2601   template<typename _CharT, typename _Traits,
   2602 	   typename _Alloc = allocator<_CharT>>
   2603     inline basic_istream<_CharT, _Traits>&
   2604     from_stream(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
   2605 		year_month_day& __ymd,
   2606 		basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
   2607 		minutes* __offset = nullptr)
   2608     {
   2609       using __format::_ChronoParts;
   2610       auto __need = _ChronoParts::_Year | _ChronoParts::_Month
   2611 		    | _ChronoParts::_Day;
   2612       __detail::_Parser<> __p(__need);
   2613       if (__p(__is, __fmt, __abbrev, __offset))
   2614 	__ymd = __p._M_ymd;
   2615       return __is;
   2616     }
   2617 
   2618   template<typename _CharT, typename _Traits>
   2619     inline basic_ostream<_CharT, _Traits>&
   2620     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2621 	       const year_month_day_last& __ymdl)
   2622     {
   2623       // As above, just write straight to a stringstream, as if by "{}/{:L}"
   2624       basic_stringstream<_CharT> __os2;
   2625       __os2.imbue(__os.getloc());
   2626       __os2 << __ymdl.year();
   2627       if constexpr (is_same_v<_CharT, char>)
   2628 	__os2 << '/';
   2629       else
   2630 	__os2 << L'/';
   2631       __os2 << __ymdl.month_day_last();
   2632       __os << __os2.view();
   2633       return __os;
   2634     }
   2635 
   2636   template<typename _CharT, typename _Traits>
   2637     inline basic_ostream<_CharT, _Traits>&
   2638     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2639 	       const year_month_weekday& __ymwd)
   2640     {
   2641       // As above, just write straight to a stringstream, as if by
   2642       // "{}/{:L}/{:L}"
   2643       basic_stringstream<_CharT> __os2;
   2644       __os2.imbue(__os.getloc());
   2645       _CharT __slash;
   2646       if constexpr (is_same_v<_CharT, char>)
   2647 	__slash = '/';
   2648       else
   2649 	__slash = L'/';
   2650       __os2 << __ymwd.year() << __slash << __ymwd.month() << __slash
   2651 	    << __ymwd.weekday_indexed();
   2652       __os << __os2.view();
   2653       return __os;
   2654     }
   2655 
   2656   template<typename _CharT, typename _Traits>
   2657     inline basic_ostream<_CharT, _Traits>&
   2658     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2659 	       const year_month_weekday_last& __ymwdl)
   2660     {
   2661       // As above, just write straight to a stringstream, as if by
   2662       // "{}/{:L}/{:L}"
   2663       basic_stringstream<_CharT> __os2;
   2664       __os2.imbue(__os.getloc());
   2665       _CharT __slash;
   2666       if constexpr (is_same_v<_CharT, char>)
   2667 	__slash = '/';
   2668       else
   2669 	__slash = L'/';
   2670       __os2 << __ymwdl.year() << __slash << __ymwdl.month() << __slash
   2671 	    << __ymwdl.weekday_last();
   2672       __os << __os2.view();
   2673       return __os;
   2674     }
   2675 
   2676   template<typename _CharT, typename _Traits, typename _Duration>
   2677     inline basic_ostream<_CharT, _Traits>&
   2678     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2679 	       const hh_mm_ss<_Duration>& __hms)
   2680     {
   2681       return __os << format(__os.getloc(), _GLIBCXX_WIDEN("{:L%T}"), __hms);
   2682     }
   2683 
   2684 #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
   2685   /// Writes a sys_info object to an ostream in an unspecified format.
   2686   template<typename _CharT, typename _Traits>
   2687     basic_ostream<_CharT, _Traits>&
   2688     operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_info& __i)
   2689     {
   2690       __os << '[' << __i.begin << ',' << __i.end
   2691 	   << ',' << hh_mm_ss(__i.offset) << ',' << __i.save
   2692 	   << ',' << __i.abbrev << ']';
   2693       return __os;
   2694     }
   2695 
   2696   /// Writes a local_info object to an ostream in an unspecified format.
   2697   template<typename _CharT, typename _Traits>
   2698     basic_ostream<_CharT, _Traits>&
   2699     operator<<(basic_ostream<_CharT, _Traits>& __os, const local_info& __li)
   2700     {
   2701       __os << '[';
   2702       if (__li.result == local_info::unique)
   2703 	__os << __li.first;
   2704       else
   2705 	{
   2706 	  if (__li.result == local_info::nonexistent)
   2707 	    __os << "nonexistent";
   2708 	  else
   2709 	    __os << "ambiguous";
   2710 	  __os << " local time between " << __li.first;
   2711 	  __os << " and " << __li.second;
   2712 	}
   2713       __os << ']';
   2714       return __os;
   2715     }
   2716 
   2717   template<typename _CharT, typename _Traits, typename _Duration,
   2718 	   typename _TimeZonePtr>
   2719     inline basic_ostream<_CharT, _Traits>&
   2720     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2721 	       const zoned_time<_Duration, _TimeZonePtr>& __t)
   2722     {
   2723       __os << format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T %Z}"), __t);
   2724       return __os;
   2725     }
   2726 #endif
   2727 
   2728   template<typename _CharT, typename _Traits, typename _Duration>
   2729     requires (!treat_as_floating_point_v<typename _Duration::rep>)
   2730       && ratio_less_v<typename _Duration::period, days::period>
   2731     inline basic_ostream<_CharT, _Traits>&
   2732     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2733 	       const sys_time<_Duration>& __tp)
   2734     {
   2735       __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __tp);
   2736       return __os;
   2737     }
   2738 
   2739   template<typename _CharT, typename _Traits>
   2740     inline basic_ostream<_CharT, _Traits>&
   2741     operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_days& __dp)
   2742     {
   2743       __os << year_month_day{__dp};
   2744       return __os;
   2745     }
   2746 
   2747   template<typename _CharT, typename _Traits, typename _Duration,
   2748 	   typename _Alloc = allocator<_CharT>>
   2749     basic_istream<_CharT, _Traits>&
   2750     from_stream(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
   2751 		sys_time<_Duration>& __tp,
   2752 		basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
   2753 		minutes* __offset = nullptr)
   2754     {
   2755       minutes __off{};
   2756       if (!__offset)
   2757 	__offset = &__off;
   2758       using __format::_ChronoParts;
   2759       auto __need = _ChronoParts::_Year | _ChronoParts::_Month
   2760 		    | _ChronoParts::_Day | _ChronoParts::_TimeOfDay;
   2761       __detail::_Parser_t<_Duration> __p(__need);
   2762       if (__p(__is, __fmt, __abbrev, __offset))
   2763 	{
   2764 	  if (__p._M_is_leap_second)
   2765 	    __is.setstate(ios_base::failbit);
   2766 	  else
   2767 	    {
   2768 	      auto __st = __p._M_sys_days + __p._M_time - *__offset;
   2769 	      __tp = chrono::time_point_cast<_Duration>(__st);
   2770 	    }
   2771 	}
   2772       return __is;
   2773     }
   2774 
   2775   template<typename _CharT, typename _Traits, typename _Duration>
   2776     inline basic_ostream<_CharT, _Traits>&
   2777     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2778 	       const utc_time<_Duration>& __t)
   2779     {
   2780       __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __t);
   2781       return __os;
   2782     }
   2783 
   2784   template<typename _CharT, typename _Traits, typename _Duration,
   2785 	   typename _Alloc = allocator<_CharT>>
   2786     inline basic_istream<_CharT, _Traits>&
   2787     from_stream(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
   2788 		utc_time<_Duration>& __tp,
   2789 		basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
   2790 		minutes* __offset = nullptr)
   2791     {
   2792       minutes __off{};
   2793       if (!__offset)
   2794 	__offset = &__off;
   2795       using __format::_ChronoParts;
   2796       auto __need = _ChronoParts::_Year | _ChronoParts::_Month
   2797 		    | _ChronoParts::_Day | _ChronoParts::_TimeOfDay;
   2798       __detail::_Parser_t<_Duration> __p(__need);
   2799       if (__p(__is, __fmt, __abbrev, __offset))
   2800 	{
   2801 	  // Converting to utc_time before adding _M_time is necessary for
   2802 	  // "23:59:60" to correctly produce a time within a leap second.
   2803 	  auto __ut = utc_clock::from_sys(__p._M_sys_days) + __p._M_time
   2804 			- *__offset;
   2805 	  __tp = chrono::time_point_cast<_Duration>(__ut);
   2806 	}
   2807       return __is;
   2808     }
   2809 
   2810   template<typename _CharT, typename _Traits, typename _Duration>
   2811     inline basic_ostream<_CharT, _Traits>&
   2812     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2813 	       const tai_time<_Duration>& __t)
   2814     {
   2815       __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __t);
   2816       return __os;
   2817     }
   2818 
   2819   template<typename _CharT, typename _Traits, typename _Duration,
   2820 	   typename _Alloc = allocator<_CharT>>
   2821     inline basic_istream<_CharT, _Traits>&
   2822     from_stream(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
   2823 		tai_time<_Duration>& __tp,
   2824 		basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
   2825 		minutes* __offset = nullptr)
   2826     {
   2827       minutes __off{};
   2828       if (!__offset)
   2829 	__offset = &__off;
   2830       using __format::_ChronoParts;
   2831       auto __need = _ChronoParts::_Year | _ChronoParts::_Month
   2832 		    | _ChronoParts::_Day | _ChronoParts::_TimeOfDay;
   2833       __detail::_Parser_t<_Duration> __p(__need);
   2834       if (__p(__is, __fmt, __abbrev, __offset))
   2835 	{
   2836 	  if (__p._M_is_leap_second)
   2837 	    __is.setstate(ios_base::failbit);
   2838 	  else
   2839 	    {
   2840 	      auto __st = __p._M_sys_days + __p._M_time - *__offset;
   2841 	      auto __tt = tai_clock::from_utc(utc_clock::from_sys(__st));
   2842 	      __tp = chrono::time_point_cast<_Duration>(__tt);
   2843 	    }
   2844 	}
   2845       return __is;
   2846     }
   2847 
   2848   template<typename _CharT, typename _Traits, typename _Duration>
   2849     inline basic_ostream<_CharT, _Traits>&
   2850     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2851 	       const gps_time<_Duration>& __t)
   2852     {
   2853       __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __t);
   2854       return __os;
   2855     }
   2856 
   2857   template<typename _CharT, typename _Traits, typename _Duration,
   2858 	   typename _Alloc = allocator<_CharT>>
   2859     inline basic_istream<_CharT, _Traits>&
   2860     from_stream(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
   2861 		gps_time<_Duration>& __tp,
   2862 		basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
   2863 		minutes* __offset = nullptr)
   2864     {
   2865       minutes __off{};
   2866       if (!__offset)
   2867 	__offset = &__off;
   2868       using __format::_ChronoParts;
   2869       auto __need = _ChronoParts::_Year | _ChronoParts::_Month
   2870 		    | _ChronoParts::_Day | _ChronoParts::_TimeOfDay;
   2871       __detail::_Parser_t<_Duration> __p(__need);
   2872       if (__p(__is, __fmt, __abbrev, __offset))
   2873 	{
   2874 	  if (__p._M_is_leap_second)
   2875 	    __is.setstate(ios_base::failbit);
   2876 	  else
   2877 	    {
   2878 	      auto __st = __p._M_sys_days + __p._M_time - *__offset;
   2879 	      auto __tt = gps_clock::from_utc(utc_clock::from_sys(__st));
   2880 	      __tp = chrono::time_point_cast<_Duration>(__tt);
   2881 	    }
   2882 	}
   2883       return __is;
   2884     }
   2885 
   2886   template<typename _CharT, typename _Traits, typename _Duration>
   2887     inline basic_ostream<_CharT, _Traits>&
   2888     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2889 	       const file_time<_Duration>& __t)
   2890     {
   2891       __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __t);
   2892       return __os;
   2893     }
   2894 
   2895   template<typename _CharT, typename _Traits, typename _Duration,
   2896 	   typename _Alloc = allocator<_CharT>>
   2897     inline basic_istream<_CharT, _Traits>&
   2898     from_stream(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
   2899 		file_time<_Duration>& __tp,
   2900 		basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
   2901 		minutes* __offset = nullptr)
   2902     {
   2903       sys_time<_Duration> __st;
   2904       if (chrono::from_stream(__is, __fmt, __st, __abbrev, __offset))
   2905 	__tp = chrono::time_point_cast<_Duration>(file_clock::from_sys(__st));
   2906       return __is;
   2907     }
   2908 
   2909   template<typename _CharT, typename _Traits, typename _Duration>
   2910     inline basic_ostream<_CharT, _Traits>&
   2911     operator<<(basic_ostream<_CharT, _Traits>& __os,
   2912 	       const local_time<_Duration>& __lt)
   2913     {
   2914       __os << sys_time<_Duration>{__lt.time_since_epoch()};
   2915       return __os;
   2916     }
   2917 
   2918   template<typename _CharT, typename _Traits, typename _Duration,
   2919 	   typename _Alloc = allocator<_CharT>>
   2920     basic_istream<_CharT, _Traits>&
   2921     from_stream(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
   2922 		local_time<_Duration>& __tp,
   2923 		basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
   2924 		minutes* __offset = nullptr)
   2925     {
   2926       using __format::_ChronoParts;
   2927       auto __need = _ChronoParts::_Year | _ChronoParts::_Month
   2928 		    | _ChronoParts::_Day | _ChronoParts::_TimeOfDay;
   2929       __detail::_Parser_t<_Duration> __p(__need);
   2930       if (__p(__is, __fmt, __abbrev, __offset))
   2931 	{
   2932 	  days __d = __p._M_sys_days.time_since_epoch();
   2933 	  auto __t = local_days(__d) + __p._M_time; // ignore offset
   2934 	  __tp = chrono::time_point_cast<_Duration>(__t);
   2935 	}
   2936       return __is;
   2937     }
   2938 
   2939   // [time.parse] parsing
   2940 
   2941 namespace __detail
   2942 {
   2943   template<typename _Parsable, typename _CharT,
   2944 	   typename _Traits = std::char_traits<_CharT>,
   2945 	   typename... _OptArgs>
   2946     concept __parsable = requires (basic_istream<_CharT, _Traits>& __is,
   2947 				   const _CharT* __fmt, _Parsable& __tp,
   2948 				   _OptArgs*... __args)
   2949     { from_stream(__is, __fmt, __tp, __args...); };
   2950 
   2951   template<typename _Parsable, typename _CharT,
   2952 	   typename _Traits = char_traits<_CharT>,
   2953 	   typename _Alloc = allocator<_CharT>>
   2954     struct _Parse
   2955     {
   2956     private:
   2957       using __string_type = basic_string<_CharT, _Traits, _Alloc>;
   2958 
   2959     public:
   2960       _Parse(const _CharT* __fmt, _Parsable& __tp,
   2961 	     basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
   2962 	     minutes* __offset = nullptr)
   2963       : _M_fmt(__fmt), _M_tp(std::__addressof(__tp)),
   2964 	_M_abbrev(__abbrev), _M_offset(__offset)
   2965       { }
   2966 
   2967       _Parse(_Parse&&) = delete;
   2968       _Parse& operator=(_Parse&&) = delete;
   2969 
   2970     private:
   2971       using __stream_type = basic_istream<_CharT, _Traits>;
   2972 
   2973       const _CharT* const  _M_fmt;
   2974       _Parsable* const     _M_tp;
   2975       __string_type* const _M_abbrev;
   2976       minutes* const       _M_offset;
   2977 
   2978       friend __stream_type&
   2979       operator>>(__stream_type& __is, _Parse&& __p)
   2980       {
   2981 	if (__p._M_offset)
   2982 	  from_stream(__is, __p._M_fmt, *__p._M_tp, __p._M_abbrev,
   2983 		      __p._M_offset);
   2984 	else if (__p._M_abbrev)
   2985 	  from_stream(__is, __p._M_fmt, *__p._M_tp, __p._M_abbrev);
   2986 	else
   2987 	  from_stream(__is, __p._M_fmt, *__p._M_tp);
   2988 	return __is;
   2989       }
   2990 
   2991       friend void operator>>(__stream_type&, _Parse&) = delete;
   2992       friend void operator>>(__stream_type&, const _Parse&) = delete;
   2993     };
   2994 } // namespace __detail
   2995 
   2996   template<typename _CharT, __detail::__parsable<_CharT> _Parsable>
   2997     [[nodiscard, __gnu__::__access__(__read_only__, 1)]]
   2998     inline auto
   2999     parse(const _CharT* __fmt, _Parsable& __tp)
   3000     { return __detail::_Parse<_Parsable, _CharT>(__fmt, __tp); }
   3001 
   3002   template<typename _CharT, typename _Traits, typename _Alloc,
   3003 	   __detail::__parsable<_CharT, _Traits> _Parsable>
   3004     [[nodiscard]]
   3005     inline auto
   3006     parse(const basic_string<_CharT, _Traits, _Alloc>& __fmt, _Parsable& __tp)
   3007     {
   3008       return __detail::_Parse<_Parsable, _CharT, _Traits>(__fmt.c_str(), __tp);
   3009     }
   3010 
   3011   template<typename _CharT, typename _Traits, typename _Alloc,
   3012 	   typename _StrT = basic_string<_CharT, _Traits, _Alloc>,
   3013 	   __detail::__parsable<_CharT, _Traits, _StrT> _Parsable>
   3014     [[nodiscard, __gnu__::__access__(__read_only__, 1)]]
   3015     inline auto
   3016     parse(const _CharT* __fmt, _Parsable& __tp,
   3017 	  basic_string<_CharT, _Traits, _Alloc>& __abbrev)
   3018     {
   3019       auto __pa = std::__addressof(__abbrev);
   3020       return __detail::_Parse<_Parsable, _CharT, _Traits, _Alloc>(__fmt, __tp,
   3021 								  __pa);
   3022     }
   3023 
   3024   template<typename _CharT, typename _Traits, typename _Alloc,
   3025 	   typename _StrT = basic_string<_CharT, _Traits, _Alloc>,
   3026 	   __detail::__parsable<_CharT, _Traits, _StrT> _Parsable>
   3027     [[nodiscard]]
   3028     inline auto
   3029     parse(const basic_string<_CharT, _Traits, _Alloc>& __fmt, _Parsable& __tp,
   3030 	  basic_string<_CharT, _Traits, _Alloc>& __abbrev)
   3031     {
   3032       auto __pa = std::__addressof(__abbrev);
   3033       return __detail::_Parse<_Parsable, _CharT, _Traits, _Alloc>(__fmt.c_str(),
   3034 								  __tp, __pa);
   3035     }
   3036 
   3037   template<typename _CharT, typename _Traits = char_traits<_CharT>,
   3038 	   typename _StrT = basic_string<_CharT, _Traits>,
   3039 	   __detail::__parsable<_CharT, _Traits, _StrT, minutes> _Parsable>
   3040     [[nodiscard, __gnu__::__access__(__read_only__, 1)]]
   3041     inline auto
   3042     parse(const _CharT* __fmt, _Parsable& __tp, minutes& __offset)
   3043     {
   3044       return __detail::_Parse<_Parsable, _CharT>(__fmt, __tp, nullptr,
   3045 						 &__offset);
   3046     }
   3047 
   3048   template<typename _CharT, typename _Traits, typename _Alloc,
   3049 	   typename _StrT = basic_string<_CharT, _Traits>,
   3050 	   __detail::__parsable<_CharT, _Traits, _StrT, minutes> _Parsable>
   3051     [[nodiscard]]
   3052     inline auto
   3053     parse(const basic_string<_CharT, _Traits, _Alloc>& __fmt, _Parsable& __tp,
   3054 	  minutes& __offset)
   3055     {
   3056       return __detail::_Parse<_Parsable, _CharT, _Traits, _Alloc>(__fmt.c_str(),
   3057 								  __tp, nullptr,
   3058 								  &__offset);
   3059     }
   3060 
   3061   template<typename _CharT, typename _Traits, typename _Alloc,
   3062 	   typename _StrT = basic_string<_CharT, _Traits, _Alloc>,
   3063 	   __detail::__parsable<_CharT, _Traits, _StrT, minutes> _Parsable>
   3064     [[nodiscard, __gnu__::__access__(__read_only__, 1)]]
   3065     inline auto
   3066     parse(const _CharT* __fmt, _Parsable& __tp,
   3067 	  basic_string<_CharT, _Traits, _Alloc>& __abbrev, minutes& __offset)
   3068     {
   3069       auto __pa = std::__addressof(__abbrev);
   3070       return __detail::_Parse<_Parsable, _CharT, _Traits, _Alloc>(__fmt, __tp,
   3071 								  __pa,
   3072 								  &__offset);
   3073     }
   3074 
   3075   template<typename _CharT, typename _Traits, typename _Alloc,
   3076 	   typename _StrT = basic_string<_CharT, _Traits, _Alloc>,
   3077 	   __detail::__parsable<_CharT, _Traits, _StrT, minutes> _Parsable>
   3078     [[nodiscard]]
   3079     inline auto
   3080     parse(const basic_string<_CharT, _Traits, _Alloc>& __fmt, _Parsable& __tp,
   3081 	  basic_string<_CharT, _Traits, _Alloc>& __abbrev, minutes& __offset)
   3082     {
   3083       auto __pa = std::__addressof(__abbrev);
   3084       return __detail::_Parse<_Parsable, _CharT, _Traits, _Alloc>(__fmt.c_str(),
   3085 								  __tp, __pa,
   3086 								  &__offset);
   3087     }
   3088 
   3089   /// @cond undocumented
   3090   template<typename _Duration>
   3091   template<typename _CharT, typename _Traits, typename _Alloc>
   3092     basic_istream<_CharT, _Traits>&
   3093     __detail::_Parser<_Duration>::
   3094     operator()(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
   3095 	       basic_string<_CharT, _Traits, _Alloc>* __abbrev,
   3096 	       minutes* __offset)
   3097     {
   3098       using sentry = typename basic_istream<_CharT, _Traits>::sentry;
   3099       ios_base::iostate __err = ios_base::goodbit;
   3100       if (sentry __cerb(__is, true); __cerb)
   3101 	{
   3102 	  locale __loc = __is.getloc();
   3103 	  auto& __tmget = std::use_facet<std::time_get<_CharT>>(__loc);
   3104 	  auto& __tmpunct = std::use_facet<std::__timepunct<_CharT>>(__loc);
   3105 
   3106 	  // RAII type to save and restore stream state.
   3107 	  struct _Stream_state
   3108 	  {
   3109 	    explicit
   3110 	    _Stream_state(basic_istream<_CharT, _Traits>& __i)
   3111 	    : _M_is(__i),
   3112 	      _M_flags(__i.flags(ios_base::skipws | ios_base::dec)),
   3113 	      _M_w(__i.width(0))
   3114 	    { }
   3115 
   3116 	    ~_Stream_state()
   3117 	    {
   3118 	      _M_is.flags(_M_flags);
   3119 	      _M_is.width(_M_w);
   3120 	    }
   3121 
   3122 	    _Stream_state(_Stream_state&&) = delete;
   3123 
   3124 	    basic_istream<_CharT, _Traits>& _M_is;
   3125 	    ios_base::fmtflags _M_flags;
   3126 	    streamsize _M_w;
   3127 	  };
   3128 
   3129 	  auto __is_failed = [](ios_base::iostate __e) {
   3130 	    return static_cast<bool>(__e & ios_base::failbit);
   3131 	  };
   3132 
   3133 	  // Read an unsigned integer from the stream and return it.
   3134 	  // Extract no more than __n digits. Set __err on error.
   3135 	  auto __read_unsigned = [&] (int __n) {
   3136 	    return _S_read_unsigned(__is, __err, __n);
   3137 	  };
   3138 
   3139 	  // Read a signed integer from the stream and return it.
   3140 	  // Extract no more than __n digits. Set __err on error.
   3141 	  auto __read_signed = [&] (int __n) {
   3142 	    return _S_read_signed(__is, __err, __n);
   3143 	  };
   3144 
   3145 	  // Read an expected character from the stream.
   3146 	  auto __read_chr = [&__is, &__err] (_CharT __c) {
   3147 	    return _S_read_chr(__is, __err, __c);
   3148 	  };
   3149 
   3150 	  using __format::_ChronoParts;
   3151 	  _ChronoParts __parts{};
   3152 
   3153 	  const year __bad_y = --year::min(); // SHRT_MIN
   3154 	  const month __bad_mon(255);
   3155 	  const day __bad_day(255);
   3156 	  const weekday __bad_wday(255);
   3157 	  const hours __bad_h(-1);
   3158 	  const minutes __bad_min(-9999);
   3159 	  const seconds __bad_sec(-1);
   3160 
   3161 	  year __y = __bad_y, __yy = __bad_y;         // %Y, %yy
   3162 	  year __iso_y = __bad_y, __iso_yy = __bad_y; // %G, %g
   3163 	  month __m = __bad_mon;                      // %m
   3164 	  day __d = __bad_day;                        // %d
   3165 	  weekday __wday = __bad_wday;                // %a %A %u %w
   3166 	  hours __h = __bad_h, __h12 = __bad_h;       // %H, %I
   3167 	  minutes __min = __bad_min;                  // %M
   3168 	  _Duration __s = __bad_sec;                  // %S
   3169 	  int __ampm = 0;                             // %p
   3170 	  int __iso_wk = -1, __sunday_wk = -1, __monday_wk = -1; // %V, %U, %W
   3171 	  int __century = -1;                         // %C
   3172 	  int __dayofyear = -1;                       // %j (for non-duration)
   3173 
   3174 	  minutes __tz_offset = __bad_min;
   3175 	  basic_string<_CharT, _Traits> __tz_abbr;
   3176 
   3177 	  if ((_M_need & _ChronoParts::_TimeOfDay)
   3178 		&& (_M_need & _ChronoParts::_Year))
   3179 	    {
   3180 	      // For time_points assume "00:00:00" is implicitly present,
   3181 	      // so we don't fail to parse if it's not (PR libstdc++/114240).
   3182 	      // We will still fail to parse if there's no year+month+day.
   3183 	      __h = hours(0);
   3184 	      __parts = _ChronoParts::_TimeOfDay;
   3185 	    }
   3186 
   3187 	  // bool __is_neg = false; // TODO: how is this handled for parsing?
   3188 
   3189 	  _CharT __mod{}; // One of 'E' or 'O' or nul.
   3190 	  unsigned __num = 0; // Non-zero for N modifier.
   3191 	  bool __is_flag = false; // True if we're processing a % flag.
   3192 
   3193 	  constexpr bool __is_floating
   3194 	    = treat_as_floating_point_v<typename _Duration::rep>;
   3195 
   3196 	  // If an out-of-range value is extracted (e.g. 61min for %M),
   3197 	  // do not set failbit immediately because we might not need it
   3198 	  // (e.g. parsing chrono::year doesn't care about invalid %M values).
   3199 	  // Instead set the variable back to its initial 'bad' state,
   3200 	  // and also set related variables corresponding to the same field
   3201 	  // (e.g. a bad %M value for __min should also reset __h and __s).
   3202 	  // If a valid value is needed later the bad value will cause failure.
   3203 
   3204 	  // For some fields we don't know the correct range when parsing and
   3205 	  // we have to be liberal in what we accept, e.g. we allow 366 for
   3206 	  // day-of-year because that's valid in leap years, and we allow 31
   3207 	  // for day-of-month. If those values are needed to determine the
   3208 	  // result then we can do a correct range check at the end when we
   3209 	  // know the how many days the relevant year or month actually has.
   3210 
   3211 	  while (*__fmt)
   3212 	    {
   3213 	      _CharT __c = *__fmt++;
   3214 	      if (!__is_flag)
   3215 		{
   3216 		  if (__c == '%')
   3217 		    __is_flag = true; // This is the start of a flag.
   3218 		  else if (std::isspace(__c, __loc))
   3219 		    std::ws(__is); // Match zero or more whitespace characters.
   3220 		  else if (!__read_chr(__c)) [[unlikely]]
   3221 		    break; // Failed to match the expected character.
   3222 
   3223 		  continue; // Process next character in the format string.
   3224 		}
   3225 
   3226 	      // Now processing a flag.
   3227 	      switch (__c)
   3228 	      {
   3229 		case 'a': // Locale's weekday name
   3230 		case 'A': // (full or abbreviated, matched case-insensitively).
   3231 		  if (__mod || __num) [[unlikely]]
   3232 		    __err = ios_base::failbit;
   3233 		  else
   3234 		    {
   3235 		      struct tm __tm{};
   3236 		      __tmget.get(__is, {}, __is, __err, &__tm,
   3237 				  __fmt - 2, __fmt);
   3238 		      if (!__is_failed(__err))
   3239 			__wday = weekday(__tm.tm_wday);
   3240 		    }
   3241 		  __parts |= _ChronoParts::_Weekday;
   3242 		  break;
   3243 
   3244 		case 'b': // Locale's month name
   3245 		case 'h': // (full or abbreviated, matched case-insensitively).
   3246 		case 'B':
   3247 		  if (__mod || __num) [[unlikely]]
   3248 		    __err = ios_base::failbit;
   3249 		  else
   3250 		    {
   3251 		      // strptime behaves differently for %b and %B,
   3252 		      // but chrono::parse says they're equivalent.
   3253 		      // Luckily libstdc++ std::time_get works as needed.
   3254 		      struct tm __tm{};
   3255 		      __tmget.get(__is, {}, __is, __err, &__tm,
   3256 				  __fmt - 2, __fmt);
   3257 		      if (!__is_failed(__err))
   3258 			__m = month(__tm.tm_mon + 1);
   3259 		    }
   3260 		  __parts |= _ChronoParts::_Month;
   3261 		  break;
   3262 
   3263 		case 'c': // Locale's date and time representation.
   3264 		  if (__mod == 'O' || __num) [[unlikely]]
   3265 		    __err |= ios_base::failbit;
   3266 		  else
   3267 		    {
   3268 		      struct tm __tm{};
   3269 		      __tmget.get(__is, {}, __is, __err, &__tm,
   3270 				  __fmt - 2 - (__mod == 'E'), __fmt);
   3271 		      if (!__is_failed(__err))
   3272 			{
   3273 			  __y = year(__tm.tm_year + 1900);
   3274 			  __m = month(__tm.tm_mon + 1);
   3275 			  __d = day(__tm.tm_mday);
   3276 			  __h = hours(__tm.tm_hour);
   3277 			  __min = minutes(__tm.tm_min);
   3278 			  __s = seconds(__tm.tm_sec);
   3279 			}
   3280 		    }
   3281 		  __parts |= _ChronoParts::_DateTime;
   3282 		  break;
   3283 
   3284 		case 'C': // Century
   3285 		  if (!__mod) [[likely]]
   3286 		    {
   3287 		      auto __v = __read_signed(__num ? __num : 2);
   3288 		      if (!__is_failed(__err))
   3289 			{
   3290 			  int __cmin = (int)year::min() / 100;
   3291 			  int __cmax = (int)year::max() / 100;
   3292 			  if (__cmin <= __v && __v <= __cmax)
   3293 			    __century = __v * 100;
   3294 			  else
   3295 			    __century = -2; // This prevents guessing century.
   3296 			}
   3297 		    }
   3298 		  else if (__mod == 'E')
   3299 		    {
   3300 		      struct tm __tm{};
   3301 		      __tmget.get(__is, {}, __is, __err, &__tm,
   3302 				  __fmt - 3, __fmt);
   3303 		      if (!__is_failed(__err))
   3304 			__century = __tm.tm_year;
   3305 		    }
   3306 		  else [[unlikely]]
   3307 		    __err |= ios_base::failbit;
   3308 		  // N.B. don't set this here: __parts |= _ChronoParts::_Year;
   3309 		  break;
   3310 
   3311 		case 'd': // Day of month (1-31)
   3312 		case 'e':
   3313 		  if (!__mod) [[likely]]
   3314 		    {
   3315 		      auto __v = __read_unsigned(__num ? __num : 2);
   3316 		      if (!__is_failed(__err))
   3317 			__d = day(__v);
   3318 		    }
   3319 		  else if (__mod == 'O')
   3320 		    {
   3321 		      struct tm __tm{};
   3322 		      __tmget.get(__is, {}, __is, __err, &__tm,
   3323 				  __fmt - 3, __fmt);
   3324 		      if (!__is_failed(__err))
   3325 			__d = day(__tm.tm_mday);
   3326 		    }
   3327 		  else [[unlikely]]
   3328 		    __err |= ios_base::failbit;
   3329 		  __parts |= _ChronoParts::_Day;
   3330 		  break;
   3331 
   3332 		case 'D': // %m/%d/%y
   3333 		  if (__mod || __num) [[unlikely]]
   3334 		    __err |= ios_base::failbit;
   3335 		  else
   3336 		    {
   3337 		      auto __month = __read_unsigned(2); // %m
   3338 		      __read_chr('/');
   3339 		      auto __day = __read_unsigned(2); // %d
   3340 		      __read_chr('/');
   3341 		      auto __year = __read_unsigned(2); // %y
   3342 		      if (__is_failed(__err))
   3343 			break;
   3344 		      __y = year(__year + 1900 + 100 * int(__year < 69));
   3345 		      __m = month(__month);
   3346 		      __d = day(__day);
   3347 		      if (!year_month_day(__y, __m, __d).ok())
   3348 			{
   3349 			  __y = __yy = __iso_y = __iso_yy = __bad_y;
   3350 			  __m = __bad_mon;
   3351 			  __d = __bad_day;
   3352 			  break;
   3353 			}
   3354 		    }
   3355 		  __parts |= _ChronoParts::_Date;
   3356 		  break;
   3357 
   3358 		case 'F': // %Y-%m-%d - any N modifier only applies to %Y.
   3359 		  if (__mod) [[unlikely]]
   3360 		    __err |= ios_base::failbit;
   3361 		  else
   3362 		    {
   3363 		      auto __year = __read_signed(__num ? __num : 4); // %Y
   3364 		      __read_chr('-');
   3365 		      auto __month = __read_unsigned(2); // %m
   3366 		      __read_chr('-');
   3367 		      auto __day = __read_unsigned(2); // %d
   3368 		      if (__is_failed(__err))
   3369 			break;
   3370 		      __y = year(__year);
   3371 		      __m = month(__month);
   3372 		      __d = day(__day);
   3373 		      if (!year_month_day(__y, __m, __d).ok())
   3374 			{
   3375 			  __y = __yy = __iso_y = __iso_yy = __bad_y;
   3376 			  __m = __bad_mon;
   3377 			  __d = __bad_day;
   3378 			  break;
   3379 			}
   3380 		    }
   3381 		  __parts |= _ChronoParts::_Date;
   3382 		  break;
   3383 
   3384 		case 'g': // Last two digits of ISO week-based year.
   3385 		  if (__mod) [[unlikely]]
   3386 		    __err |= ios_base::failbit;
   3387 		  else
   3388 		    {
   3389 		      auto __val = __read_unsigned(__num ? __num : 2);
   3390 		      if (__val >= 0 && __val <= 99)
   3391 			{
   3392 			  __iso_yy = year(__val);
   3393 			  if (__century == -1) // No %C has been parsed yet.
   3394 			    __century = 2000;
   3395 			}
   3396 		      else
   3397 			__iso_yy = __iso_y = __y = __yy = __bad_y;
   3398 		    }
   3399 		  __parts |= _ChronoParts::_Year;
   3400 		  break;
   3401 
   3402 		case 'G': // ISO week-based year.
   3403 		  if (__mod) [[unlikely]]
   3404 		    __err |= ios_base::failbit;
   3405 		  else
   3406 		    __iso_y = year(__read_unsigned(__num ? __num : 4));
   3407 		  __parts |= _ChronoParts::_Year;
   3408 		  break;
   3409 
   3410 		case 'H': // 24-hour (00-23)
   3411 		case 'I': // 12-hour (1-12)
   3412 		  if (__mod == 'E') [[unlikely]]
   3413 		    __err |= ios_base::failbit;
   3414 		  else if (__mod == 'O')
   3415 		    {
   3416 #if 0
   3417 		      struct tm __tm{};
   3418 		      __tm.tm_ampm = 1;
   3419 		      __tmget.get(__is, {}, __is, __err, &__tm,
   3420 				  __fmt - 3, __fmt);
   3421 		      if (!__is_failed(__err))
   3422 			{
   3423 			  if (__c == 'I')
   3424 			    {
   3425 			      __h12 = hours(__tm.tm_hour);
   3426 			      __h = __bad_h;
   3427 			    }
   3428 			  else
   3429 			    __h = hours(__tm.tm_hour);
   3430 			}
   3431 #else
   3432 		      // XXX %OI seems to be unimplementable.
   3433 		      __err |= ios_base::failbit;
   3434 #endif
   3435 		    }
   3436 		  else
   3437 		    {
   3438 		      auto __val = __read_unsigned(__num ? __num : 2);
   3439 		      if (__c == 'I' && __val >= 1 && __val <= 12)
   3440 			{
   3441 			  __h12 = hours(__val);
   3442 			  __h = __bad_h;
   3443 			}
   3444 		      else if (__c == 'H' && __val >= 0 && __val <= 23)
   3445 			{
   3446 			  __h = hours(__val);
   3447 			  __h12 = __bad_h;
   3448 			}
   3449 		      else
   3450 			{
   3451 			  if (_M_need & _ChronoParts::_TimeOfDay)
   3452 			    __err |= ios_base::failbit;
   3453 			  break;
   3454 			}
   3455 		    }
   3456 		  __parts |= _ChronoParts::_TimeOfDay;
   3457 		  break;
   3458 
   3459 		case 'j': // For duration, count of days, otherwise day of year
   3460 		  if (__mod) [[unlikely]]
   3461 		    __err |= ios_base::failbit;
   3462 		  else if (_M_need == _ChronoParts::_TimeOfDay) // duration
   3463 		    {
   3464 		      auto __val = __read_signed(__num ? __num : 3);
   3465 		      if (!__is_failed(__err))
   3466 			{
   3467 			  __h = days(__val); // __h will get added to _M_time
   3468 			  __parts |= _ChronoParts::_TimeOfDay;
   3469 			}
   3470 		    }
   3471 		  else
   3472 		    {
   3473 		      __dayofyear = __read_unsigned(__num ? __num : 3);
   3474 		      // N.B. do not alter __parts here, done after loop.
   3475 		      // No need for range checking here either.
   3476 		    }
   3477 		  break;
   3478 
   3479 		case 'm': // Month (1-12)
   3480 		  if (__mod == 'E') [[unlikely]]
   3481 		    __err |= ios_base::failbit;
   3482 		  else if (__mod == 'O')
   3483 		    {
   3484 		      struct tm __tm{};
   3485 		      __tmget.get(__is, {}, __is, __err, &__tm,
   3486 				  __fmt - 2, __fmt);
   3487 		      if (!__is_failed(__err))
   3488 			__m = month(__tm.tm_mon + 1);
   3489 		    }
   3490 		  else
   3491 		    {
   3492 		      auto __val = __read_unsigned(__num ? __num : 2);
   3493 		      if (__val >= 1 && __val <= 12)
   3494 			__m = month(__val);
   3495 		      else
   3496 			__m = __bad_mon;
   3497 		    }
   3498 		  __parts |= _ChronoParts::_Month;
   3499 		  break;
   3500 
   3501 		case 'M': // Minutes
   3502 		  if (__mod == 'E') [[unlikely]]
   3503 		    __err |= ios_base::failbit;
   3504 		  else if (__mod == 'O')
   3505 		    {
   3506 		      struct tm __tm{};
   3507 		      __tmget.get(__is, {}, __is, __err, &__tm,
   3508 				  __fmt - 2, __fmt);
   3509 		      if (!__is_failed(__err))
   3510 			__min = minutes(__tm.tm_min);
   3511 		    }
   3512 		  else
   3513 		    {
   3514 		      auto __val = __read_unsigned(__num ? __num : 2);
   3515 		      if (0 <= __val && __val < 60)
   3516 			__min = minutes(__val);
   3517 		      else
   3518 			{
   3519 			  if (_M_need & _ChronoParts::_TimeOfDay)
   3520 			    __err |= ios_base::failbit;
   3521 			  break;
   3522 			}
   3523 		    }
   3524 		  __parts |= _ChronoParts::_TimeOfDay;
   3525 		  break;
   3526 
   3527 		case 'p': // Locale's AM/PM designation for 12-hour clock.
   3528 		  if (__mod || __num)
   3529 		    __err |= ios_base::failbit;
   3530 		  else
   3531 		    {
   3532 		      // Can't use std::time_get here as it can't parse %p
   3533 		      // in isolation without %I. This might be faster anyway.
   3534 		      const _CharT* __ampms[2];
   3535 		      __tmpunct._M_am_pm(__ampms);
   3536 		      int __n = 0, __which = 3;
   3537 		      while (__which != 0)
   3538 			{
   3539 			  auto __i = __is.peek();
   3540 			  if (_Traits::eq_int_type(__i, _Traits::eof()))
   3541 			    {
   3542 			      __err |= ios_base::eofbit | ios_base::failbit;
   3543 			      break;
   3544 			    }
   3545 			  __i = std::toupper(_Traits::to_char_type(__i), __loc);
   3546 			  if (__which & 1)
   3547 			    {
   3548 			      if (__i != std::toupper(__ampms[0][__n], __loc))
   3549 				__which ^= 1;
   3550 			      else if (__ampms[0][__n + 1] == _CharT())
   3551 				{
   3552 				  __which = 1;
   3553 				  (void) __is.get();
   3554 				  break;
   3555 				}
   3556 			    }
   3557 			  if (__which & 2)
   3558 			    {
   3559 			      if (__i != std::toupper(__ampms[1][__n], __loc))
   3560 				__which ^= 2;
   3561 			      else if (__ampms[1][__n + 1] == _CharT())
   3562 				{
   3563 				  __which = 2;
   3564 				  (void) __is.get();
   3565 				  break;
   3566 				}
   3567 			    }
   3568 			  if (__which)
   3569 			    (void) __is.get();
   3570 			  ++__n;
   3571 			}
   3572 		      if (__which == 0 || __which == 3)
   3573 			__err |= ios_base::failbit;
   3574 		      else
   3575 			__ampm = __which;
   3576 		    }
   3577 		  break;
   3578 
   3579 		case 'r': // Locale's 12-hour time.
   3580 		  if (__mod || __num)
   3581 		    __err |= ios_base::failbit;
   3582 		  else
   3583 		    {
   3584 		      struct tm __tm{};
   3585 		      __tmget.get(__is, {}, __is, __err, &__tm,
   3586 				  __fmt - 2, __fmt);
   3587 		      if (!__is_failed(__err))
   3588 			{
   3589 			  __h = hours(__tm.tm_hour);
   3590 			  __min = minutes(__tm.tm_min);
   3591 			  __s = seconds(__tm.tm_sec);
   3592 			}
   3593 		    }
   3594 		  __parts |= _ChronoParts::_TimeOfDay;
   3595 		  break;
   3596 
   3597 		case 'R': // %H:%M
   3598 		case 'T': // %H:%M:%S
   3599 		  if (__mod || __num) [[unlikely]]
   3600 		    {
   3601 		      __err |= ios_base::failbit;
   3602 		      break;
   3603 		    }
   3604 		  else
   3605 		    {
   3606 		      auto __val = __read_unsigned(2);
   3607 		      if (__val == -1 || __val > 23) [[unlikely]]
   3608 			{
   3609 			  if (_M_need & _ChronoParts::_TimeOfDay)
   3610 			    __err |= ios_base::failbit;
   3611 			  break;
   3612 			}
   3613 		      if (!__read_chr(':')) [[unlikely]]
   3614 			break;
   3615 		      __h = hours(__val);
   3616 
   3617 		      __val = __read_unsigned(2);
   3618 		      if (__val == -1 || __val > 60) [[unlikely]]
   3619 			{
   3620 			  if (_M_need & _ChronoParts::_TimeOfDay)
   3621 			    __err |= ios_base::failbit;
   3622 			  break;
   3623 			}
   3624 		      __min = minutes(__val);
   3625 
   3626 		      if (__c == 'R')
   3627 			{
   3628 			  __parts |= _ChronoParts::_TimeOfDay;
   3629 			  break;
   3630 			}
   3631 		      else if (!__read_chr(':')) [[unlikely]]
   3632 			break;
   3633 		    }
   3634 		  [[fallthrough]];
   3635 
   3636 		case 'S': // Seconds
   3637 		  if (__mod == 'E') [[unlikely]]
   3638 		    __err |= ios_base::failbit;
   3639 		  else if (__mod == 'O')
   3640 		    {
   3641 		      struct tm __tm{};
   3642 		      __tmget.get(__is, {}, __is, __err, &__tm,
   3643 				  __fmt - 3, __fmt);
   3644 		      if (!__is_failed(__err))
   3645 			__s = seconds(__tm.tm_sec);
   3646 		    }
   3647 		  else if constexpr (_Duration::period::den == 1
   3648 				       && !__is_floating)
   3649 		    {
   3650 		      auto __val = __read_unsigned(__num ? __num : 2);
   3651 		      if (0 <= __val && __val <= 59) [[likely]]
   3652 			__s = seconds(__val);
   3653 		      else
   3654 			{
   3655 			  if (_M_need & _ChronoParts::_TimeOfDay)
   3656 			    __err |= ios_base::failbit;
   3657 			  break;
   3658 			}
   3659 		    }
   3660 		  else // Read fractional seconds
   3661 		    {
   3662 		      basic_stringstream<_CharT> __buf;
   3663 		      auto __digit = _S_try_read_digit(__is, __err);
   3664 		      if (__digit != -1)
   3665 			{
   3666 			  __buf.put(_CharT('0') + __digit);
   3667 			  __digit = _S_try_read_digit(__is, __err);
   3668 			  if (__digit != -1)
   3669 			    __buf.put(_CharT('0') + __digit);
   3670 			}
   3671 
   3672 		      auto __i = __is.peek();
   3673 		      if (_Traits::eq_int_type(__i, _Traits::eof()))
   3674 			__err |= ios_base::eofbit;
   3675 		      else
   3676 			{
   3677 			  _CharT __dp = '.';
   3678 			  if (__loc != locale::classic())
   3679 			    {
   3680 			      auto& __np = use_facet<numpunct<_CharT>>(__loc);
   3681 			      __dp = __np.decimal_point();
   3682 			    }
   3683 			  _CharT __c = _Traits::to_char_type(__i);
   3684 			  if (__c == __dp)
   3685 			    {
   3686 			      (void) __is.get();
   3687 			      __buf.put('.');
   3688 			      int __prec
   3689 				= hh_mm_ss<_Duration>::fractional_width;
   3690 			      do
   3691 				{
   3692 				  __digit = _S_try_read_digit(__is, __err);
   3693 				  if (__digit != -1)
   3694 				    __buf.put(_CharT('0') + __digit);
   3695 				  else
   3696 				    break;
   3697 				}
   3698 			      while (--__prec);
   3699 			    }
   3700 			}
   3701 
   3702 		      if (!__is_failed(__err)) [[likely]]
   3703 			{
   3704 			  long double __val{};
   3705 #if __cpp_lib_to_chars
   3706 			  string __str = std::move(__buf).str();
   3707 			  auto __first = __str.data();
   3708 			  auto __last = __first + __str.size();
   3709 			  using enum chars_format;
   3710 			  auto [ptr, ec] = std::from_chars(__first, __last,
   3711 							   __val, fixed);
   3712 			  if ((bool)ec || ptr != __last) [[unlikely]]
   3713 			    __err |= ios_base::failbit;
   3714 			  else
   3715 #else
   3716 			  if (__buf >> __val)
   3717 #endif
   3718 			    {
   3719 			      duration<long double> __fs(__val);
   3720 			      if constexpr (__is_floating)
   3721 				__s = __fs;
   3722 			      else
   3723 				__s = chrono::round<_Duration>(__fs);
   3724 			    }
   3725 			}
   3726 		    }
   3727 		  __parts |= _ChronoParts::_TimeOfDay;
   3728 		  break;
   3729 
   3730 		case 'u': // ISO weekday (1-7)
   3731 		case 'w': // Weekday (0-6)
   3732 		  if (__mod == 'E') [[unlikely]]
   3733 		    __err |= ios_base::failbit;
   3734 		  else if (__mod == 'O')
   3735 		    {
   3736 		      if (__c == 'w')
   3737 			{
   3738 			  struct tm __tm{};
   3739 			  __tmget.get(__is, {}, __is, __err, &__tm,
   3740 				      __fmt - 3, __fmt);
   3741 			  if (!__is_failed(__err))
   3742 			    __wday = weekday(__tm.tm_wday);
   3743 			}
   3744 		      else
   3745 			__err |= ios_base::failbit;
   3746 		    }
   3747 		  else
   3748 		    {
   3749 		      const int __lo = __c == 'u' ? 1 : 0;
   3750 		      const int __hi = __lo + 6;
   3751 		      auto __val = __read_unsigned(__num ? __num : 1);
   3752 		      if (__lo <= __val && __val <= __hi)
   3753 			__wday = weekday(__val);
   3754 		      else
   3755 			{
   3756 			  __wday = __bad_wday;
   3757 			  break;
   3758 			}
   3759 		    }
   3760 		  __parts |= _ChronoParts::_Weekday;
   3761 		  break;
   3762 
   3763 		case 'U': // Week number of the year (from first Sunday).
   3764 		case 'V': // ISO week-based week number.
   3765 		case 'W': // Week number of the year (from first Monday).
   3766 		  if (__mod == 'E') [[unlikely]]
   3767 		    __err |= ios_base::failbit;
   3768 		  else if (__mod == 'O')
   3769 		    {
   3770 		      if (__c == 'V') [[unlikely]]
   3771 			__err |= ios_base::failbit;
   3772 		      else
   3773 			{
   3774 			  // TODO nl_langinfo_l(ALT_DIGITS) ?
   3775 			  // Not implementable using std::time_get.
   3776 			}
   3777 		    }
   3778 		  else
   3779 		    {
   3780 		      const int __lo = __c == 'V' ? 1 : 0;
   3781 		      const int __hi = 53;
   3782 		      auto __val = __read_unsigned(__num ? __num : 2);
   3783 		      if (__lo <= __val && __val <= __hi)
   3784 			{
   3785 			  switch (__c)
   3786 			  {
   3787 			    case 'U':
   3788 			      __sunday_wk = __val;
   3789 			      break;
   3790 			    case 'V':
   3791 			      __iso_wk = __val;
   3792 			      break;
   3793 			    case 'W':
   3794 			      __monday_wk = __val;
   3795 			      break;
   3796 			  }
   3797 			}
   3798 		      else
   3799 			__iso_wk = __sunday_wk = __monday_wk = -1;
   3800 		    }
   3801 		  // N.B. do not alter __parts here, done after loop.
   3802 		  break;
   3803 
   3804 		case 'x': // Locale's date representation.
   3805 		  if (__mod == 'O' || __num) [[unlikely]]
   3806 		    __err |= ios_base::failbit;
   3807 		  else
   3808 		    {
   3809 		      struct tm __tm{};
   3810 		      __tmget.get(__is, {}, __is, __err, &__tm,
   3811 				  __fmt - 2 - (__mod == 'E'), __fmt);
   3812 		      if (!__is_failed(__err))
   3813 			{
   3814 			  __y = year(__tm.tm_year + 1900);
   3815 			  __m = month(__tm.tm_mon + 1);
   3816 			  __d = day(__tm.tm_mday);
   3817 			}
   3818 		    }
   3819 		  __parts |= _ChronoParts::_Date;
   3820 		  break;
   3821 
   3822 		case 'X': // Locale's time representation.
   3823 		  if (__mod == 'O' || __num) [[unlikely]]
   3824 		    __err |= ios_base::failbit;
   3825 		  else
   3826 		    {
   3827 		      struct tm __tm{};
   3828 		      __tmget.get(__is, {}, __is, __err, &__tm,
   3829 				  __fmt - 2 - (__mod == 'E'), __fmt);
   3830 		      if (!__is_failed(__err))
   3831 			{
   3832 			  __h = hours(__tm.tm_hour);
   3833 			  __min = minutes(__tm.tm_min);
   3834 			  __s = seconds(__tm.tm_sec);
   3835 			}
   3836 		    }
   3837 		  __parts |= _ChronoParts::_TimeOfDay;
   3838 		  break;
   3839 
   3840 		case 'y': // Last two digits of year.
   3841 		  if (__mod) [[unlikely]]
   3842 		    {
   3843 		      struct tm __tm{};
   3844 		      __tmget.get(__is, {}, __is, __err, &__tm,
   3845 				  __fmt - 3, __fmt);
   3846 		      if (!__is_failed(__err))
   3847 			{
   3848 			  int __cent = __tm.tm_year < 2000 ? 1900 : 2000;
   3849 			  __yy = year(__tm.tm_year - __cent);
   3850 			  if (__century == -1) // No %C has been parsed yet.
   3851 			    __century = __cent;
   3852 			}
   3853 		    }
   3854 		  else
   3855 		    {
   3856 		      auto __val = __read_unsigned(__num ? __num : 2);
   3857 		      if (__val >= 0 && __val <= 99)
   3858 			{
   3859 			  __yy = year(__val);
   3860 			  if (__century == -1) // No %C has been parsed yet.
   3861 			    __century = __val < 69 ? 2000 : 1900;
   3862 			}
   3863 		      else
   3864 			__y = __yy = __iso_yy = __iso_y = __bad_y;
   3865 		    }
   3866 		  __parts |= _ChronoParts::_Year;
   3867 		  break;
   3868 
   3869 		case 'Y': // Year
   3870 		  if (__mod == 'O') [[unlikely]]
   3871 		    __err |= ios_base::failbit;
   3872 		  else if (__mod == 'E')
   3873 		    {
   3874 		      struct tm __tm{};
   3875 		      __tmget.get(__is, {}, __is, __err, &__tm,
   3876 				  __fmt - 3, __fmt);
   3877 		      if (!__is_failed(__err))
   3878 			__y = year(__tm.tm_year);
   3879 		    }
   3880 		  else
   3881 		    {
   3882 		      auto __val = __read_unsigned(__num ? __num : 4);
   3883 		      if (!__is_failed(__err))
   3884 			__y = year(__val);
   3885 		    }
   3886 		  __parts |= _ChronoParts::_Year;
   3887 		  break;
   3888 
   3889 		case 'z':
   3890 		  if (__num) [[unlikely]]
   3891 		    __err |= ios_base::failbit;
   3892 		  else
   3893 		    {
   3894 		      // For %Ez and %Oz read [+|-][h]h[:mm].
   3895 		      // For %z read [+|-]hh[mm].
   3896 
   3897 		      auto __i = __is.peek();
   3898 		      if (_Traits::eq_int_type(__i, _Traits::eof()))
   3899 			{
   3900 			  __err |= ios_base::eofbit | ios_base::failbit;
   3901 			  break;
   3902 			}
   3903 		      _CharT __ic = _Traits::to_char_type(__i);
   3904 		      const bool __neg = __ic == _CharT('-');
   3905 		      if (__ic == _CharT('-') || __ic == _CharT('+'))
   3906 			(void) __is.get();
   3907 
   3908 		      int_least32_t __hh;
   3909 		      if (__mod)
   3910 			{
   3911 			  // Read h[h]
   3912 			  __hh = __read_unsigned(2);
   3913 			}
   3914 		      else
   3915 			{
   3916 			  // Read hh
   3917 			  __hh = 10 * _S_try_read_digit(__is, __err);
   3918 			  __hh += _S_try_read_digit(__is, __err);
   3919 			}
   3920 
   3921 		      if (__is_failed(__err))
   3922 			break;
   3923 
   3924 		      __i = __is.peek();
   3925 		      if (_Traits::eq_int_type(__i, _Traits::eof()))
   3926 			{
   3927 			  __err |= ios_base::eofbit;
   3928 			  __tz_offset = minutes(__hh * (__neg ? -60 : 60));
   3929 			  break;
   3930 			}
   3931 		      __ic = _Traits::to_char_type(__i);
   3932 
   3933 		      bool __read_mm = false;
   3934 		      if (__mod)
   3935 			{
   3936 			  if (__ic == _GLIBCXX_WIDEN(":")[0])
   3937 			    {
   3938 			      // Read [:mm] part.
   3939 			      (void) __is.get();
   3940 			      __read_mm = true;
   3941 			    }
   3942 			}
   3943 		      else if (_CharT('0') <= __ic && __ic <= _CharT('9'))
   3944 			{
   3945 			  // Read [mm] part.
   3946 			  __read_mm = true;
   3947 			}
   3948 
   3949 		      int_least32_t __mm = 0;
   3950 		      if (__read_mm)
   3951 			{
   3952 			  __mm = 10 * _S_try_read_digit(__is, __err);
   3953 			  __mm += _S_try_read_digit(__is, __err);
   3954 			}
   3955 
   3956 		      if (!__is_failed(__err))
   3957 			{
   3958 			  auto __z = __hh * 60 + __mm;
   3959 			  __tz_offset = minutes(__neg ? -__z : __z);
   3960 			}
   3961 		    }
   3962 		  break;
   3963 
   3964 		case 'Z':
   3965 		  if (__mod || __num) [[unlikely]]
   3966 		    __err |= ios_base::failbit;
   3967 		  else
   3968 		    {
   3969 		      basic_string_view<_CharT> __x = _GLIBCXX_WIDEN("_/-+");
   3970 		      __tz_abbr.clear();
   3971 		      while (true)
   3972 			{
   3973 			  auto __i = __is.peek();
   3974 			  if (!_Traits::eq_int_type(__i, _Traits::eof()))
   3975 			    {
   3976 			      _CharT __a = _Traits::to_char_type(__i);
   3977 			      if (std::isalnum(__a, __loc)
   3978 				    || __x.find(__a) != __x.npos)
   3979 				{
   3980 				  __tz_abbr.push_back(__a);
   3981 				  (void) __is.get();
   3982 				  continue;
   3983 				}
   3984 			    }
   3985 			  else
   3986 			    __err |= ios_base::eofbit;
   3987 			  break;
   3988 			}
   3989 		      if (__tz_abbr.empty())
   3990 			__err |= ios_base::failbit;
   3991 		    }
   3992 		  break;
   3993 
   3994 		case 'n': // Exactly one whitespace character.
   3995 		  if (__mod || __num) [[unlikely]]
   3996 		    __err |= ios_base::failbit;
   3997 		  else
   3998 		    {
   3999 		      _CharT __i = __is.peek();
   4000 		      if (_Traits::eq_int_type(__i, _Traits::eof()))
   4001 			__err |= ios_base::eofbit | ios_base::failbit;
   4002 		      else if (std::isspace(_Traits::to_char_type(__i), __loc))
   4003 			(void) __is.get();
   4004 		      else
   4005 			__err |= ios_base::failbit;
   4006 		    }
   4007 		  break;
   4008 
   4009 		case 't': // Zero or one whitespace characters.
   4010 		  if (__mod || __num) [[unlikely]]
   4011 		    __err |= ios_base::failbit;
   4012 		  else
   4013 		    {
   4014 		      _CharT __i = __is.peek();
   4015 		      if (_Traits::eq_int_type(__i, _Traits::eof()))
   4016 			__err |= ios_base::eofbit;
   4017 		      else if (std::isspace(_Traits::to_char_type(__i), __loc))
   4018 			(void) __is.get();
   4019 		    }
   4020 		  break;
   4021 
   4022 		case '%': // A % character.
   4023 		  if (__mod || __num) [[unlikely]]
   4024 		    __err |= ios_base::failbit;
   4025 		  else
   4026 		    __read_chr('%');
   4027 		  break;
   4028 
   4029 		case 'O': // Modifiers
   4030 		case 'E':
   4031 		  if (__mod || __num) [[unlikely]]
   4032 		    {
   4033 		      __err |= ios_base::failbit;
   4034 		      break;
   4035 		    }
   4036 		  __mod = __c;
   4037 		  continue;
   4038 
   4039 		default:
   4040 		  if (_CharT('1') <= __c && __c <= _CharT('9'))
   4041 		    {
   4042 		      if (!__mod) [[likely]]
   4043 			{
   4044 			  // %Nx - extract positive decimal integer N
   4045 			  auto __end = __fmt + _Traits::length(__fmt);
   4046 			  auto [__v, __ptr]
   4047 			    = __format::__parse_integer(__fmt - 1, __end);
   4048 			  if (__ptr) [[likely]]
   4049 			    {
   4050 			      __num = __v;
   4051 			      __fmt = __ptr;
   4052 			      continue;
   4053 			    }
   4054 			}
   4055 		    }
   4056 		  __err |= ios_base::failbit;
   4057 		}
   4058 
   4059 	      if (__is_failed(__err)) [[unlikely]]
   4060 		break;
   4061 
   4062 	      __is_flag = false;
   4063 	      __num = 0;
   4064 	      __mod = _CharT();
   4065 	    }
   4066 
   4067 	  if (__century >= 0)
   4068 	    {
   4069 	      if (__yy != __bad_y && __y == __bad_y)
   4070 		__y = years(__century) + __yy; // Use %y instead of %Y
   4071 	      if (__iso_yy != __bad_y && __iso_y == __bad_y)
   4072 		__iso_y = years(__century) + __iso_yy; // Use %g instead of %G
   4073 	    }
   4074 
   4075 	  bool __can_use_doy = false;
   4076 	  bool __can_use_iso_wk = false;
   4077 	  bool __can_use_sun_wk = false;
   4078 	  bool __can_use_mon_wk = false;
   4079 
   4080 	  // A year + day-of-year can be converted to a full date.
   4081 	  if (__y != __bad_y && __dayofyear >= 0)
   4082 	    {
   4083 	      __can_use_doy = true;
   4084 	      __parts |= _ChronoParts::_Date;
   4085 	    }
   4086 	  else if (__y != __bad_y && __wday != __bad_wday && __sunday_wk >= 0)
   4087 	    {
   4088 	      __can_use_sun_wk = true;
   4089 	      __parts |= _ChronoParts::_Date;
   4090 	    }
   4091 	  else if (__y != __bad_y && __wday != __bad_wday && __monday_wk >= 0)
   4092 	    {
   4093 	      __can_use_mon_wk = true;
   4094 	      __parts |= _ChronoParts::_Date;
   4095 	    }
   4096 	  else if (__iso_y != __bad_y && __wday != __bad_wday && __iso_wk > 0)
   4097 	    {
   4098 	      // An ISO week date can be converted to a full date.
   4099 	      __can_use_iso_wk = true;
   4100 	      __parts |= _ChronoParts::_Date;
   4101 	    }
   4102 
   4103 	  if (__is_failed(__err)) [[unlikely]]
   4104 	    ; // Don't bother doing any more work.
   4105 	  else if (__is_flag) [[unlikely]] // incomplete format flag
   4106 	    __err |= ios_base::failbit;
   4107 	  else if ((_M_need & __parts) == _M_need) [[likely]]
   4108 	    {
   4109 	      // We try to avoid calculating _M_sys_days and _M_ymd unless
   4110 	      // necessary, because converting sys_days to year_month_day
   4111 	      // (or vice versa) requires non-trivial calculations.
   4112 	      // If we have y/m/d values then use them to populate _M_ymd
   4113 	      // and only convert it to _M_sys_days if the caller needs that.
   4114 	      // But if we don't have y/m/d and need to calculate the date
   4115 	      // from the day-of-year or a week+weekday then we set _M_sys_days
   4116 	      // and only convert it to _M_ymd if the caller needs that.
   4117 
   4118 	      // We do more error checking here, but only for the fields that
   4119 	      // we actually need to use. For example, we will not diagnose
   4120 	      // an invalid dayofyear==366 for non-leap years unless actually
   4121 	      // using __dayofyear. This should mean we never produce invalid
   4122 	      // results, but it means not all invalid inputs are diagnosed,
   4123 	      // e.g. "2023-01-01 366" >> "%F %j" ignores the invalid 366.
   4124 	      // We also do not diagnose inconsistent values for the same
   4125 	      // field, e.g. "2021 2022 2023" >> "%C%y %Y %Y" just uses 2023.
   4126 
   4127 	      // Whether the caller wants _M_wd.
   4128 	      // The _Weekday bit is only set for chrono::weekday.
   4129 	      const bool __need_wday = _M_need & _ChronoParts::_Weekday;
   4130 
   4131 	      // Whether the caller wants _M_sys_days and _M_time.
   4132 	      // Only true for durations and time_points.
   4133 	      const bool __need_time = _M_need & _ChronoParts::_TimeOfDay;
   4134 
   4135 	      if (__need_wday && __wday != __bad_wday)
   4136 		_M_wd = __wday; // Caller only wants a weekday and we have one.
   4137 	      else if (_M_need & _ChronoParts::_Date) // subsumes __need_wday
   4138 		{
   4139 		  // Whether the caller wants _M_ymd.
   4140 		  // True for chrono::year etc., false for time_points.
   4141 		  const bool __need_ymd = !__need_wday && !__need_time;
   4142 
   4143 		  if ((_M_need & _ChronoParts::_Year && __y == __bad_y)
   4144 		     || (_M_need & _ChronoParts::_Month && __m == __bad_mon)
   4145 		     || (_M_need & _ChronoParts::_Day && __d == __bad_day))
   4146 		    {
   4147 		      // Missing at least one of y/m/d so calculate sys_days
   4148 		      // from the other data we have available.
   4149 
   4150 		      if (__can_use_doy)
   4151 			{
   4152 			  if ((0 < __dayofyear && __dayofyear <= 365)
   4153 				|| (__dayofyear == 366 && __y.is_leap()))
   4154 			    [[likely]]
   4155 			    {
   4156 			      _M_sys_days = sys_days(__y/January/1)
   4157 					      + days(__dayofyear - 1);
   4158 			      if (__need_ymd)
   4159 				_M_ymd = year_month_day(_M_sys_days);
   4160 			    }
   4161 			  else
   4162 			    __err |= ios_base::failbit;
   4163 			}
   4164 		      else if (__can_use_iso_wk)
   4165 			{
   4166 			  // Calculate y/m/d from ISO week date.
   4167 
   4168 			  if (__iso_wk == 53)
   4169 			    {
   4170 			      // A year has 53 weeks iff Jan 1st is a Thursday
   4171 			      // or Jan 1 is a Wednesday and it's a leap year.
   4172 			      const sys_days __jan4(__iso_y/January/4);
   4173 			      weekday __wd1(__jan4 - days(3));
   4174 			      if (__wd1 != Thursday)
   4175 				if (__wd1 != Wednesday || !__iso_y.is_leap())
   4176 				  __err |= ios_base::failbit;
   4177 			    }
   4178 
   4179 			  if (!__is_failed(__err)) [[likely]]
   4180 			    {
   4181 			      // First Thursday is always in week one:
   4182 			      sys_days __w(Thursday[1]/January/__iso_y);
   4183 			      // First day of week-based year:
   4184 			      __w -= Thursday - Monday;
   4185 			      __w += days(weeks(__iso_wk - 1));
   4186 			      __w += __wday - Monday;
   4187 			      _M_sys_days = __w;
   4188 
   4189 			      if (__need_ymd)
   4190 				_M_ymd = year_month_day(_M_sys_days);
   4191 			    }
   4192 			}
   4193 		      else if (__can_use_sun_wk)
   4194 			{
   4195 			  // Calculate y/m/d from week number + weekday.
   4196 			  sys_days __wk1(__y/January/Sunday[1]);
   4197 			  _M_sys_days = __wk1 + weeks(__sunday_wk - 1)
   4198 					+ days(__wday.c_encoding());
   4199 			  _M_ymd = year_month_day(_M_sys_days);
   4200 			  if (_M_ymd.year() != __y) [[unlikely]]
   4201 			    __err |= ios_base::failbit;
   4202 			}
   4203 		      else if (__can_use_mon_wk)
   4204 			{
   4205 			  // Calculate y/m/d from week number + weekday.
   4206 			  sys_days __wk1(__y/January/Monday[1]);
   4207 			  _M_sys_days = __wk1 + weeks(__monday_wk - 1)
   4208 					+ days(__wday.c_encoding() - 1);
   4209 			  _M_ymd = year_month_day(_M_sys_days);
   4210 			  if (_M_ymd.year() != __y) [[unlikely]]
   4211 			    __err |= ios_base::failbit;
   4212 			}
   4213 		      else // Should not be able to get here.
   4214 			__err |= ios_base::failbit;
   4215 		    }
   4216 		  else
   4217 		    {
   4218 		      // We know that all fields the caller needs are present,
   4219 		      // but check that their values are in range.
   4220 		      // Make unwanted fields valid so that _M_ymd.ok() is true.
   4221 
   4222 		      if (_M_need & _ChronoParts::_Year)
   4223 			{
   4224 			  if (!__y.ok()) [[unlikely]]
   4225 			    __err |= ios_base::failbit;
   4226 			}
   4227 		      else if (__y == __bad_y)
   4228 			__y = 1972y; // Leap year so that Feb 29 is valid.
   4229 
   4230 		      if (_M_need & _ChronoParts::_Month)
   4231 			{
   4232 			  if (!__m.ok()) [[unlikely]]
   4233 			    __err |= ios_base::failbit;
   4234 			}
   4235 		      else if (__m == __bad_mon)
   4236 			__m = January;
   4237 
   4238 		      if (_M_need & _ChronoParts::_Day)
   4239 			{
   4240 			  if (__d < day(1) || __d > (__y/__m/last).day())
   4241 			    __err |= ios_base::failbit;
   4242 			}
   4243 		      else if (__d == __bad_day)
   4244 			__d = 1d;
   4245 
   4246 		      if (year_month_day __ymd(__y, __m, __d); __ymd.ok())
   4247 			{
   4248 			  _M_ymd = __ymd;
   4249 			  if (__need_wday || __need_time)
   4250 			    _M_sys_days = sys_days(_M_ymd);
   4251 			}
   4252 		      else [[unlikely]]
   4253 			__err |= ios_base::failbit;
   4254 		    }
   4255 
   4256 		  if (__need_wday)
   4257 		    _M_wd = weekday(_M_sys_days);
   4258 		}
   4259 
   4260 	      // Need to set _M_time for both durations and time_points.
   4261 	      if (__need_time)
   4262 		{
   4263 		  if (__h == __bad_h && __h12 != __bad_h)
   4264 		    {
   4265 		      if (__ampm == 1)
   4266 			__h = __h12 == hours(12) ? hours(0) : __h12;
   4267 		      else if (__ampm == 2)
   4268 			__h = __h12 == hours(12) ? __h12 : __h12 + hours(12);
   4269 		      else [[unlikely]]
   4270 			__err |= ios_base::failbit;
   4271 		    }
   4272 
   4273 		  auto __t = _M_time.zero();
   4274 		  bool __ok = false;
   4275 
   4276 		  if (__h != __bad_h)
   4277 		    {
   4278 		      __ok = true;
   4279 		      __t += __h;
   4280 		    }
   4281 
   4282 		  if (__min != __bad_min)
   4283 		    {
   4284 		      __ok = true;
   4285 		      __t += __min;
   4286 		    }
   4287 
   4288 		  if (__s != __bad_sec)
   4289 		    {
   4290 		      __ok = true;
   4291 		      __t += __s;
   4292 		      _M_is_leap_second = __s >= seconds(60);
   4293 		    }
   4294 
   4295 		  if (__ok)
   4296 		    _M_time = __t;
   4297 		  else
   4298 		    __err |= ios_base::failbit;
   4299 		}
   4300 
   4301 	      if (!__is_failed(__err)) [[likely]]
   4302 		{
   4303 		  if (__offset && __tz_offset != __bad_min)
   4304 		    *__offset = __tz_offset;
   4305 		  if (__abbrev && !__tz_abbr.empty())
   4306 		    *__abbrev = std::move(__tz_abbr);
   4307 		}
   4308 	    }
   4309 	  else
   4310 	    __err |= ios_base::failbit;
   4311 	}
   4312       if (__err)
   4313 	__is.setstate(__err);
   4314       return __is;
   4315     }
   4316   /// @endcond
   4317 #undef _GLIBCXX_WIDEN
   4318 
   4319   /// @} group chrono
   4320 } // namespace chrono
   4321 
   4322 _GLIBCXX_END_NAMESPACE_VERSION
   4323 } // namespace std
   4324 
   4325 #endif // C++20
   4326 
   4327 #endif //_GLIBCXX_CHRONO_IO_H
   4328