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