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