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