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