libstdc++
chrono_io.h
Go to the documentation of this file.
1 // <chrono> Formatting -*- C++ -*-
2 
3 // Copyright The GNU Toolchain Authors.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file include/bits/chrono_io.h
26  * This is an internal header file, included by other library headers.
27  * Do not attempt to use it directly. @headername{chrono}
28  */
29 
30 #ifndef _GLIBCXX_CHRONO_IO_H
31 #define _GLIBCXX_CHRONO_IO_H 1
32 
33 #pragma GCC system_header
34 
35 #if __cplusplus >= 202002L
36 
37 #include <sstream> // ostringstream
38 #include <iomanip> // setw, setfill
39 #include <format>
40 
42 
43 namespace std _GLIBCXX_VISIBILITY(default)
44 {
45 _GLIBCXX_BEGIN_NAMESPACE_VERSION
46 
47 namespace chrono
48 {
49 /// @addtogroup chrono
50 /// @{
51 
52 /// @cond undocumented
53 namespace __detail
54 {
55  // STATICALLY-WIDEN, see C++20 [time.general]
56  // It doesn't matter for format strings (which can only be char or wchar_t)
57  // but this returns the narrow string for anything that isn't wchar_t. This
58  // is done because const char* can be inserted into any ostream type, and
59  // will be widened at runtime if necessary.
60  template<typename _CharT>
61  consteval auto
62  _Widen(const char* __narrow, const wchar_t* __wide)
63  {
64  if constexpr (is_same_v<_CharT, wchar_t>)
65  return __wide;
66  else
67  return __narrow;
68  }
69 #define _GLIBCXX_WIDEN_(C, S) ::std::chrono::__detail::_Widen<C>(S, L##S)
70 #define _GLIBCXX_WIDEN(S) _GLIBCXX_WIDEN_(_CharT, S)
71 
72  template<typename _Period, typename _CharT>
74  __units_suffix() noexcept
75  {
76  // The standard say these are all narrow strings, which would need to
77  // be widened at run-time when inserted into a wide stream. We use
78  // STATICALLY-WIDEN to widen at compile-time.
79 #define _GLIBCXX_UNITS_SUFFIX(period, suffix) \
80  if constexpr (is_same_v<_Period, period>) \
81  return _GLIBCXX_WIDEN(suffix); \
82  else
83 
84  _GLIBCXX_UNITS_SUFFIX(atto, "as")
85  _GLIBCXX_UNITS_SUFFIX(femto, "fs")
86  _GLIBCXX_UNITS_SUFFIX(pico, "ps")
87  _GLIBCXX_UNITS_SUFFIX(nano, "ns")
88  _GLIBCXX_UNITS_SUFFIX(milli, "ms")
89 #if _GLIBCXX_USE_ALT_MICROSECONDS_SUFFIX
90  // Deciding this at compile-time is wrong, maybe use nl_langinfo(CODESET)
91  // to check runtime environment and return u8"\u00b5s", "\xb5s", or "us".
92  _GLIBCXX_UNITS_SUFFIX(micro, "\u00b5s")
93 #else
94  _GLIBCXX_UNITS_SUFFIX(micro, "us")
95 #endif
96  _GLIBCXX_UNITS_SUFFIX(centi, "cs")
97  _GLIBCXX_UNITS_SUFFIX(deci, "ds")
98  _GLIBCXX_UNITS_SUFFIX(ratio<1>, "s")
99  _GLIBCXX_UNITS_SUFFIX(deca, "das")
100  _GLIBCXX_UNITS_SUFFIX(hecto, "hs")
101  _GLIBCXX_UNITS_SUFFIX(kilo, "ks")
102  _GLIBCXX_UNITS_SUFFIX(mega, "Ms")
103  _GLIBCXX_UNITS_SUFFIX(giga, "Gs")
104  _GLIBCXX_UNITS_SUFFIX(tera, "Ts")
105  _GLIBCXX_UNITS_SUFFIX(tera, "Ts")
106  _GLIBCXX_UNITS_SUFFIX(peta, "Ps")
107  _GLIBCXX_UNITS_SUFFIX(exa, "Es")
108  _GLIBCXX_UNITS_SUFFIX(ratio<60>, "min")
109  _GLIBCXX_UNITS_SUFFIX(ratio<3600>, "h")
110  _GLIBCXX_UNITS_SUFFIX(ratio<86400>, "d")
111 #undef _GLIBCXX_UNITS_SUFFIX
112  return {};
113  }
114 
115  template<typename _Period, typename _CharT, typename _Out>
116  inline _Out
117  __fmt_units_suffix(_Out __out) noexcept
118  {
119  if (auto __s = __detail::__units_suffix<_Period, _CharT>(); __s.size())
120  return __format::__write(std::move(__out), __s);
121  else if constexpr (_Period::den == 1)
122  return std::format_to(std::move(__out), _GLIBCXX_WIDEN("[{}]s"),
123  (uintmax_t)_Period::num);
124  else
125  return std::format_to(std::move(__out), _GLIBCXX_WIDEN("[{}/{}]s"),
126  (uintmax_t)_Period::num,
127  (uintmax_t)_Period::den);
128  }
129 } // namespace __detail
130 /// @endcond
131 
132  /** Write a `chrono::duration` to an ostream.
133  *
134  * @since C++20
135  */
136  template<typename _CharT, typename _Traits,
137  typename _Rep, typename _Period>
140  const duration<_Rep, _Period>& __d)
141  {
143  using period = typename _Period::type;
145  __s.flags(__os.flags());
146  __s.imbue(__os.getloc());
147  __s.precision(__os.precision());
148  __s << __d.count();
149  __detail::__fmt_units_suffix<period, _CharT>(_Out(__s));
150  __os << std::move(__s).str();
151  return __os;
152  }
153 
154 /// @cond undocumented
155 namespace __detail
156 {
157  // An unspecified type returned by `chrono::local_time_format`.
158  template<typename _Duration>
159  struct __local_time_fmt
160  {
161  local_time<_Duration> _M_time;
162  const string* _M_abbrev;
163  const seconds* _M_offset_sec;
164  };
165 
166  struct __local_fmt_t;
167 }
168 /// @endcond
169 
170  /** Return an object that asssociates timezone info with a local time.
171  *
172  * A `chrono::local_time` object has no timezone associated with it. This
173  * function creates an object that allows formatting a `local_time` as
174  * though it refers to a timezone with the given abbreviated name and
175  * offset from UTC.
176  *
177  * @since C++20
178  */
179  template<typename _Duration>
180  inline __detail::__local_time_fmt<_Duration>
182  const string* __abbrev = nullptr,
183  const seconds* __offset_sec = nullptr)
184  { return {__time, __abbrev, __offset_sec}; }
185 
186  /// @}
187 } // namespace chrono
188 
189 /// @cond undocumented
190 namespace __format
191 {
192  [[noreturn,__gnu__::__always_inline__]]
193  inline void
194  __no_timezone_available()
195  { __throw_format_error("format error: no timezone available for %Z or %z"); }
196 
197  [[noreturn,__gnu__::__always_inline__]]
198  inline void
199  __not_valid_for_duration()
200  { __throw_format_error("format error: chrono-format-spec not valid for "
201  "chrono::duration"); }
202 
203  [[noreturn,__gnu__::__always_inline__]]
204  inline void
205  __invalid_chrono_spec()
206  { __throw_format_error("format error: chrono-format-spec not valid for "
207  "argument type"); }
208 
209  template<typename _CharT>
210  struct _ChronoSpec : _Spec<_CharT>
211  {
212  basic_string_view<_CharT> _M_chrono_specs;
213  };
214 
215  // Represents the information provided by a chrono type.
216  // e.g. month_weekday has month and weekday but no year or time of day,
217  // hh_mm_ss has time of day but no date, sys_time is time_point+timezone.
218  enum _ChronoParts {
219  _Year = 1, _Month = 2, _Day = 4, _Weekday = 8, _TimeOfDay = 16,
220  _TimeZone = 32,
221  _Date = _Year | _Month | _Day | _Weekday,
222  _DateTime = _Date | _TimeOfDay,
223  _ZonedDateTime = _DateTime | _TimeZone,
224  _Duration = 128 // special case
225  };
226 
227  constexpr _ChronoParts
228  operator|(_ChronoParts __x, _ChronoParts __y)
229  { return static_cast<_ChronoParts>((int)__x | (int)__y); }
230 
231  // TODO rename this to chrono::__formatter? or chrono::__detail::__formatter?
232  template<typename _CharT>
233  struct __formatter_chrono
234  {
235  using __string_view = basic_string_view<_CharT>;
236  using __string = basic_string<_CharT>;
237 
238  template<typename _ParseContext>
239  constexpr typename _ParseContext::iterator
240  _M_parse(_ParseContext& __pc, _ChronoParts __parts)
241  {
242  auto __first = __pc.begin();
243  auto __last = __pc.end();
244 
245  _ChronoSpec<_CharT> __spec{};
246 
247  auto __finalize = [this, &__spec] {
248  _M_spec = __spec;
249  };
250 
251  auto __finished = [&] {
252  if (__first == __last || *__first == '}')
253  {
254  __finalize();
255  return true;
256  }
257  return false;
258  };
259 
260  if (__finished())
261  return __first;
262 
263  __first = __spec._M_parse_fill_and_align(__first, __last);
264  if (__finished())
265  return __first;
266 
267  __first = __spec._M_parse_width(__first, __last, __pc);
268  if (__finished())
269  return __first;
270 
271  if (__parts & _ChronoParts::_Duration)
272  {
273  __first = __spec._M_parse_precision(__first, __last, __pc);
274  if (__finished())
275  return __first;
276  }
277 
278  __first = __spec._M_parse_locale(__first, __last);
279  if (__finished())
280  return __first;
281 
282  // Everything up to the end of the string or the first '}' is a
283  // chrono-specs string. Check it is valid.
284  {
285  __string_view __str(__first, __last - __first);
286  auto __end = __str.find('}');
287  if (__end != __str.npos)
288  {
289  __str.remove_suffix(__str.length() - __end);
290  __last = __first + __end;
291  }
292  if (__str.find('{') != __str.npos)
293  __throw_format_error("chrono format error: '{' in chrono-specs");
294  }
295 
296  // Parse chrono-specs in [first,last), checking each conversion-spec
297  // against __parts (so fail for %Y if no year in parts).
298  // Save range in __spec._M_chrono_specs.
299 
300  const auto __chrono_specs = __first++; // Skip leading '%'
301  if (*__chrono_specs != '%')
302  __throw_format_error("chrono format error: no '%' at start of "
303  "chrono-specs");
304 
305  _CharT __mod{};
306  bool __conv = true;
307  int __needed = 0;
308 
309  while (__first != __last)
310  {
311  enum _Mods { _Mod_none, _Mod_E, _Mod_O, _Mod_E_O };
312  _Mods __allowed_mods = _Mod_none;
313 
314  _CharT __c = *__first++;
315  switch (__c)
316  {
317  case 'a':
318  case 'A':
319  __needed = _Weekday;
320  break;
321  case 'b':
322  case 'h':
323  case 'B':
324  __needed = _Month;
325  break;
326  case 'c':
327  __needed = _DateTime;
328  __allowed_mods = _Mod_E;
329  break;
330  case 'C':
331  __needed = _Year;
332  __allowed_mods = _Mod_E;
333  break;
334  case 'd':
335  case 'e':
336  __needed = _Day;
337  __allowed_mods = _Mod_O;
338  break;
339  case 'D':
340  case 'F':
341  __needed = _Date;
342  break;
343  case 'g':
344  case 'G':
345  __needed = _Date;
346  break;
347  case 'H':
348  case 'I':
349  __needed = _TimeOfDay;
350  __allowed_mods = _Mod_O;
351  break;
352  case 'j':
353  if (!(__parts & _Duration))
354  __needed = _Date;
355  break;
356  case 'm':
357  __needed = _Month;
358  __allowed_mods = _Mod_O;
359  break;
360  case 'M':
361  __needed = _TimeOfDay;
362  __allowed_mods = _Mod_O;
363  break;
364  case 'p':
365  case 'r':
366  case 'R':
367  case 'T':
368  __needed = _TimeOfDay;
369  break;
370  case 'q':
371  case 'Q':
372  __needed = _Duration;
373  break;
374  case 'S':
375  __needed = _TimeOfDay;
376  __allowed_mods = _Mod_O;
377  break;
378  case 'u':
379  case 'w':
380  __needed = _Weekday;
381  __allowed_mods = _Mod_O;
382  break;
383  case 'U':
384  case 'V':
385  case 'W':
386  __needed = _Date;
387  __allowed_mods = _Mod_O;
388  break;
389  case 'x':
390  __needed = _Date;
391  __allowed_mods = _Mod_E;
392  break;
393  case 'X':
394  __needed = _TimeOfDay;
395  __allowed_mods = _Mod_E;
396  break;
397  case 'y':
398  __needed = _Year;
399  __allowed_mods = _Mod_E_O;
400  break;
401  case 'Y':
402  __needed = _Year;
403  __allowed_mods = _Mod_E;
404  break;
405  case 'z':
406  __needed = _TimeZone;
407  __allowed_mods = _Mod_E_O;
408  break;
409  case 'Z':
410  __needed = _TimeZone;
411  break;
412  case 'n':
413  case 't':
414  case '%':
415  break;
416  case 'O':
417  case 'E':
418  if (__mod) [[unlikely]]
419  {
420  __allowed_mods = _Mod_none;
421  break;
422  }
423  __mod = __c;
424  continue;
425  default:
426  __throw_format_error("chrono format error: invalid "
427  " specifier in chrono-specs");
428  }
429 
430  if ((__mod == 'E' && !(__allowed_mods & _Mod_E))
431  || (__mod == 'O' && !(__allowed_mods & _Mod_O)))
432  __throw_format_error("chrono format error: invalid "
433  " modifier in chrono-specs");
434  __mod = _CharT();
435 
436  if ((__parts & __needed) != __needed)
437  __throw_format_error("chrono format error: format argument "
438  "does not contain the information "
439  "required by the chrono-specs");
440 
441  // Scan for next '%', ignoring literal-chars before it.
442  size_t __pos = __string_view(__first, __last - __first).find('%');
443  if (__pos == 0)
444  ++__first;
445  else
446  {
447  if (__pos == __string_view::npos)
448  {
449  __first = __last;
450  __conv = false;
451  }
452  else
453  __first += __pos + 1;
454  }
455  }
456 
457  // Check for a '%' conversion-spec without a type.
458  if (__conv || __mod != _CharT())
459  __throw_format_error("chrono format error: unescaped '%' in "
460  "chrono-specs");
461 
462  _M_spec = __spec;
463  _M_spec._M_chrono_specs
464  = __string_view(__chrono_specs, __first - __chrono_specs);
465 
466  return __first;
467  }
468 
469  // TODO this function template is instantiated for every different _Tp.
470  // Consider creating a polymorphic interface for calendar types so
471  // that we instantiate fewer different specializations. Similar to
472  // _Sink_iter for std::format. Replace each _S_year, _S_day etc. with
473  // member functions of that type.
474  template<typename _Tp, typename _FormatContext>
475  typename _FormatContext::iterator
476  _M_format(const _Tp& __t, _FormatContext& __fc,
477  bool __is_neg = false) const
478  {
479  auto __first = _M_spec._M_chrono_specs.begin();
480  const auto __last = _M_spec._M_chrono_specs.end();
481  if (__first == __last)
482  return _M_format_to_ostream(__t, __fc, __is_neg);
483 
484  _Sink_iter<_CharT> __out;
485  __format::_Str_sink<_CharT> __sink;
486  bool __write_direct = false;
487  if constexpr (is_same_v<typename _FormatContext::iterator,
488  _Sink_iter<_CharT>>)
489  {
490  if (_M_spec._M_width_kind == __format::_WP_none)
491  {
492  __out = __fc.out();
493  __write_direct = true;
494  }
495  else
496  __out = __sink.out();
497  }
498  else
499  __out = __sink.out();
500 
501  // formatter<duration> passes the correct value of __is_neg
502  // for durations but for hh_mm_ss we decide it here.
503  if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>)
504  __is_neg = __t.is_negative();
505 
506  auto __print_sign = [&__is_neg, &__out] {
507  if constexpr (chrono::__is_duration_v<_Tp>
508  || __is_specialization_of<_Tp, chrono::hh_mm_ss>)
509  if (__is_neg)
510  {
511  *__out++ = _S_plus_minus[1];
512  __is_neg = false;
513  }
514  return std::move(__out);
515  };
516 
517  // Characters to output for "%n", "%t" and "%%" specifiers.
518  constexpr const _CharT* __literals = _GLIBCXX_WIDEN("\n\t%");
519 
520  ++__first; // Skip leading '%' at start of chrono-specs.
521 
522  _CharT __mod{};
523  do
524  {
525  _CharT __c = *__first++;
526  switch (__c)
527  {
528  case 'a':
529  case 'A':
530  __out = _M_a_A(__t, std::move(__out), __fc, __c == 'A');
531  break;
532  case 'b':
533  case 'h':
534  case 'B':
535  __out = _M_b_B(__t, std::move(__out), __fc, __c == 'B');
536  break;
537  case 'c':
538  __out = _M_c(__t, std::move(__out), __fc, __mod == 'E');
539  break;
540  case 'C':
541  case 'y':
542  case 'Y':
543  __out = _M_C_y_Y(__t, std::move(__out), __fc, __c, __mod);
544  break;
545  case 'd':
546  case 'e':
547  __out = _M_d_e(__t, std::move(__out), __fc, __c, __mod == 'O');
548  break;
549  case 'D':
550  __out = _M_D(__t, std::move(__out), __fc);
551  break;
552  case 'F':
553  __out = _M_F(__t, std::move(__out), __fc);
554  break;
555  case 'g':
556  case 'G':
557  __out = _M_g_G(__t, std::move(__out), __fc, __c == 'G');
558  break;
559  case 'H':
560  case 'I':
561  __out = _M_H_I(__t, __print_sign(), __fc, __c, __mod == 'O');
562  break;
563  case 'j':
564  __out = _M_j(__t, __print_sign(), __fc);
565  break;
566  case 'm':
567  __out = _M_m(__t, std::move(__out), __fc, __mod == 'O');
568  break;
569  case 'M':
570  __out = _M_M(__t, __print_sign(), __fc, __mod == 'O');
571  break;
572  case 'p':
573  __out = _M_p(__t, std::move(__out), __fc);
574  break;
575  case 'q':
576  __out = _M_q(__t, std::move(__out), __fc);
577  break;
578  case 'Q':
579  // %Q The duration's numeric value.
580  if constexpr (chrono::__is_duration_v<_Tp>)
581  __out = std::format_to(__print_sign(), _S_empty_spec,
582  __t.count());
583  else
584  __throw_format_error("chrono format error: argument is "
585  "not a duration");
586  break;
587  case 'r':
588  __out = _M_r(__t, __print_sign(), __fc);
589  break;
590  case 'R':
591  case 'T':
592  __out = _M_R_T(__t, __print_sign(), __fc, __c == 'T');
593  break;
594  case 'S':
595  __out = _M_S(__t, __print_sign(), __fc, __mod == 'O');
596  break;
597  case 'u':
598  case 'w':
599  __out = _M_u_w(__t, std::move(__out), __fc, __c, __mod == 'O');
600  break;
601  case 'U':
602  case 'V':
603  case 'W':
604  __out = _M_U_V_W(__t, std::move(__out), __fc, __c,
605  __mod == 'O');
606  break;
607  case 'x':
608  __out = _M_x(__t, std::move(__out), __fc, __mod == 'E');
609  break;
610  case 'X':
611  __out = _M_X(__t, __print_sign(), __fc, __mod == 'E');
612  break;
613  case 'z':
614  __out = _M_z(__t, std::move(__out), __fc, (bool)__mod);
615  break;
616  case 'Z':
617  __out = _M_Z(__t, std::move(__out), __fc);
618  break;
619  case 'n':
620  *__out++ = __literals[0];
621  break;
622  case 't':
623  *__out++ = __literals[1];
624  break;
625  case '%':
626  *__out++ = __literals[2];
627  break;
628  case 'O':
629  case 'E':
630  __mod = __c;
631  continue;
632  case '}':
633  __first = __last;
634  break;
635  }
636  __mod = _CharT();
637  // Scan for next '%' and write out everything before it.
638  __string_view __str(__first, __last - __first);
639  size_t __pos = __str.find('%');
640  if (__pos == 0)
641  ++__first;
642  else
643  {
644  if (__pos == __str.npos)
645  __first = __last;
646  else
647  {
648  __str.remove_suffix(__str.length() - __pos);
649  __first += __pos + 1;
650  }
651  __out = __format::__write(std::move(__out), __str);
652  }
653  }
654  while (__first != __last);
655 
656  if constexpr (is_same_v<typename _FormatContext::iterator,
657  _Sink_iter<_CharT>>)
658  if (__write_direct)
659  return __out;
660 
661  auto __str = std::move(__sink).get();
662  return __format::__write_padded_as_spec(__str, __str.size(),
663  __fc, _M_spec);
664  }
665 
666  _ChronoSpec<_CharT> _M_spec;
667 
668  private:
669  // Return the formatting locale.
670  template<typename _FormatContext>
671  std::locale
672  _M_locale(_FormatContext& __fc) const
673  {
674  if (!_M_spec._M_localized)
675  return std::locale::classic();
676  else
677  return __fc.locale();
678  }
679 
680  // Format for empty chrono-specs, e.g. "{}" (C++20 [time.format] p6).
681  // TODO: consider moving body of every operator<< into this function
682  // and use std::format("{}", t) to implement those operators. That
683  // would avoid std::format("{}", t) calling operator<< which calls
684  // std::format again.
685  template<typename _Tp, typename _FormatContext>
686  typename _FormatContext::iterator
687  _M_format_to_ostream(const _Tp& __t, _FormatContext& __fc,
688  bool __is_neg) const
689  {
690  using ::std::chrono::__detail::__utc_leap_second;
691  using ::std::chrono::__detail::__local_time_fmt;
692 
693  if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
694  return _M_format_to_ostream(__t._M_time, __fc, false);
695  else
696  {
697  basic_ostringstream<_CharT> __os;
698  __os.imbue(_M_locale(__fc));
699 
700  if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
701  __os << __t._M_date << ' ' << __t._M_time;
702  else if constexpr (chrono::__is_time_point_v<_Tp>)
703  {
704  // Need to be careful here because not all specializations
705  // of chrono::sys_time can be written to an ostream.
706  // For the specializations of time_point that can be
707  // formatted with an empty chrono-specs, either it's a
708  // sys_time with period greater or equal to days:
709  if constexpr (is_convertible_v<_Tp, chrono::sys_days>)
710  __os << _S_date(__t);
711  else // Or it's formatted as "{:L%F %T}":
712  {
713  auto __days = chrono::floor<chrono::days>(__t);
714  __os << chrono::year_month_day(__days) << ' '
715  << chrono::hh_mm_ss(__t - __days);
716  }
717  }
718  else
719  {
720  if constexpr (chrono::__is_duration_v<_Tp>)
721  if (__is_neg) [[unlikely]]
722  __os << _S_plus_minus[1];
723  __os << __t;
724  }
725 
726  auto __str = std::move(__os).str();
727  return __format::__write_padded_as_spec(__str, __str.size(),
728  __fc, _M_spec);
729  }
730  }
731 
732  static constexpr const _CharT* _S_chars
733  = _GLIBCXX_WIDEN("0123456789+-:/ {}");
734  static constexpr const _CharT* _S_plus_minus = _S_chars + 10;
735  static constexpr _CharT _S_colon = _S_chars[12];
736  static constexpr _CharT _S_slash = _S_chars[13];
737  static constexpr _CharT _S_space = _S_chars[14];
738  static constexpr const _CharT* _S_empty_spec = _S_chars + 15;
739 
740  template<typename _Tp, typename _FormatContext>
741  typename _FormatContext::iterator
742  _M_a_A(const _Tp& __t, typename _FormatContext::iterator __out,
743  _FormatContext& __ctx, bool __full) const
744  {
745  // %a Locale's abbreviated weekday name.
746  // %A Locale's full weekday name.
747  chrono::weekday __wd = _S_weekday(__t);
748  if (!__wd.ok())
749  __throw_format_error("format error: invalid weekday");
750 
751  locale __loc = _M_locale(__ctx);
752  const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
753  const _CharT* __days[7];
754  if (__full)
755  __tp._M_days(__days);
756  else
757  __tp._M_days_abbreviated(__days);
758  __string_view __str(__days[__wd.c_encoding()]);
759  return __format::__write(std::move(__out), __str);
760  }
761 
762  template<typename _Tp, typename _FormatContext>
763  typename _FormatContext::iterator
764  _M_b_B(const _Tp& __t, typename _FormatContext::iterator __out,
765  _FormatContext& __ctx, bool __full) const
766  {
767  // %b Locale's abbreviated month name.
768  // %B Locale's full month name.
769  chrono::month __m = _S_month(__t);
770  if (!__m.ok())
771  __throw_format_error("format error: invalid month");
772  locale __loc = _M_locale(__ctx);
773  const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
774  const _CharT* __months[12];
775  if (__full)
776  __tp._M_months(__months);
777  else
778  __tp._M_months_abbreviated(__months);
779  __string_view __str(__months[(unsigned)__m - 1]);
780  return __format::__write(std::move(__out), __str);
781  }
782 
783  template<typename _Tp, typename _FormatContext>
784  typename _FormatContext::iterator
785  _M_c(const _Tp& __tt, typename _FormatContext::iterator __out,
786  _FormatContext& __ctx, bool __mod = false) const
787  {
788  // %c Locale's date and time representation.
789  // %Ec Locale's alternate date and time representation.
790 
791  basic_string<_CharT> __fmt;
792  auto __t = _S_floor_seconds(__tt);
793  locale __loc = _M_locale(__ctx);
794  const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
795  const _CharT* __formats[2];
796  __tp._M_date_time_formats(__formats);
797  if (*__formats[__mod]) [[likely]]
798  {
799  __fmt = _GLIBCXX_WIDEN("{:L}");
800  __fmt.insert(3u, __formats[__mod]);
801  }
802  else
803  __fmt = _GLIBCXX_WIDEN("{:L%a %b %e %T %Y}");
804  return std::vformat_to(std::move(__out), __loc, __fmt,
805  std::make_format_args<_FormatContext>(__t));
806  }
807 
808  template<typename _Tp, typename _FormatContext>
809  typename _FormatContext::iterator
810  _M_C_y_Y(const _Tp& __t, typename _FormatContext::iterator __out,
811  _FormatContext& __ctx, _CharT __conv, _CharT __mod = 0) const
812  {
813  // %C Year divided by 100 using floored division.
814  // %EC Locale's alternative preresentation of the century (era name).
815  // %y Last two decimal digits of the year.
816  // %Oy Locale's alternative representation.
817  // %Ey Locale's alternative representation of offset from %EC.
818  // %Y Year as a decimal number.
819  // %EY Locale's alternative full year representation.
820 
821  chrono::year __y = _S_year(__t);
822 
823  if (__mod) [[unlikely]]
824  {
825  struct tm __tm{};
826  __tm.tm_year = (int)__y - 1900;
827  return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
828  __conv, __mod);
829  }
830 
831  basic_string<_CharT> __s;
832  int __yi = (int)__y;
833  const bool __is_neg = __yi < 0;
834  __yi = __builtin_abs(__yi);
835 
836  if (__conv == 'Y' || __conv == 'C')
837  {
838  int __ci = __yi / 100;
839  if (__is_neg) [[unlikely]]
840  {
841  __s.assign(1, _S_plus_minus[1]);
842  // For floored division -123//100 is -2 and -100//100 is -1
843  if (__conv == 'C' && (__ci * 100) != __yi)
844  ++__ci;
845  }
846  if (__ci >= 100) [[unlikely]]
847  {
848  __s += std::format(_S_empty_spec, __ci / 100);
849  __ci %= 100;
850  }
851  __s += _S_two_digits(__ci);
852  }
853 
854  if (__conv == 'Y' || __conv == 'y')
855  __s += _S_two_digits(__yi % 100);
856 
857  return __format::__write(std::move(__out), __string_view(__s));
858  }
859 
860  template<typename _Tp, typename _FormatContext>
861  typename _FormatContext::iterator
862  _M_D(const _Tp& __t, typename _FormatContext::iterator __out,
863  _FormatContext&) const
864  {
865  auto __ymd = _S_date(__t);
866  basic_string<_CharT> __s;
867 #if ! _GLIBCXX_USE_CXX11_ABI
868  __s.reserve(8);
869 #endif
870  __s = _S_two_digits((unsigned)__ymd.month());
871  __s += _S_slash;
872  __s += _S_two_digits((unsigned)__ymd.day());
873  __s += _S_slash;
874  __s += _S_two_digits(__builtin_abs((int)__ymd.year()) % 100);
875  return __format::__write(std::move(__out), __string_view(__s));
876  }
877 
878  template<typename _Tp, typename _FormatContext>
879  typename _FormatContext::iterator
880  _M_d_e(const _Tp& __t, typename _FormatContext::iterator __out,
881  _FormatContext& __ctx, _CharT __conv, bool __mod = false) const
882  {
883  // %d The day of month as a decimal number.
884  // %Od Locale's alternative representation.
885  // %e Day of month as decimal number, padded with space.
886  // %Oe Locale's alternative digits.
887 
888  chrono::day __d = _S_day(__t);
889  unsigned __i = (unsigned)__d;
890 
891  if (__mod) [[unlikely]]
892  {
893  struct tm __tm{};
894  __tm.tm_mday = __i;
895  return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
896  (char)__conv, 'O');
897  }
898 
899  auto __sv = _S_two_digits(__i);
900  _CharT __buf[2];
901  if (__conv == _CharT('e') && __i < 10)
902  {
903  __buf[0] = _S_space;
904  __buf[1] = __sv[1];
905  __sv = {__buf, 2};
906  }
907  return __format::__write(std::move(__out), __sv);
908  }
909 
910  template<typename _Tp, typename _FormatContext>
911  typename _FormatContext::iterator
912  _M_F(const _Tp& __t, typename _FormatContext::iterator __out,
913  _FormatContext&) const
914  {
915  auto __ymd = _S_date(__t);
916  basic_string<_CharT> __s;
917 #if ! _GLIBCXX_USE_CXX11_ABI
918  __s.reserve(11);
919 #endif
920  __s += std::format(_GLIBCXX_WIDEN("{:04d}- - "), (int)__ymd.year());
921  auto __sv = _S_two_digits((unsigned)__ymd.month());
922  __s[__s.size() - 5] = __sv[0];
923  __s[__s.size() - 4] = __sv[1];
924  __sv = _S_two_digits((unsigned)__ymd.day());
925  __s[__s.size() - 2] = __sv[0];
926  __s[__s.size() - 1] = __sv[1];
927  __sv = __s;
928  return __format::__write(std::move(__out), __sv);
929  }
930 
931  template<typename _Tp, typename _FormatContext>
932  typename _FormatContext::iterator
933  _M_g_G(const _Tp& __t, typename _FormatContext::iterator __out,
934  _FormatContext& __ctx, bool __full) const
935  {
936  // %g last two decimal digits of the ISO week-based year.
937  // %G ISO week-based year.
938  using namespace chrono;
939  auto __d = _S_days(__t);
940  // Move to nearest Thursday:
941  __d -= (weekday(__d) - Monday) - days(3);
942  // ISO week-based year is the year that contains that Thursday:
943  year __y = year_month_day(__d).year();
944  return _M_C_y_Y(__y, std::move(__out), __ctx, "yY"[__full]);
945  }
946 
947  template<typename _Tp, typename _FormatContext>
948  typename _FormatContext::iterator
949  _M_H_I(const _Tp& __t, typename _FormatContext::iterator __out,
950  _FormatContext& __ctx, _CharT __conv, bool __mod = false) const
951  {
952  // %H The hour (24-hour clock) as a decimal number.
953  // %OH Locale's alternative representation.
954  // %I The hour (12-hour clock) as a decimal number.
955  // %OI Locale's alternative representation.
956 
957  const auto __hms = _S_hms(__t);
958  int __i = __hms.hours().count();
959 
960  if (__mod) [[unlikely]]
961  {
962  struct tm __tm{};
963  __tm.tm_hour = __i;
964  return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
965  (char)__conv, 'O');
966  }
967 
968  if (__conv == _CharT('I'))
969  {
970  if (__i == 0)
971  __i = 12;
972  else if (__i > 12)
973  __i -= 12;
974  }
975  return __format::__write(std::move(__out), _S_two_digits(__i));
976  }
977 
978  template<typename _Tp, typename _FormatContext>
979  typename _FormatContext::iterator
980  _M_j(const _Tp& __t, typename _FormatContext::iterator __out,
981  _FormatContext&) const
982  {
983  if constexpr (chrono::__is_duration_v<_Tp>)
984  {
985  // Decimal number of days, without padding.
986  unsigned __d = chrono::duration_cast<chrono::days>(__t).count();
987  return std::format_to(std::move(__out), _S_empty_spec, __d);
988  }
989  else
990  {
991  // Day of the year as a decimal number, padding with zero.
992  using namespace chrono;
993  auto __day = _S_days(__t);
994  auto __ymd = _S_date(__t);
995  days __d;
996  // See "Calculating Ordinal Dates" at
997  // https://github.com/HowardHinnant/date/wiki/Examples-and-Recipes
998  if constexpr (is_same_v<typename decltype(__day)::clock, local_t>)
999  __d = __day - local_days(__ymd.year()/January/0);
1000  else
1001  __d = __day - sys_days(__ymd.year()/January/0);
1002  return std::format_to(std::move(__out), _GLIBCXX_WIDEN("{:03d}"),
1003  __d.count());
1004  }
1005  }
1006 
1007  template<typename _Tp, typename _FormatContext>
1008  typename _FormatContext::iterator
1009  _M_m(const _Tp& __t, typename _FormatContext::iterator __out,
1010  _FormatContext& __ctx, bool __mod) const
1011  {
1012  // %m month as a decimal number.
1013  // %Om Locale's alternative representation.
1014 
1015  auto __m = _S_month(__t);
1016  auto __i = (unsigned)__m;
1017 
1018  if (__mod) [[unlikely]] // %Om
1019  {
1020  struct tm __tm{};
1021  __tm.tm_mon = __i - 1;
1022  return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
1023  'm', 'O');
1024  }
1025 
1026  return __format::__write(std::move(__out), _S_two_digits(__i));
1027  }
1028 
1029  template<typename _Tp, typename _FormatContext>
1030  typename _FormatContext::iterator
1031  _M_M(const _Tp& __t, typename _FormatContext::iterator __out,
1032  _FormatContext& __ctx, bool __mod) const
1033  {
1034  // %M The minute as a decimal number.
1035  // %OM Locale's alternative representation.
1036 
1037  auto __m = _S_hms(__t).minutes();
1038  auto __i = __m.count();
1039 
1040  if (__mod) [[unlikely]] // %OM
1041  {
1042  struct tm __tm{};
1043  __tm.tm_min = __i;
1044  return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
1045  'M', 'O');
1046  }
1047 
1048  return __format::__write(std::move(__out), _S_two_digits(__i));
1049  }
1050 
1051  template<typename _Tp, typename _FormatContext>
1052  typename _FormatContext::iterator
1053  _M_p(const _Tp& __t, typename _FormatContext::iterator __out,
1054  _FormatContext& __ctx) const
1055  {
1056  // %p The locale's equivalent of the AM/PM designations.
1057  auto __hms = _S_hms(__t);
1058  locale __loc = _M_locale(__ctx);
1059  const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
1060  const _CharT* __ampm[2];
1061  __tp._M_am_pm(__ampm);
1062  return std::format_to(std::move(__out), _S_empty_spec,
1063  __ampm[__hms.hours().count() >= 12]);
1064  }
1065 
1066  template<typename _Tp, typename _FormatContext>
1067  typename _FormatContext::iterator
1068  _M_q(const _Tp&, typename _FormatContext::iterator __out,
1069  _FormatContext&) const
1070  {
1071  // %q The duration's unit suffix
1072  if constexpr (!chrono::__is_duration_v<_Tp>)
1073  __throw_format_error("format error: argument is not a duration");
1074  else
1075  {
1076  namespace __d = chrono::__detail;
1077  using period = typename _Tp::period;
1078  return __d::__fmt_units_suffix<period, _CharT>(std::move(__out));
1079  }
1080  }
1081 
1082  // %Q handled in _M_format
1083 
1084  template<typename _Tp, typename _FormatContext>
1085  typename _FormatContext::iterator
1086  _M_r(const _Tp& __tt, typename _FormatContext::iterator __out,
1087  _FormatContext& __ctx) const
1088  {
1089  // %r locale's 12-hour clock time.
1090  auto __t = _S_floor_seconds(__tt);
1091  locale __loc = _M_locale(__ctx);
1092  const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
1093  const _CharT* __ampm_fmt;
1094  __tp._M_am_pm_format(&__ampm_fmt);
1095  basic_string<_CharT> __fmt(_S_empty_spec);
1096  __fmt.insert(1u, 1u, _S_colon);
1097  __fmt.insert(2u, __ampm_fmt);
1098  return std::vformat_to(std::move(__out), __fmt,
1099  std::make_format_args<_FormatContext>(__t));
1100  }
1101 
1102  template<typename _Tp, typename _FormatContext>
1103  typename _FormatContext::iterator
1104  _M_R_T(const _Tp& __t, typename _FormatContext::iterator __out,
1105  _FormatContext& __ctx, bool __secs) const
1106  {
1107  // %R Equivalent to %H:%M
1108  // %T Equivalent to %H:%M:%S
1109  auto __hms = _S_hms(__t);
1110 
1111  basic_string<_CharT> __s;
1112 #if ! _GLIBCXX_USE_CXX11_ABI
1113  __s.reserve(11);
1114 #endif
1115  __s = std::format(_GLIBCXX_WIDEN("{:02d}:00"), __hms.hours().count());
1116  auto __sv = _S_two_digits(__hms.minutes().count());
1117  __s[__s.size() - 2] = __sv[0];
1118  __s[__s.size() - 1] = __sv[1];
1119  __sv = __s;
1120  __out = __format::__write(std::move(__out), __sv);
1121  if (__secs)
1122  {
1123  *__out++ = _S_colon;
1124  __out = _M_S(__hms, std::move(__out), __ctx);
1125  }
1126  return __out;
1127  }
1128 
1129  template<typename _Tp, typename _FormatContext>
1130  typename _FormatContext::iterator
1131  _M_S(const _Tp& __t, typename _FormatContext::iterator __out,
1132  _FormatContext& __ctx, bool __mod = false) const
1133  {
1134  // %S Seconds as a decimal number.
1135  // %OS The locale's alternative representation.
1136  auto __hms = _S_hms(__t);
1137 
1138  if (__mod) [[unlikely]] // %OS
1139  {
1140  struct tm __tm{};
1141  __tm.tm_sec = (int)__hms.seconds().count();
1142  return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
1143  'S', 'O');
1144  }
1145 
1146  if constexpr (__hms.fractional_width == 0)
1147  __out = __format::__write(std::move(__out),
1148  _S_two_digits(__hms.seconds().count()));
1149  else
1150  {
1151  locale __loc = _M_locale(__ctx);
1152  auto __s = __hms.seconds();
1153  auto __ss = __hms.subseconds();
1154  using rep = typename decltype(__ss)::rep;
1155  if constexpr (is_floating_point_v<rep>)
1156  {
1157  chrono::duration<rep> __fs = __s + __ss;
1158  __out = std::format_to(std::move(__out), __loc,
1159  _GLIBCXX_WIDEN("{:#0{}.{}Lf}"),
1160  __fs.count(),
1161  3 + __hms.fractional_width,
1162  __hms.fractional_width);
1163  }
1164  else
1165  {
1166  const auto& __np
1167  = use_facet<numpunct<_CharT>>(__loc);
1168  __out = __format::__write(std::move(__out),
1169  _S_two_digits(__s.count()));
1170  *__out++ = __np.decimal_point();
1171  if constexpr (is_integral_v<rep>)
1172  __out = std::format_to(std::move(__out),
1173  _GLIBCXX_WIDEN("{:0{}}"),
1174  __ss.count(),
1175  __hms.fractional_width);
1176  else
1177  {
1178  auto __str = std::format(_S_empty_spec, __ss.count());
1179  __out = std::format_to(_GLIBCXX_WIDEN("{:0>{}s}"),
1180  __str,
1181  __hms.fractional_width);
1182  }
1183  }
1184  }
1185  return __out;
1186  }
1187 
1188  // %t handled in _M_format
1189 
1190  template<typename _Tp, typename _FormatContext>
1191  typename _FormatContext::iterator
1192  _M_u_w(const _Tp& __t, typename _FormatContext::iterator __out,
1193  _FormatContext& __ctx, _CharT __conv, bool __mod = false) const
1194  {
1195  // %u ISO weekday as a decimal number (1-7), where Monday is 1.
1196  // %Ou Locale's alternative numeric rep.
1197  // %w Weekday as a decimal number (0-6), where Sunday is 0.
1198  // %Ow Locale's alternative numeric rep.
1199 
1200  chrono::weekday __wd = _S_weekday(__t);
1201 
1202  if (__mod) [[unlikely]]
1203  {
1204  struct tm __tm{};
1205  __tm.tm_wday = __wd.c_encoding();
1206  return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
1207  (char)__conv, 'O');
1208  }
1209 
1210  unsigned __wdi = __conv == 'u' ? __wd.iso_encoding()
1211  : __wd.c_encoding();
1212  const _CharT __d = _S_digit(__wdi);
1213  return __format::__write(std::move(__out), __string_view(&__d, 1));
1214  }
1215 
1216  template<typename _Tp, typename _FormatContext>
1217  typename _FormatContext::iterator
1218  _M_U_V_W(const _Tp& __t, typename _FormatContext::iterator __out,
1219  _FormatContext& __ctx, _CharT __conv, bool __mod = false) const
1220  {
1221  // %U Week number of the year as a decimal number, from first Sunday.
1222  // %OU Locale's alternative numeric rep.
1223  // %V ISO week-based week number as a decimal number.
1224  // %OV Locale's alternative numeric rep.
1225  // %W Week number of the year as a decimal number, from first Monday.
1226  // %OW Locale's alternative numeric rep.
1227  using namespace chrono;
1228  auto __d = _S_days(__t);
1229  using _TDays = decltype(__d); // Either sys_days or local_days.
1230 
1231  if (__mod) [[unlikely]]
1232  {
1233  const year_month_day __ymd(__d);
1234  const year __y = __ymd.year();
1235  struct tm __tm{};
1236  __tm.tm_year = (int)__y - 1900;
1237  __tm.tm_yday = (__d - _TDays(__y/January/1)).count();
1238  __tm.tm_wday = weekday(__d).c_encoding();
1239  return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
1240  (char)__conv, 'O');
1241  }
1242 
1243  _TDays __first; // First day of week 1.
1244  if (__conv == 'V') // W01 begins on Monday before first Thursday.
1245  {
1246  // Move to nearest Thursday:
1247  __d -= (weekday(__d) - Monday) - days(3);
1248  // ISO week of __t is number of weeks since January 1 of the
1249  // same year as that nearest Thursday.
1250  __first = _TDays(year_month_day(__d).year()/January/1);
1251  }
1252  else
1253  {
1254  year __y;
1255  if constexpr (requires { __t.year(); })
1256  __y = __t.year();
1257  else
1258  __y = year_month_day(__d).year();
1259  const weekday __weekstart = __conv == 'U' ? Sunday : Monday;
1260  __first = _TDays(__y/January/__weekstart[1]);
1261  }
1262  auto __weeks = chrono::floor<weeks>(__d - __first);
1263  __string_view __sv = _S_two_digits(__weeks.count() + 1);
1264  return __format::__write(std::move(__out), __sv);
1265  }
1266 
1267  template<typename _Tp, typename _FormatContext>
1268  typename _FormatContext::iterator
1269  _M_x(const _Tp& __t, typename _FormatContext::iterator __out,
1270  _FormatContext& __ctx, bool __mod = false) const
1271  {
1272  // %x Locale's date rep
1273  // %Ex Locale's alternative date representation.
1274  locale __loc = _M_locale(__ctx);
1275  const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
1276  const _CharT* __date_reps[2];
1277  __tp._M_date_formats(__date_reps);
1278  const _CharT* __rep = __date_reps[__mod];
1279  if (!*__rep)
1280  return _M_D(__t, std::move(__out), __ctx);
1281 
1282  basic_string<_CharT> __fmt(_S_empty_spec);
1283  __fmt.insert(1u, 1u, _S_colon);
1284  __fmt.insert(2u, __rep);
1285  return std::vformat_to(std::move(__out), __fmt,
1286  std::make_format_args<_FormatContext>(__t));
1287  }
1288 
1289  template<typename _Tp, typename _FormatContext>
1290  typename _FormatContext::iterator
1291  _M_X(const _Tp& __tt, typename _FormatContext::iterator __out,
1292  _FormatContext& __ctx, bool __mod = false) const
1293  {
1294  // %X Locale's time rep
1295  // %EX Locale's alternative time representation.
1296  auto __t = _S_floor_seconds(__tt);
1297  locale __loc = _M_locale(__ctx);
1298  const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
1299  const _CharT* __time_reps[2];
1300  __tp._M_time_formats(__time_reps);
1301  const _CharT* __rep = __time_reps[__mod];
1302  if (!*__rep)
1303  return _M_R_T(__t, std::move(__out), __ctx, true);
1304 
1305  basic_string<_CharT> __fmt(_S_empty_spec);
1306  __fmt.insert(1u, 1u, _S_colon);
1307  __fmt.insert(2u, __rep);
1308  return std::vformat_to(std::move(__out), __fmt,
1309  std::make_format_args<_FormatContext>(__t));
1310  }
1311 
1312  template<typename _Tp, typename _FormatContext>
1313  typename _FormatContext::iterator
1314  _M_z(const _Tp& __t, typename _FormatContext::iterator __out,
1315  _FormatContext&, bool __mod = false) const
1316  {
1317  using ::std::chrono::__detail::__utc_leap_second;
1318  using ::std::chrono::__detail::__local_time_fmt;
1319 
1320  auto __utc = __mod ? __string_view(_GLIBCXX_WIDEN("+00:00"), 6)
1321  : __string_view(_GLIBCXX_WIDEN("+0000"), 5);
1322 
1323  if constexpr (chrono::__is_time_point_v<_Tp>)
1324  {
1325  if constexpr (is_same_v<typename _Tp::clock,
1326  chrono::system_clock>)
1327  return __format::__write(std::move(__out), __utc);
1328  }
1329  else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
1330  {
1331  if (__t._M_offset_sec)
1332  {
1333  auto __sv = __utc;
1334  basic_string<_CharT> __s;
1335  if (*__t._M_offset_sec != 0s)
1336  {
1337  chrono:: hh_mm_ss __hms(*__t._M_offset_sec);
1338  __s = _S_plus_minus[__hms.is_negative()];
1339  __s += _S_two_digits(__hms.hours().count());
1340  if (__mod)
1341  __s += _S_colon;
1342  __s += _S_two_digits(__hms.minutes().count());
1343  __sv = __s;
1344  }
1345  return __format::__write(std::move(__out), __sv);
1346  }
1347  }
1348  else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
1349  return __format::__write(std::move(__out), __utc);
1350 
1351  __no_timezone_available();
1352  }
1353 
1354  template<typename _Tp, typename _FormatContext>
1355  typename _FormatContext::iterator
1356  _M_Z(const _Tp& __t, typename _FormatContext::iterator __out,
1357  _FormatContext& __ctx) const
1358  {
1359  using ::std::chrono::__detail::__utc_leap_second;
1360  using ::std::chrono::__detail::__local_time_fmt;
1361 
1362  __string_view __utc(_GLIBCXX_WIDEN("UTC"), 3);
1363  if constexpr (chrono::__is_time_point_v<_Tp>)
1364  {
1365  if constexpr (is_same_v<typename _Tp::clock,
1366  chrono::system_clock>)
1367  return __format::__write(std::move(__out), __utc);
1368  }
1369  else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
1370  {
1371  if (__t._M_abbrev)
1372  {
1373  string_view __sv = *__t._M_abbrev;
1374  if constexpr (is_same_v<_CharT, char>)
1375  return __format::__write(std::move(__out), __sv);
1376  else
1377  {
1378  // TODO use resize_and_overwrite
1379  basic_string<_CharT> __ws(__sv.size(), _CharT());
1380  auto& __ct = use_facet<ctype<_CharT>>(_M_locale(__ctx));
1381  __ct.widen(__sv.begin(), __sv.end(), __ws.data());
1382  __string_view __wsv = __ws;
1383  return __format::__write(std::move(__out), __wsv);
1384  }
1385  }
1386  }
1387  else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
1388  return __format::__write(std::move(__out), __utc);
1389 
1390  __no_timezone_available();
1391  }
1392 
1393  // %% handled in _M_format
1394 
1395  // A single digit character in the range '0'..'9'.
1396  static _CharT
1397  _S_digit(int __n) noexcept
1398  {
1399  // Extra 9s avoid past-the-end read on bad input.
1400  return _GLIBCXX_WIDEN("0123456789999999")[__n & 0xf];
1401  }
1402 
1403  // A string view of two digit characters, "00".."99".
1404  static basic_string_view<_CharT>
1405  _S_two_digits(int __n) noexcept
1406  {
1407  return {
1408  _GLIBCXX_WIDEN("0001020304050607080910111213141516171819"
1409  "2021222324252627282930313233343536373839"
1410  "4041424344454647484950515253545556575859"
1411  "6061626364656667686970717273747576777879"
1412  "8081828384858687888990919293949596979899"
1413  "9999999999999999999999999999999999999999"
1414  "9999999999999999") + 2 * (__n & 0x7f),
1415  2
1416  };
1417  }
1418 
1419  // Accessors for the components of chrono types:
1420 
1421  // Returns a hh_mm_ss.
1422  template<typename _Tp>
1423  static decltype(auto)
1424  _S_hms(const _Tp& __t)
1425  {
1426  using ::std::chrono::__detail::__utc_leap_second;
1427  using ::std::chrono::__detail::__local_time_fmt;
1428 
1429  if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>)
1430  return __t;
1431  else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
1432  return __t._M_time;
1433  else if constexpr (chrono::__is_duration_v<_Tp>)
1434  return chrono::hh_mm_ss<_Tp>(__t);
1435  else if constexpr (chrono::__is_time_point_v<_Tp>)
1436  return chrono::hh_mm_ss(__t - chrono::floor<chrono::days>(__t));
1437  else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
1438  return _S_hms(__t._M_time);
1439  else
1440  {
1441  __invalid_chrono_spec();
1442  return chrono::hh_mm_ss<chrono::seconds>();
1443  }
1444  }
1445 
1446  // Returns a sys_days or local_days.
1447  template<typename _Tp>
1448  static auto
1449  _S_days(const _Tp& __t)
1450  {
1451  using namespace chrono;
1452  using ::std::chrono::__detail::__utc_leap_second;
1453  using ::std::chrono::__detail::__local_time_fmt;
1454 
1455  if constexpr (__is_time_point_v<_Tp>)
1456  return chrono::floor<days>(__t);
1457  else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
1458  return __t._M_date;
1459  else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
1460  return chrono::floor<days>(__t._M_time);
1461  else if constexpr (is_same_v<_Tp, year_month_day>
1462  || is_same_v<_Tp, year_month_day_last>
1463  || is_same_v<_Tp, year_month_weekday>
1464  || is_same_v<_Tp, year_month_weekday_last>)
1465  return sys_days(__t);
1466  else
1467  {
1468  if constexpr (__is_duration_v<_Tp>)
1469  __not_valid_for_duration();
1470  else
1471  __invalid_chrono_spec();
1472  return chrono::sys_days();
1473  }
1474  }
1475 
1476  // Returns a year_month_day.
1477  template<typename _Tp>
1478  static chrono::year_month_day
1479  _S_date(const _Tp& __t)
1480  {
1481  if constexpr (is_same_v<_Tp, chrono::year_month_day>)
1482  return __t;
1483  else
1484  return chrono::year_month_day(_S_days(__t));
1485  }
1486 
1487  template<typename _Tp>
1488  static chrono::day
1489  _S_day(const _Tp& __t)
1490  {
1491  using namespace chrono;
1492 
1493  if constexpr (is_same_v<_Tp, day>)
1494  return __t;
1495  else if constexpr (requires { __t.day(); })
1496  return __t.day();
1497  else
1498  return _S_date(__t).day();
1499  }
1500 
1501  template<typename _Tp>
1502  static chrono::month
1503  _S_month(const _Tp& __t)
1504  {
1505  using namespace chrono;
1506 
1507  if constexpr (is_same_v<_Tp, month>)
1508  return __t;
1509  else if constexpr (requires { __t.month(); })
1510  return __t.month();
1511  else
1512  return _S_date(__t).month();
1513  }
1514 
1515  template<typename _Tp>
1516  static chrono::year
1517  _S_year(const _Tp& __t)
1518  {
1519  using namespace chrono;
1520 
1521  if constexpr (is_same_v<_Tp, year>)
1522  return __t;
1523  else if constexpr (requires { __t.year(); })
1524  return __t.year();
1525  else
1526  return _S_date(__t).year();
1527  }
1528 
1529  template<typename _Tp>
1530  static chrono::weekday
1531  _S_weekday(const _Tp& __t)
1532  {
1533  using namespace ::std::chrono;
1534  using ::std::chrono::__detail::__local_time_fmt;
1535 
1536  if constexpr (is_same_v<_Tp, weekday>)
1537  return __t;
1538  else if constexpr (requires { __t.weekday(); })
1539  return __t.weekday();
1540  else if constexpr (is_same_v<_Tp, month_weekday>)
1541  return __t.weekday_indexed().weekday();
1542  else if constexpr (is_same_v<_Tp, month_weekday_last>)
1543  return __t.weekday_last().weekday();
1544  else
1545  return weekday(_S_days(__t));
1546  }
1547 
1548  // Remove subsecond precision from a time_point.
1549  template<typename _Tp>
1550  static auto
1551  _S_floor_seconds(const _Tp& __t)
1552  {
1553  using chrono::__detail::__local_time_fmt;
1554  if constexpr (chrono::__is_time_point_v<_Tp>
1555  || chrono::__is_duration_v<_Tp>)
1556  {
1557  if constexpr (_Tp::period::den != 1)
1558  return chrono::floor<chrono::seconds>(__t);
1559  else
1560  return __t;
1561  }
1562  else if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>)
1563  {
1564  if constexpr (_Tp::fractional_width != 0)
1565  return chrono::floor<chrono::seconds>(__t.to_duration());
1566  else
1567  return __t;
1568  }
1569  else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
1570  return _S_floor_seconds(__t._M_time);
1571  else
1572  return __t;
1573  }
1574 
1575  // Use the formatting locale's std::time_put facet to produce
1576  // a locale-specific representation.
1577  template<typename _Iter>
1578  _Iter
1579  _M_locale_fmt(_Iter __out, const locale& __loc, const struct tm& __tm,
1580  char __fmt, char __mod) const
1581  {
1582  basic_ostringstream<_CharT> __os;
1583  const auto& __tp = use_facet<time_put<_CharT>>(__loc);
1584  __tp.put(__os, __os, _S_space, &__tm, __fmt, __mod);
1585  if (__os)
1586  __out = __format::__write(std::move(__out), __os.view());
1587  return __out;
1588  }
1589  };
1590 
1591 } // namespace __format
1592 /// @endcond
1593 
1594  template<typename _Rep, typename _Period, typename _CharT>
1595  struct formatter<chrono::duration<_Rep, _Period>, _CharT>
1596  {
1597  constexpr typename basic_format_parse_context<_CharT>::iterator
1598  parse(basic_format_parse_context<_CharT>& __pc)
1599  {
1600  using namespace __format;
1601  auto __it = _M_f._M_parse(__pc, _Duration|_TimeOfDay);
1602  if constexpr (!is_floating_point_v<_Rep>)
1603  if (_M_f._M_spec._M_prec_kind != __format::_WP_none)
1604  __throw_format_error("format error: invalid precision for duration");
1605  return __it;
1606  }
1607 
1608  template<typename _Out>
1609  typename basic_format_context<_Out, _CharT>::iterator
1610  format(const chrono::duration<_Rep, _Period>& __d,
1611  basic_format_context<_Out, _CharT>& __fc) const
1612  {
1613  if constexpr (numeric_limits<_Rep>::is_signed)
1614  if (__d < __d.zero()) [[unlikely]]
1615  {
1616  if constexpr (is_integral_v<_Rep>)
1617  {
1618  // -d is undefined for the most negative integer.
1619  // Convert duration to corresponding unsigned rep.
1620  using _URep = make_unsigned_t<_Rep>;
1621  auto __ucnt = -static_cast<_URep>(__d.count());
1622  auto __ud = chrono::duration<_URep, _Period>(__ucnt);
1623  return _M_f._M_format(__ud, __fc, true);
1624  }
1625  else
1626  return _M_f._M_format(-__d, __fc, true);
1627  }
1628  return _M_f._M_format(__d, __fc, false);
1629  }
1630 
1631  private:
1632  __format::__formatter_chrono<_CharT> _M_f;
1633  };
1634 
1635  template<typename _CharT>
1636  struct formatter<chrono::day, _CharT>
1637  {
1638  template<typename _ParseContext>
1639  constexpr typename _ParseContext::iterator
1640  parse(_ParseContext& __pc)
1641  { return _M_f._M_parse(__pc, __format::_Day); }
1642 
1643  template<typename _FormatContext>
1644  typename _FormatContext::iterator
1645  format(const chrono::day& __t, _FormatContext& __fc) const
1646  { return _M_f._M_format(__t, __fc); }
1647 
1648  private:
1649  __format::__formatter_chrono<_CharT> _M_f;
1650  };
1651 
1652  template<typename _CharT>
1653  struct formatter<chrono::month, _CharT>
1654  {
1655  template<typename _ParseContext>
1656  constexpr typename _ParseContext::iterator
1657  parse(_ParseContext& __pc)
1658  { return _M_f._M_parse(__pc, __format::_Month); }
1659 
1660  template<typename _FormatContext>
1661  typename _FormatContext::iterator
1662  format(const chrono::month& __t, _FormatContext& __fc) const
1663  { return _M_f._M_format(__t, __fc); }
1664 
1665  private:
1666  __format::__formatter_chrono<_CharT> _M_f;
1667  };
1668 
1669  template<typename _CharT>
1670  struct formatter<chrono::year, _CharT>
1671  {
1672  template<typename _ParseContext>
1673  constexpr typename _ParseContext::iterator
1674  parse(_ParseContext& __pc)
1675  { return _M_f._M_parse(__pc, __format::_Year); }
1676 
1677  template<typename _FormatContext>
1678  typename _FormatContext::iterator
1679  format(const chrono::year& __t, _FormatContext& __fc) const
1680  { return _M_f._M_format(__t, __fc); }
1681 
1682  private:
1683  __format::__formatter_chrono<_CharT> _M_f;
1684  };
1685 
1686  template<typename _CharT>
1687  struct formatter<chrono::weekday, _CharT>
1688  {
1689  template<typename _ParseContext>
1690  constexpr typename _ParseContext::iterator
1691  parse(_ParseContext& __pc)
1692  { return _M_f._M_parse(__pc, __format::_Weekday); }
1693 
1694  template<typename _FormatContext>
1695  typename _FormatContext::iterator
1696  format(const chrono::weekday& __t, _FormatContext& __fc) const
1697  { return _M_f._M_format(__t, __fc); }
1698 
1699  private:
1700  __format::__formatter_chrono<_CharT> _M_f;
1701  };
1702 
1703  template<typename _CharT>
1704  struct formatter<chrono::weekday_indexed, _CharT>
1705  {
1706  template<typename _ParseContext>
1707  constexpr typename _ParseContext::iterator
1708  parse(_ParseContext& __pc)
1709  { return _M_f._M_parse(__pc, __format::_Weekday); }
1710 
1711  template<typename _FormatContext>
1712  typename _FormatContext::iterator
1713  format(const chrono::weekday_indexed& __t, _FormatContext& __fc) const
1714  { return _M_f._M_format(__t, __fc); }
1715 
1716  private:
1717  __format::__formatter_chrono<_CharT> _M_f;
1718  };
1719 
1720  template<typename _CharT>
1721  struct formatter<chrono::weekday_last, _CharT>
1722  {
1723  template<typename _ParseContext>
1724  constexpr typename _ParseContext::iterator
1725  parse(_ParseContext& __pc)
1726  { return _M_f._M_parse(__pc, __format::_Weekday); }
1727 
1728  template<typename _FormatContext>
1729  typename _FormatContext::iterator
1730  format(const chrono::weekday_last& __t, _FormatContext& __fc) const
1731  { return _M_f._M_format(__t, __fc); }
1732 
1733  private:
1734  __format::__formatter_chrono<_CharT> _M_f;
1735  };
1736 
1737  template<typename _CharT>
1738  struct formatter<chrono::month_day, _CharT>
1739  {
1740  template<typename _ParseContext>
1741  constexpr typename _ParseContext::iterator
1742  parse(_ParseContext& __pc)
1743  { return _M_f._M_parse(__pc, __format::_Month|__format::_Day); }
1744 
1745  template<typename _FormatContext>
1746  typename _FormatContext::iterator
1747  format(const chrono::month_day& __t, _FormatContext& __fc) const
1748  { return _M_f._M_format(__t, __fc); }
1749 
1750  private:
1751  __format::__formatter_chrono<_CharT> _M_f;
1752  };
1753 
1754  template<typename _CharT>
1755  struct formatter<chrono::month_day_last, _CharT>
1756  {
1757  template<typename _ParseContext>
1758  constexpr typename _ParseContext::iterator
1759  parse(_ParseContext& __pc)
1760  { return _M_f._M_parse(__pc, __format::_Month|__format::_Day); }
1761 
1762  template<typename _FormatContext>
1763  typename _FormatContext::iterator
1764  format(const chrono::month_day_last& __t, _FormatContext& __fc) const
1765  { return _M_f._M_format(__t, __fc); }
1766 
1767  private:
1768  __format::__formatter_chrono<_CharT> _M_f;
1769  };
1770 
1771  template<typename _CharT>
1772  struct formatter<chrono::month_weekday, _CharT>
1773  {
1774  template<typename _ParseContext>
1775  constexpr typename _ParseContext::iterator
1776  parse(_ParseContext& __pc)
1777  { return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday); }
1778 
1779  template<typename _FormatContext>
1780  typename _FormatContext::iterator
1781  format(const chrono::month_weekday& __t, _FormatContext& __fc) const
1782  { return _M_f._M_format(__t, __fc); }
1783 
1784  private:
1785  __format::__formatter_chrono<_CharT> _M_f;
1786  };
1787 
1788  template<typename _CharT>
1789  struct formatter<chrono::month_weekday_last, _CharT>
1790  {
1791  template<typename _ParseContext>
1792  constexpr typename _ParseContext::iterator
1793  parse(_ParseContext& __pc)
1794  { return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday); }
1795 
1796  template<typename _FormatContext>
1797  typename _FormatContext::iterator
1798  format(const chrono::month_weekday_last& __t,
1799  _FormatContext& __fc) const
1800  { return _M_f._M_format(__t, __fc); }
1801 
1802  private:
1803  __format::__formatter_chrono<_CharT> _M_f;
1804  };
1805 
1806  template<typename _CharT>
1807  struct formatter<chrono::year_month, _CharT>
1808  {
1809  template<typename _ParseContext>
1810  constexpr typename _ParseContext::iterator
1811  parse(_ParseContext& __pc)
1812  { return _M_f._M_parse(__pc, __format::_Year|__format::_Month); }
1813 
1814  template<typename _FormatContext>
1815  typename _FormatContext::iterator
1816  format(const chrono::year_month& __t, _FormatContext& __fc) const
1817  { return _M_f._M_format(__t, __fc); }
1818 
1819  private:
1820  __format::__formatter_chrono<_CharT> _M_f;
1821  };
1822 
1823  template<typename _CharT>
1824  struct formatter<chrono::year_month_day, _CharT>
1825  {
1826  template<typename _ParseContext>
1827  constexpr typename _ParseContext::iterator
1828  parse(_ParseContext& __pc)
1829  { return _M_f._M_parse(__pc, __format::_Date); }
1830 
1831  template<typename _FormatContext>
1832  typename _FormatContext::iterator
1833  format(const chrono::year_month_day& __t, _FormatContext& __fc) const
1834  { return _M_f._M_format(__t, __fc); }
1835 
1836  private:
1837  __format::__formatter_chrono<_CharT> _M_f;
1838  };
1839 
1840  template<typename _CharT>
1841  struct formatter<chrono::year_month_day_last, _CharT>
1842  {
1843  template<typename _ParseContext>
1844  constexpr typename _ParseContext::iterator
1845  parse(_ParseContext& __pc)
1846  { return _M_f._M_parse(__pc, __format::_Date); }
1847 
1848  template<typename _FormatContext>
1849  typename _FormatContext::iterator
1850  format(const chrono::year_month_day_last& __t,
1851  _FormatContext& __fc) const
1852  { return _M_f._M_format(__t, __fc); }
1853 
1854  private:
1855  __format::__formatter_chrono<_CharT> _M_f;
1856  };
1857 
1858  template<typename _CharT>
1859  struct formatter<chrono::year_month_weekday, _CharT>
1860  {
1861  template<typename _ParseContext>
1862  constexpr typename _ParseContext::iterator
1863  parse(_ParseContext& __pc)
1864  { return _M_f._M_parse(__pc, __format::_Date); }
1865 
1866  template<typename _FormatContext>
1867  typename _FormatContext::iterator
1868  format(const chrono::year_month_weekday& __t,
1869  _FormatContext& __fc) const
1870  { return _M_f._M_format(__t, __fc); }
1871 
1872  private:
1873  __format::__formatter_chrono<_CharT> _M_f;
1874  };
1875 
1876  template<typename _CharT>
1877  struct formatter<chrono::year_month_weekday_last, _CharT>
1878  {
1879  template<typename _ParseContext>
1880  constexpr typename _ParseContext::iterator
1881  parse(_ParseContext& __pc)
1882  { return _M_f._M_parse(__pc, __format::_Date); }
1883 
1884  template<typename _FormatContext>
1885  typename _FormatContext::iterator
1886  format(const chrono::year_month_weekday_last& __t,
1887  _FormatContext& __fc) const
1888  { return _M_f._M_format(__t, __fc); }
1889 
1890  private:
1891  __format::__formatter_chrono<_CharT> _M_f;
1892  };
1893 
1894  template<typename _Rep, typename _Period, typename _CharT>
1895  struct formatter<chrono::hh_mm_ss<chrono::duration<_Rep, _Period>>, _CharT>
1896  {
1897  template<typename _ParseContext>
1898  constexpr typename _ParseContext::iterator
1899  parse(_ParseContext& __pc)
1900  { return _M_f._M_parse(__pc, __format::_TimeOfDay); }
1901 
1902  template<typename _FormatContext>
1903  typename _FormatContext::iterator
1904  format(const chrono::hh_mm_ss<chrono::duration<_Rep, _Period>>& __t,
1905  _FormatContext& __fc) const
1906  { return _M_f._M_format(__t, __fc); }
1907 
1908  private:
1909  __format::__formatter_chrono<_CharT> _M_f;
1910  };
1911 
1912 #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
1913  template<typename _CharT>
1914  struct formatter<chrono::sys_info, _CharT>
1915  {
1916  template<typename _ParseContext>
1917  constexpr typename _ParseContext::iterator
1918  parse(_ParseContext& __pc)
1919  { return _M_f._M_parse(__pc, __format::_ChronoParts{}); }
1920 
1921  template<typename _FormatContext>
1922  typename _FormatContext::iterator
1923  format(const chrono::sys_info& __i, _FormatContext& __fc) const
1924  { return _M_f._M_format(__i, __fc); }
1925 
1926  private:
1927  __format::__formatter_chrono<_CharT> _M_f;
1928  };
1929 
1930  template<typename _CharT>
1931  struct formatter<chrono::local_info, _CharT>
1932  {
1933  template<typename _ParseContext>
1934  constexpr typename _ParseContext::iterator
1935  parse(_ParseContext& __pc)
1936  { return _M_f._M_parse(__pc, __format::_ChronoParts{}); }
1937 
1938  template<typename _FormatContext>
1939  typename _FormatContext::iterator
1940  format(const chrono::local_info& __i, _FormatContext& __fc) const
1941  { return _M_f._M_format(__i, __fc); }
1942 
1943  private:
1944  __format::__formatter_chrono<_CharT> _M_f;
1945  };
1946 #endif
1947 
1948  template<typename _Duration, typename _CharT>
1949  struct formatter<chrono::sys_time<_Duration>, _CharT>
1950  {
1951  template<typename _ParseContext>
1952  constexpr typename _ParseContext::iterator
1953  parse(_ParseContext& __pc)
1954  {
1955  auto __next = _M_f._M_parse(__pc, __format::_ZonedDateTime);
1956  if constexpr (!__stream_insertable)
1957  if (_M_f._M_spec._M_chrono_specs.empty())
1958  __format::__invalid_chrono_spec(); // chrono-specs can't be empty
1959  return __next;
1960  }
1961 
1962  template<typename _FormatContext>
1963  typename _FormatContext::iterator
1964  format(const chrono::sys_time<_Duration>& __t,
1965  _FormatContext& __fc) const
1966  { return _M_f._M_format(__t, __fc); }
1967 
1968  private:
1969  static constexpr bool __stream_insertable
1970  = requires (basic_ostream<_CharT>& __os,
1971  chrono::sys_time<_Duration> __t) { __os << __t; };
1972 
1973  __format::__formatter_chrono<_CharT> _M_f;
1974  };
1975 
1976  template<typename _Duration, typename _CharT>
1977  struct formatter<chrono::utc_time<_Duration>, _CharT>
1978  : __format::__formatter_chrono<_CharT>
1979  {
1980  template<typename _ParseContext>
1981  constexpr typename _ParseContext::iterator
1982  parse(_ParseContext& __pc)
1983  { return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
1984 
1985  template<typename _FormatContext>
1986  typename _FormatContext::iterator
1987  format(const chrono::utc_time<_Duration>& __t,
1988  _FormatContext& __fc) const
1989  {
1990  // Adjust by removing leap seconds to get equivalent sys_time.
1991  // We can't just use clock_cast because we want to know if the time
1992  // falls within a leap second insertion, and format seconds as "60".
1993  using chrono::__detail::__utc_leap_second;
1994  using chrono::seconds;
1995  using chrono::sys_time;
1996  using _CDur = common_type_t<_Duration, seconds>;
1997  const auto __li = chrono::get_leap_second_info(__t);
1998  sys_time<_CDur> __s{__t.time_since_epoch() - __li.elapsed};
1999  if (!__li.is_leap_second) [[likely]]
2000  return _M_f._M_format(__s, __fc);
2001  else
2002  return _M_f._M_format(__utc_leap_second(__s), __fc);
2003  }
2004 
2005  private:
2006  friend formatter<chrono::__detail::__utc_leap_second<_Duration>, _CharT>;
2007 
2008  __format::__formatter_chrono<_CharT> _M_f;
2009  };
2010 
2011  template<typename _Duration, typename _CharT>
2012  struct formatter<chrono::tai_time<_Duration>, _CharT>
2013  : __format::__formatter_chrono<_CharT>
2014  {
2015  template<typename _ParseContext>
2016  constexpr typename _ParseContext::iterator
2017  parse(_ParseContext& __pc)
2018  { return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
2019 
2020  template<typename _FormatContext>
2021  typename _FormatContext::iterator
2022  format(const chrono::tai_time<_Duration>& __t,
2023  _FormatContext& __fc) const
2024  {
2025  // Convert to __local_time_fmt with abbrev "TAI" and offset 0s.
2026 
2027  // Offset is 1970y/January/1 - 1958y/January/1
2028  constexpr chrono::days __tai_offset = chrono::days(4383);
2029  using _CDur = common_type_t<_Duration, chrono::days>;
2030  chrono::local_time<_CDur> __lt(__t.time_since_epoch() - __tai_offset);
2031  const string __abbrev("TAI", 3);
2032  const chrono::seconds __off = 0s;
2033  const auto __lf = chrono::local_time_format(__lt, &__abbrev, &__off);
2034  return _M_f._M_format(__lf, __fc);
2035  }
2036 
2037  private:
2038  __format::__formatter_chrono<_CharT> _M_f;
2039  };
2040 
2041  template<typename _Duration, typename _CharT>
2042  struct formatter<chrono::gps_time<_Duration>, _CharT>
2043  : __format::__formatter_chrono<_CharT>
2044  {
2045  template<typename _ParseContext>
2046  constexpr typename _ParseContext::iterator
2047  parse(_ParseContext& __pc)
2048  { return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
2049 
2050  template<typename _FormatContext>
2051  typename _FormatContext::iterator
2052  format(const chrono::gps_time<_Duration>& __t,
2053  _FormatContext& __fc) const
2054  {
2055  // Convert to __local_time_fmt with abbrev "GPS" and offset 0s.
2056 
2057  // Offset is 1980y/January/Sunday[1] - 1970y/January/1
2058  constexpr chrono::days __gps_offset = chrono::days(3657);
2059  using _CDur = common_type_t<_Duration, chrono::days>;
2060  chrono::local_time<_CDur> __lt(__t.time_since_epoch() + __gps_offset);
2061  const string __abbrev("GPS", 3);
2062  const chrono::seconds __off = 0s;
2063  const auto __lf = chrono::local_time_format(__lt, &__abbrev, &__off);
2064  return _M_f._M_format(__lf, __fc);
2065  }
2066 
2067  private:
2068  __format::__formatter_chrono<_CharT> _M_f;
2069  };
2070 
2071  template<typename _Duration, typename _CharT>
2072  struct formatter<chrono::file_time<_Duration>, _CharT>
2073  {
2074  template<typename _ParseContext>
2075  constexpr typename _ParseContext::iterator
2076  parse(_ParseContext& __pc)
2077  { return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
2078 
2079  template<typename _FormatContext>
2080  typename _FormatContext::iterator
2081  format(const chrono::file_time<_Duration>& __t,
2082  _FormatContext& __ctx) const
2083  {
2084  using namespace chrono;
2085  return _M_f._M_format(chrono::clock_cast<system_clock>(__t), __ctx);
2086  }
2087 
2088  private:
2089  __format::__formatter_chrono<_CharT> _M_f;
2090  };
2091 
2092  template<typename _Duration, typename _CharT>
2093  struct formatter<chrono::local_time<_Duration>, _CharT>
2094  {
2095  template<typename _ParseContext>
2096  constexpr typename _ParseContext::iterator
2097  parse(_ParseContext& __pc)
2098  { return _M_f._M_parse(__pc, __format::_DateTime); }
2099 
2100  template<typename _FormatContext>
2101  typename _FormatContext::iterator
2102  format(const chrono::local_time<_Duration>& __t,
2103  _FormatContext& __ctx) const
2104  { return _M_f._M_format(__t, __ctx); }
2105 
2106  private:
2107  __format::__formatter_chrono<_CharT> _M_f;
2108  };
2109 
2110  template<typename _Duration, typename _CharT>
2111  struct formatter<chrono::__detail::__local_time_fmt<_Duration>, _CharT>
2112  {
2113  template<typename _ParseContext>
2114  constexpr typename _ParseContext::iterator
2115  parse(_ParseContext& __pc)
2116  { return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
2117 
2118  template<typename _FormatContext>
2119  typename _FormatContext::iterator
2120  format(const chrono::__detail::__local_time_fmt<_Duration>& __t,
2121  _FormatContext& __ctx) const
2122  { return _M_f._M_format(__t, __ctx); }
2123 
2124  private:
2125  __format::__formatter_chrono<_CharT> _M_f;
2126  };
2127 
2128 #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
2129  template<typename _Duration, typename _TimeZonePtr, typename _CharT>
2130  struct formatter<chrono::zoned_time<_Duration, _TimeZonePtr>, _CharT>
2131  : formatter<chrono::__detail::__local_time_fmt<_Duration>, _CharT>
2132  {
2133  template<typename _FormatContext>
2134  typename _FormatContext::iterator
2135  format(const chrono::zoned_time<_Duration, _TimeZonePtr>& __tp,
2136  _FormatContext& __ctx) const
2137  {
2138  using chrono::__detail::__local_time_fmt;
2139  using _Base = formatter<__local_time_fmt<_Duration>, _CharT>;
2140  const chrono::sys_info __info = __tp.get_info();
2141  const auto __lf = chrono::local_time_format(__tp.get_local_time(),
2142  &__info.abbrev,
2143  &__info.offset);
2144  return _Base::format(__lf, __ctx);
2145  }
2146  };
2147 #endif
2148 
2149  // Partial specialization needed for %c formatting of __utc_leap_second.
2150  template<typename _Duration, typename _CharT>
2151  struct formatter<chrono::__detail::__utc_leap_second<_Duration>, _CharT>
2152  : formatter<chrono::utc_time<_Duration>, _CharT>
2153  {
2154  template<typename _FormatContext>
2155  typename _FormatContext::iterator
2156  format(const chrono::__detail::__utc_leap_second<_Duration>& __t,
2157  _FormatContext& __fc) const
2158  { return this->_M_f._M_format(__t, __fc); }
2159  };
2160 
2161 namespace chrono
2162 {
2163 /// @addtogroup chrono
2164 /// @{
2165 
2166  // TODO: from_stream for duration
2167 #if 0
2168  template<typename _CharT, typename _Traits, typename _Rep, typename _Period,
2169  typename _Alloc = allocator<_CharT>>
2170  basic_istream<_CharT, _Traits>&
2171  from_stream(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt,
2172  duration<_Rep, _Period>& __d,
2173  basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr,
2174  minutes* __offset = nullptr)
2175  {
2176  }
2177 #endif
2178 
2179  template<typename _CharT, typename _Traits>
2180  inline basic_ostream<_CharT, _Traits>&
2181  operator<<(basic_ostream<_CharT, _Traits>& __os, const day& __d)
2182  {
2183  using _Ctx = __conditional_t<is_same_v<_CharT, char>,
2184  format_context, wformat_context>;
2185  using _Str = basic_string_view<_CharT>;
2186  _Str __s = _GLIBCXX_WIDEN("{:02d} is not a valid day");
2187  if (__d.ok())
2188  __s = __s.substr(0, 6);
2189  auto __u = (unsigned)__d;
2190  __os << std::vformat(__s, make_format_args<_Ctx>(__u));
2191  return __os;
2192  }
2193 
2194  // TODO from_stream for day
2195 
2196  template<typename _CharT, typename _Traits>
2197  inline basic_ostream<_CharT, _Traits>&
2198  operator<<(basic_ostream<_CharT, _Traits>& __os, const month& __m)
2199  {
2200  using _Ctx = __conditional_t<is_same_v<_CharT, char>,
2201  format_context, wformat_context>;
2202  using _Str = basic_string_view<_CharT>;
2203  _Str __s = _GLIBCXX_WIDEN("{:L%b}{} is not a valid month");
2204  if (__m.ok())
2205  __os << std::vformat(__os.getloc(), __s.substr(0, 6),
2206  make_format_args<_Ctx>(__m));
2207  else
2208  {
2209  auto __u = (unsigned)__m;
2210  __os << std::vformat(__s.substr(6), make_format_args<_Ctx>(__u));
2211  }
2212  return __os;
2213  }
2214 
2215  // TODO from_stream for month
2216 
2217  template<typename _CharT, typename _Traits>
2218  inline basic_ostream<_CharT, _Traits>&
2219  operator<<(basic_ostream<_CharT, _Traits>& __os, const year& __y)
2220  {
2221  using _Ctx = __conditional_t<is_same_v<_CharT, char>,
2222  format_context, wformat_context>;
2223  using _Str = basic_string_view<_CharT>;
2224  _Str __s = _GLIBCXX_WIDEN("-{:04d} is not a valid year");
2225  if (__y.ok())
2226  __s = __s.substr(0, 7);
2227  int __i = (int)__y;
2228  if (__i >= 0) [[likely]]
2229  __s.remove_prefix(1);
2230  else
2231  __i = -__i;
2232  __os << std::vformat(__s, make_format_args<_Ctx>(__i));
2233  return __os;
2234  }
2235 
2236  // TODO from_stream for year
2237 
2238  template<typename _CharT, typename _Traits>
2239  inline basic_ostream<_CharT, _Traits>&
2240  operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday& __wd)
2241  {
2242  using _Ctx = __conditional_t<is_same_v<_CharT, char>,
2243  format_context, wformat_context>;
2244  using _Str = basic_string_view<_CharT>;
2245  _Str __s = _GLIBCXX_WIDEN("{:L%a}{} is not a valid weekday");
2246  if (__wd.ok())
2247  __os << std::vformat(__os.getloc(), __s.substr(0, 6),
2248  make_format_args<_Ctx>(__wd));
2249  else
2250  {
2251  auto __c = __wd.c_encoding();
2252  __os << std::vformat(__s.substr(6), make_format_args<_Ctx>(__c));
2253  }
2254  return __os;
2255  }
2256 
2257  // TODO from_stream for weekday
2258 
2259  template<typename _CharT, typename _Traits>
2260  inline basic_ostream<_CharT, _Traits>&
2261  operator<<(basic_ostream<_CharT, _Traits>& __os,
2262  const weekday_indexed& __wdi)
2263  {
2264  // The standard says to format wdi.weekday() and wdi.index() using
2265  // either "{:L}[{}]" or "{:L}[{} is not a valid index]". The {:L} spec
2266  // means to format the weekday using ostringstream, so just do that.
2267  basic_stringstream<_CharT> __os2;
2268  __os2.imbue(__os.getloc());
2269  __os2 << __wdi.weekday();
2270  const auto __i = __wdi.index();
2271  if constexpr (is_same_v<_CharT, char>)
2272  __os2 << std::format("[{}", __i);
2273  else
2274  __os2 << std::format(L"[{}", __i);
2275  basic_string_view<_CharT> __s = _GLIBCXX_WIDEN(" is not a valid index]");
2276  if (__i >= 1 && __i <= 5)
2277  __os2 << __s.back();
2278  else
2279  __os2 << __s;
2280  __os << __os2.view();
2281  return __os;
2282  }
2283 
2284  template<typename _CharT, typename _Traits>
2285  inline basic_ostream<_CharT, _Traits>&
2286  operator<<(basic_ostream<_CharT, _Traits>& __os,
2287  const weekday_last& __wdl)
2288  {
2289  // As above, just write straight to a stringstream, as if by "{:L}[last]"
2290  basic_stringstream<_CharT> __os2;
2291  __os2.imbue(__os.getloc());
2292  __os2 << __wdl.weekday() << _GLIBCXX_WIDEN("[last]");
2293  __os << __os2.view();
2294  return __os;
2295  }
2296 
2297  template<typename _CharT, typename _Traits>
2298  inline basic_ostream<_CharT, _Traits>&
2299  operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day& __md)
2300  {
2301  // As above, just write straight to a stringstream, as if by "{:L}/{}"
2302  basic_stringstream<_CharT> __os2;
2303  __os2.imbue(__os.getloc());
2304  __os2 << __md.month();
2305  if constexpr (is_same_v<_CharT, char>)
2306  __os2 << '/';
2307  else
2308  __os2 << L'/';
2309  __os2 << __md.day();
2310  __os << __os2.view();
2311  return __os;
2312  }
2313 
2314  // TODO from_stream for month_day
2315 
2316  template<typename _CharT, typename _Traits>
2317  inline basic_ostream<_CharT, _Traits>&
2318  operator<<(basic_ostream<_CharT, _Traits>& __os,
2319  const month_day_last& __mdl)
2320  {
2321  // As above, just write straight to a stringstream, as if by "{:L}/last"
2322  basic_stringstream<_CharT> __os2;
2323  __os2.imbue(__os.getloc());
2324  __os2 << __mdl.month();
2325  if constexpr (is_same_v<_CharT, char>)
2326  __os2 << "/last";
2327  else
2328  __os2 << L"/last";
2329  __os << __os2.view();
2330  return __os;
2331  }
2332 
2333  template<typename _CharT, typename _Traits>
2334  inline basic_ostream<_CharT, _Traits>&
2335  operator<<(basic_ostream<_CharT, _Traits>& __os,
2336  const month_weekday& __mwd)
2337  {
2338  // As above, just write straight to a stringstream, as if by "{:L}/{:L}"
2339  basic_stringstream<_CharT> __os2;
2340  __os2.imbue(__os.getloc());
2341  __os2 << __mwd.month();
2342  if constexpr (is_same_v<_CharT, char>)
2343  __os2 << '/';
2344  else
2345  __os2 << L'/';
2346  __os2 << __mwd.weekday_indexed();
2347  __os << __os2.view();
2348  return __os;
2349  }
2350 
2351  template<typename _CharT, typename _Traits>
2352  inline basic_ostream<_CharT, _Traits>&
2353  operator<<(basic_ostream<_CharT, _Traits>& __os,
2354  const month_weekday_last& __mwdl)
2355  {
2356  // As above, just write straight to a stringstream, as if by "{:L}/{:L}"
2357  basic_stringstream<_CharT> __os2;
2358  __os2.imbue(__os.getloc());
2359  __os2 << __mwdl.month();
2360  if constexpr (is_same_v<_CharT, char>)
2361  __os2 << '/';
2362  else
2363  __os2 << L'/';
2364  __os2 << __mwdl.weekday_last();
2365  __os << __os2.view();
2366  return __os;
2367  }
2368 
2369  template<typename _CharT, typename _Traits>
2370  inline basic_ostream<_CharT, _Traits>&
2371  operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month& __ym)
2372  {
2373  // As above, just write straight to a stringstream, as if by "{}/{:L}"
2374  basic_stringstream<_CharT> __os2;
2375  __os2.imbue(__os.getloc());
2376  __os2 << __ym.year();
2377  if constexpr (is_same_v<_CharT, char>)
2378  __os2 << '/';
2379  else
2380  __os2 << L'/';
2381  __os2 << __ym.month();
2382  __os << __os2.view();
2383  return __os;
2384  }
2385 
2386  // TODO from_stream for year_month
2387 
2388  template<typename _CharT, typename _Traits>
2389  inline basic_ostream<_CharT, _Traits>&
2390  operator<<(basic_ostream<_CharT, _Traits>& __os,
2391  const year_month_day& __ymd)
2392  {
2393  using _Ctx = __conditional_t<is_same_v<_CharT, char>,
2394  format_context, wformat_context>;
2395  using _Str = basic_string_view<_CharT>;
2396  _Str __s = _GLIBCXX_WIDEN("{:%F} is not a valid date");
2397  __os << std::vformat(__ymd.ok() ? __s.substr(0, 5) : __s,
2398  make_format_args<_Ctx>(__ymd));
2399  return __os;
2400  }
2401 
2402  // TODO from_stream for year_month_day
2403 
2404  template<typename _CharT, typename _Traits>
2405  inline basic_ostream<_CharT, _Traits>&
2406  operator<<(basic_ostream<_CharT, _Traits>& __os,
2407  const year_month_day_last& __ymdl)
2408  {
2409  // As above, just write straight to a stringstream, as if by "{}/{:L}"
2410  basic_stringstream<_CharT> __os2;
2411  __os2.imbue(__os.getloc());
2412  __os2 << __ymdl.year();
2413  if constexpr (is_same_v<_CharT, char>)
2414  __os2 << '/';
2415  else
2416  __os2 << L'/';
2417  __os2 << __ymdl.month_day_last();
2418  __os << __os2.view();
2419  return __os;
2420  }
2421 
2422  template<typename _CharT, typename _Traits>
2423  inline basic_ostream<_CharT, _Traits>&
2424  operator<<(basic_ostream<_CharT, _Traits>& __os,
2425  const year_month_weekday& __ymwd)
2426  {
2427  // As above, just write straight to a stringstream, as if by
2428  // "{}/{:L}/{:L}"
2429  basic_stringstream<_CharT> __os2;
2430  __os2.imbue(__os.getloc());
2431  _CharT __slash;
2432  if constexpr (is_same_v<_CharT, char>)
2433  __slash = '/';
2434  else
2435  __slash = L'/';
2436  __os2 << __ymwd.year() << __slash << __ymwd.month() << __slash
2437  << __ymwd.weekday_indexed();
2438  __os << __os2.view();
2439  return __os;
2440  }
2441 
2442  template<typename _CharT, typename _Traits>
2443  inline basic_ostream<_CharT, _Traits>&
2444  operator<<(basic_ostream<_CharT, _Traits>& __os,
2445  const year_month_weekday_last& __ymwdl)
2446  {
2447  // As above, just write straight to a stringstream, as if by
2448  // "{}/{:L}/{:L}"
2449  basic_stringstream<_CharT> __os2;
2450  __os2.imbue(__os.getloc());
2451  _CharT __slash;
2452  if constexpr (is_same_v<_CharT, char>)
2453  __slash = '/';
2454  else
2455  __slash = L'/';
2456  __os2 << __ymwdl.year() << __slash << __ymwdl.month() << __slash
2457  << __ymwdl.weekday_last();
2458  __os << __os2.view();
2459  return __os;
2460  }
2461 
2462  template<typename _CharT, typename _Traits, typename _Duration>
2463  inline basic_ostream<_CharT, _Traits>&
2464  operator<<(basic_ostream<_CharT, _Traits>& __os,
2465  const hh_mm_ss<_Duration>& __hms)
2466  {
2467  return __os << format(__os.getloc(), _GLIBCXX_WIDEN("{:L%T}"), __hms);
2468  }
2469 
2470 #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
2471  /// Writes a sys_info object to an ostream in an unspecified format.
2472  template<typename _CharT, typename _Traits>
2473  basic_ostream<_CharT, _Traits>&
2474  operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_info& __i)
2475  {
2476  __os << '[' << __i.begin << ',' << __i.end
2477  << ',' << hh_mm_ss(__i.offset) << ',' << __i.save
2478  << ',' << __i.abbrev << ']';
2479  return __os;
2480  }
2481 
2482  /// Writes a local_info object to an ostream in an unspecified format.
2483  template<typename _CharT, typename _Traits>
2484  basic_ostream<_CharT, _Traits>&
2485  operator<<(basic_ostream<_CharT, _Traits>& __os, const local_info& __li)
2486  {
2487  __os << '[';
2488  if (__li.result == local_info::unique)
2489  __os << __li.first;
2490  else
2491  {
2492  if (__li.result == local_info::nonexistent)
2493  __os << "nonexistent";
2494  else
2495  __os << "ambiguous";
2496  __os << " local time between " << __li.first;
2497  __os << " and " << __li.second;
2498  }
2499  __os << ']';
2500  return __os;
2501  }
2502 
2503  template<typename _CharT, typename _Traits, typename _Duration,
2504  typename _TimeZonePtr>
2505  inline basic_ostream<_CharT, _Traits>&
2506  operator<<(basic_ostream<_CharT, _Traits>& __os,
2507  const zoned_time<_Duration, _TimeZonePtr>& __t)
2508  {
2509  __os << format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T %Z}"), __t);
2510  return __os;
2511  }
2512 #endif
2513 
2514  template<typename _CharT, typename _Traits, typename _Duration>
2515  requires (!treat_as_floating_point_v<typename _Duration::rep>)
2516  && ratio_less_v<typename _Duration::period, days::period>
2517  inline basic_ostream<_CharT, _Traits>&
2518  operator<<(basic_ostream<_CharT, _Traits>& __os,
2519  const sys_time<_Duration>& __tp)
2520  {
2521  __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __tp);
2522  return __os;
2523  }
2524 
2525  template<typename _CharT, typename _Traits>
2526  inline basic_ostream<_CharT, _Traits>&
2527  operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_days& __dp)
2528  {
2529  __os << year_month_day{__dp};
2530  return __os;
2531  }
2532 
2533  // TODO: from_stream for sys_time
2534 
2535  template<typename _CharT, typename _Traits, typename _Duration>
2536  inline basic_ostream<_CharT, _Traits>&
2537  operator<<(basic_ostream<_CharT, _Traits>& __os,
2538  const utc_time<_Duration>& __t)
2539  {
2540  __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __t);
2541  return __os;
2542  }
2543 
2544  // TODO: from_stream for utc_time
2545 
2546  template<typename _CharT, typename _Traits, typename _Duration>
2547  inline basic_ostream<_CharT, _Traits>&
2548  operator<<(basic_ostream<_CharT, _Traits>& __os,
2549  const tai_time<_Duration>& __t)
2550  {
2551  __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __t);
2552  return __os;
2553  }
2554 
2555  // TODO: from_stream for tai_time
2556 
2557  template<typename _CharT, typename _Traits, typename _Duration>
2558  inline basic_ostream<_CharT, _Traits>&
2559  operator<<(basic_ostream<_CharT, _Traits>& __os,
2560  const gps_time<_Duration>& __t)
2561  {
2562  __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __t);
2563  return __os;
2564  }
2565 
2566  // TODO: from_stream for gps_time
2567 
2568 
2569  template<typename _CharT, typename _Traits, typename _Duration>
2570  inline basic_ostream<_CharT, _Traits>&
2571  operator<<(basic_ostream<_CharT, _Traits>& __os,
2572  const file_time<_Duration>& __t)
2573  {
2574  __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __t);
2575  return __os;
2576  }
2577 
2578  // TODO: from_stream for file_time
2579 
2580  template<typename _CharT, typename _Traits, typename _Duration>
2581  inline basic_ostream<_CharT, _Traits>&
2582  operator<<(basic_ostream<_CharT, _Traits>& __os,
2583  const local_time<_Duration>& __lt)
2584  {
2585  __os << sys_time<_Duration>{__lt.time_since_epoch()};
2586  return __os;
2587  }
2588 
2589  // TODO: from_stream for local_time
2590 #undef _GLIBCXX_WIDEN
2591 
2592  /// @} group chrono
2593 } // namespace chrono
2594 
2595 _GLIBCXX_END_NAMESPACE_VERSION
2596 } // namespace std
2597 
2598 #endif // C++20
2599 
2600 #endif //_GLIBCXX_CHRONO_IO_H
basic_ostream< _CharT, _Traits > & operator<<(std::basic_ostream< _CharT, _Traits > &__os, const duration< _Rep, _Period > &__d)
Definition: chrono_io.h:139
duration< int64_t, ratio< 86400 > > days
days
Definition: chrono.h:907
__detail::__local_time_fmt< _Duration > local_time_format(local_time< _Duration > __time, const string *__abbrev=nullptr, const seconds *__offset_sec=nullptr)
Definition: chrono_io.h:181
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:97
ISO C++ entities toplevel namespace is std.
constexpr bitset< _Nb > operator|(const bitset< _Nb > &__x, const bitset< _Nb > &__y) noexcept
Global bitwise operations on bitsets.
Definition: bitset:1563
constexpr auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())
Return the size of a container.
Definition: range_access.h:264
locale imbue(const locale &__loc)
Moves to a new locale.
Definition: basic_ios.tcc:114
Template class basic_ostream.
Definition: ostream:61
Controlling output for std::string.
Definition: sstream:772
Provides output iterator semantics for streambufs.
Provides compile-time rational arithmetic.
Definition: ratio:267
A non-owning reference to a string.
Definition: string_view:107
chrono::duration represents a distance between two points in time
Definition: chrono.h:512
chrono::time_point represents a point in time as measured by a clock
Definition: chrono.h:923
iterator begin()
Definition: cow_string.h:805
streamsize precision() const
Flags access.
Definition: ios_base.h:732
fmtflags flags() const
Access to format flags.
Definition: ios_base.h:662
static const locale & classic()
Return reference to the C locale.