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