HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
chrono.h
Go to the documentation of this file.
1 // Formatting library for C++ - chrono support
2 //
3 // Copyright (c) 2012 - present, Victor Zverovich
4 // All rights reserved.
5 //
6 // For the license information refer to format.h.
7 
8 #ifndef FMT_CHRONO_H_
9 #define FMT_CHRONO_H_
10 
11 #include <algorithm>
12 #include <chrono>
13 #include <cmath> // std::isfinite
14 #include <cstring> // std::memcpy
15 #include <ctime>
16 #include <iterator>
17 #include <locale>
18 #include <ostream>
19 #include <type_traits>
20 
21 #include "format.h"
22 
24 
25 // Check if std::chrono::local_t is available.
26 #ifndef FMT_USE_LOCAL_TIME
27 # ifdef __cpp_lib_chrono
28 # define FMT_USE_LOCAL_TIME (__cpp_lib_chrono >= 201907L)
29 # else
30 # define FMT_USE_LOCAL_TIME 0
31 # endif
32 #endif
33 
34 // Check if std::chrono::utc_timestamp is available.
35 #ifndef FMT_USE_UTC_TIME
36 # ifdef __cpp_lib_chrono
37 # define FMT_USE_UTC_TIME (__cpp_lib_chrono >= 201907L)
38 # else
39 # define FMT_USE_UTC_TIME 0
40 # endif
41 #endif
42 
43 // Enable tzset.
44 #ifndef FMT_USE_TZSET
45 // UWP doesn't provide _tzset.
46 # if FMT_HAS_INCLUDE("winapifamily.h")
47 # include <winapifamily.h>
48 # endif
49 # if defined(_WIN32) && (!defined(WINAPI_FAMILY) || \
50  (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
51 # define FMT_USE_TZSET 1
52 # else
53 # define FMT_USE_TZSET 0
54 # endif
55 #endif
56 
57 // Enable safe chrono durations, unless explicitly disabled.
58 #ifndef FMT_SAFE_DURATION_CAST
59 # define FMT_SAFE_DURATION_CAST 1
60 #endif
61 #if FMT_SAFE_DURATION_CAST
62 
63 // For conversion between std::chrono::durations without undefined
64 // behaviour or erroneous results.
65 // This is a stripped down version of duration_cast, for inclusion in fmt.
66 // See https://github.com/pauldreik/safe_duration_cast
67 //
68 // Copyright Paul Dreik 2019
69 namespace safe_duration_cast {
70 
71 template <typename To, typename From,
75 FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {
76  ec = 0;
77  using F = std::numeric_limits<From>;
78  using T = std::numeric_limits<To>;
79  static_assert(F::is_integer, "From must be integral");
80  static_assert(T::is_integer, "To must be integral");
81 
82  // A and B are both signed, or both unsigned.
83  if (detail::const_check(F::digits <= T::digits)) {
84  // From fits in To without any problem.
85  } else {
86  // From does not always fit in To, resort to a dynamic check.
87  if (from < (T::min)() || from > (T::max)()) {
88  // outside range.
89  ec = 1;
90  return {};
91  }
92  }
93  return static_cast<To>(from);
94 }
95 
96 /**
97  * converts From to To, without loss. If the dynamic value of from
98  * can't be converted to To without loss, ec is set.
99  */
100 template <typename To, typename From,
104 FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {
105  ec = 0;
106  using F = std::numeric_limits<From>;
107  using T = std::numeric_limits<To>;
108  static_assert(F::is_integer, "From must be integral");
109  static_assert(T::is_integer, "To must be integral");
110 
112  // From may be negative, not allowed!
113  if (fmt::detail::is_negative(from)) {
114  ec = 1;
115  return {};
116  }
117  // From is positive. Can it always fit in To?
118  if (detail::const_check(F::digits > T::digits) &&
119  from > static_cast<From>(detail::max_value<To>())) {
120  ec = 1;
121  return {};
122  }
123  }
124 
126  F::digits >= T::digits) &&
127  from > static_cast<From>(detail::max_value<To>())) {
128  ec = 1;
129  return {};
130  }
131  return static_cast<To>(from); // Lossless conversion.
132 }
133 
134 template <typename To, typename From,
136 FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {
137  ec = 0;
138  return from;
139 } // function
140 
141 // clang-format off
142 /**
143  * converts From to To if possible, otherwise ec is set.
144  *
145  * input | output
146  * ---------------------------------|---------------
147  * NaN | NaN
148  * Inf | Inf
149  * normal, fits in output | converted (possibly lossy)
150  * normal, does not fit in output | ec is set
151  * subnormal | best effort
152  * -Inf | -Inf
153  */
154 // clang-format on
155 template <typename To, typename From,
157 FMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) {
158  ec = 0;
159  using T = std::numeric_limits<To>;
160  static_assert(std::is_floating_point<From>::value, "From must be floating");
161  static_assert(std::is_floating_point<To>::value, "To must be floating");
162 
163  // catch the only happy case
164  if (std::isfinite(from)) {
165  if (from >= T::lowest() && from <= (T::max)()) {
166  return static_cast<To>(from);
167  }
168  // not within range.
169  ec = 1;
170  return {};
171  }
172 
173  // nan and inf will be preserved
174  return static_cast<To>(from);
175 } // function
176 
177 template <typename To, typename From,
179 FMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) {
180  ec = 0;
181  static_assert(std::is_floating_point<From>::value, "From must be floating");
182  return from;
183 }
184 
185 /**
186  * safe duration cast between integral durations
187  */
188 template <typename To, typename FromRep, typename FromPeriod,
191 To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
192  int& ec) {
193  using From = std::chrono::duration<FromRep, FromPeriod>;
194  ec = 0;
195  // the basic idea is that we need to convert from count() in the from type
196  // to count() in the To type, by multiplying it with this:
197  struct Factor
198  : std::ratio_divide<typename From::period, typename To::period> {};
199 
200  static_assert(Factor::num > 0, "num must be positive");
201  static_assert(Factor::den > 0, "den must be positive");
202 
203  // the conversion is like this: multiply from.count() with Factor::num
204  // /Factor::den and convert it to To::rep, all this without
205  // overflow/underflow. let's start by finding a suitable type that can hold
206  // both To, From and Factor::num
207  using IntermediateRep =
208  typename std::common_type<typename From::rep, typename To::rep,
209  decltype(Factor::num)>::type;
210 
211  // safe conversion to IntermediateRep
212  IntermediateRep count =
213  lossless_integral_conversion<IntermediateRep>(from.count(), ec);
214  if (ec) return {};
215  // multiply with Factor::num without overflow or underflow
216  if (detail::const_check(Factor::num != 1)) {
217  const auto max1 = detail::max_value<IntermediateRep>() / Factor::num;
218  if (count > max1) {
219  ec = 1;
220  return {};
221  }
222  const auto min1 =
225  count < min1) {
226  ec = 1;
227  return {};
228  }
229  count *= Factor::num;
230  }
231 
232  if (detail::const_check(Factor::den != 1)) count /= Factor::den;
233  auto tocount = lossless_integral_conversion<typename To::rep>(count, ec);
234  return ec ? To() : To(tocount);
235 }
236 
237 /**
238  * safe duration_cast between floating point durations
239  */
240 template <typename To, typename FromRep, typename FromPeriod,
243 To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
244  int& ec) {
245  using From = std::chrono::duration<FromRep, FromPeriod>;
246  ec = 0;
247  if (std::isnan(from.count())) {
248  // nan in, gives nan out. easy.
249  return To{std::numeric_limits<typename To::rep>::quiet_NaN()};
250  }
251  // maybe we should also check if from is denormal, and decide what to do about
252  // it.
253 
254  // +-inf should be preserved.
255  if (std::isinf(from.count())) {
256  return To{from.count()};
257  }
258 
259  // the basic idea is that we need to convert from count() in the from type
260  // to count() in the To type, by multiplying it with this:
261  struct Factor
262  : std::ratio_divide<typename From::period, typename To::period> {};
263 
264  static_assert(Factor::num > 0, "num must be positive");
265  static_assert(Factor::den > 0, "den must be positive");
266 
267  // the conversion is like this: multiply from.count() with Factor::num
268  // /Factor::den and convert it to To::rep, all this without
269  // overflow/underflow. let's start by finding a suitable type that can hold
270  // both To, From and Factor::num
271  using IntermediateRep =
272  typename std::common_type<typename From::rep, typename To::rep,
273  decltype(Factor::num)>::type;
274 
275  // force conversion of From::rep -> IntermediateRep to be safe,
276  // even if it will never happen be narrowing in this context.
277  IntermediateRep count =
278  safe_float_conversion<IntermediateRep>(from.count(), ec);
279  if (ec) {
280  return {};
281  }
282 
283  // multiply with Factor::num without overflow or underflow
284  if (detail::const_check(Factor::num != 1)) {
285  constexpr auto max1 = detail::max_value<IntermediateRep>() /
286  static_cast<IntermediateRep>(Factor::num);
287  if (count > max1) {
288  ec = 1;
289  return {};
290  }
291  constexpr auto min1 = std::numeric_limits<IntermediateRep>::lowest() /
292  static_cast<IntermediateRep>(Factor::num);
293  if (count < min1) {
294  ec = 1;
295  return {};
296  }
297  count *= static_cast<IntermediateRep>(Factor::num);
298  }
299 
300  // this can't go wrong, right? den>0 is checked earlier.
301  if (detail::const_check(Factor::den != 1)) {
302  using common_t = typename std::common_type<IntermediateRep, intmax_t>::type;
303  count /= static_cast<common_t>(Factor::den);
304  }
305 
306  // convert to the to type, safely
307  using ToRep = typename To::rep;
308 
309  const ToRep tocount = safe_float_conversion<ToRep>(count, ec);
310  if (ec) {
311  return {};
312  }
313  return To{tocount};
314 }
315 } // namespace safe_duration_cast
316 #endif
317 
318 // Prevents expansion of a preceding token as a function-style macro.
319 // Usage: f FMT_NOMACRO()
320 #define FMT_NOMACRO
321 
322 namespace detail {
323 template <typename T = void> struct null {};
324 inline null<> localtime_r FMT_NOMACRO(...) { return null<>(); }
325 inline null<> localtime_s(...) { return null<>(); }
326 inline null<> gmtime_r(...) { return null<>(); }
327 inline null<> gmtime_s(...) { return null<>(); }
328 
330  static const auto& locale = std::locale::classic();
331  return locale;
332 }
333 
334 template <typename CodeUnit> struct codecvt_result {
335  static constexpr const size_t max_size = 32;
336  CodeUnit buf[max_size];
337  CodeUnit* end;
338 };
339 template <typename CodeUnit>
340 constexpr const size_t codecvt_result<CodeUnit>::max_size;
341 
342 template <typename CodeUnit>
344  const std::locale& loc) {
345 #if FMT_CLANG_VERSION
346 # pragma clang diagnostic push
347 # pragma clang diagnostic ignored "-Wdeprecated"
348  auto& f = std::use_facet<std::codecvt<CodeUnit, char, std::mbstate_t>>(loc);
349 # pragma clang diagnostic pop
350 #else
351  auto& f = std::use_facet<std::codecvt<CodeUnit, char, std::mbstate_t>>(loc);
352 #endif
353  auto mb = std::mbstate_t();
354  const char* from_next = nullptr;
355  auto result = f.in(mb, in_buf.begin(), in_buf.end(), from_next,
356  std::begin(out.buf), std::end(out.buf), out.end);
357  if (result != std::codecvt_base::ok)
358  FMT_THROW(format_error("failed to format time"));
359 }
360 
361 template <typename OutputIt>
362 auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale& loc)
363  -> OutputIt {
364  if (detail::is_utf8() && loc != get_classic_locale()) {
365  // char16_t and char32_t codecvts are broken in MSVC (linkage errors) and
366  // gcc-4.
367 #if FMT_MSC_VERSION != 0 || \
368  (defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI))
369  // The _GLIBCXX_USE_DUAL_ABI macro is always defined in libstdc++ from gcc-5
370  // and newer.
371  using code_unit = wchar_t;
372 #else
373  using code_unit = char32_t;
374 #endif
375 
376  using unit_t = codecvt_result<code_unit>;
377  unit_t unit;
378  write_codecvt(unit, in, loc);
379  // In UTF-8 is used one to four one-byte code units.
381  u;
382  if (!u.convert({unit.buf, to_unsigned(unit.end - unit.buf)}))
383  FMT_THROW(format_error("failed to format time"));
384  return copy_str<char>(u.c_str(), u.c_str() + u.size(), out);
385  }
386  return copy_str<char>(in.data(), in.data() + in.size(), out);
387 }
388 
389 template <typename Char, typename OutputIt,
391 auto write_tm_str(OutputIt out, string_view sv, const std::locale& loc)
392  -> OutputIt {
394  write_codecvt(unit, sv, loc);
395  return copy_str<Char>(unit.buf, unit.end, out);
396 }
397 
398 template <typename Char, typename OutputIt,
400 auto write_tm_str(OutputIt out, string_view sv, const std::locale& loc)
401  -> OutputIt {
402  return write_encoded_tm_str(out, sv, loc);
403 }
404 
405 template <typename Char>
406 inline void do_write(buffer<Char>& buf, const std::tm& time,
407  const std::locale& loc, char format, char modifier) {
408  auto&& format_buf = formatbuf<std::basic_streambuf<Char>>(buf);
409  auto&& os = std::basic_ostream<Char>(&format_buf);
410  os.imbue(loc);
411  using iterator = std::ostreambuf_iterator<Char>;
412  const auto& facet = std::use_facet<std::time_put<Char, iterator>>(loc);
413  auto end = facet.put(os, os, Char(' '), &time, format, modifier);
414  if (end.failed()) FMT_THROW(format_error("failed to format time"));
415 }
416 
417 template <typename Char, typename OutputIt,
419 auto write(OutputIt out, const std::tm& time, const std::locale& loc,
420  char format, char modifier = 0) -> OutputIt {
421  auto&& buf = get_buffer<Char>(out);
422  do_write<Char>(buf, time, loc, format, modifier);
423  return get_iterator(buf, out);
424 }
425 
426 template <typename Char, typename OutputIt,
428 auto write(OutputIt out, const std::tm& time, const std::locale& loc,
429  char format, char modifier = 0) -> OutputIt {
430  auto&& buf = basic_memory_buffer<Char>();
431  do_write<char>(buf, time, loc, format, modifier);
432  return write_encoded_tm_str(out, string_view(buf.data(), buf.size()), loc);
433 }
434 
435 } // namespace detail
436 
438 
439 /**
440  Converts given time since epoch as ``std::time_t`` value into calendar time,
441  expressed in local time. Unlike ``std::localtime``, this function is
442  thread-safe on most platforms.
443  */
444 inline std::tm localtime(std::time_t time) {
445  struct dispatcher {
446  std::time_t time_;
447  std::tm tm_;
448 
449  dispatcher(std::time_t t) : time_(t) {}
450 
451  bool run() {
452  using namespace fmt::detail;
453  return handle(localtime_r(&time_, &tm_));
454  }
455 
456  bool handle(std::tm* tm) { return tm != nullptr; }
457 
458  bool handle(detail::null<>) {
459  using namespace fmt::detail;
460  return fallback(localtime_s(&tm_, &time_));
461  }
462 
463  bool fallback(int res) { return res == 0; }
464 
465 #if !FMT_MSC_VERSION
466  bool fallback(detail::null<>) {
467  using namespace fmt::detail;
468  std::tm* tm = std::localtime(&time_);
469  if (tm) tm_ = *tm;
470  return tm != nullptr;
471  }
472 #endif
473  };
474  dispatcher lt(time);
475  // Too big time values may be unsupported.
476  if (!lt.run()) FMT_THROW(format_error("time_t value out of range"));
477  return lt.tm_;
478 }
479 
480 #if FMT_USE_LOCAL_TIME
481 template <typename Duration>
482 inline auto localtime(std::chrono::local_time<Duration> time) -> std::tm {
483  return localtime(std::chrono::system_clock::to_time_t(
484  std::chrono::current_zone()->to_sys(time)));
485 }
486 #endif
487 
488 /**
489  Converts given time since epoch as ``std::time_t`` value into calendar time,
490  expressed in Coordinated Universal Time (UTC). Unlike ``std::gmtime``, this
491  function is thread-safe on most platforms.
492  */
493 inline std::tm gmtime(std::time_t time) {
494  struct dispatcher {
495  std::time_t time_;
496  std::tm tm_;
497 
498  dispatcher(std::time_t t) : time_(t) {}
499 
500  bool run() {
501  using namespace fmt::detail;
502  return handle(gmtime_r(&time_, &tm_));
503  }
504 
505  bool handle(std::tm* tm) { return tm != nullptr; }
506 
507  bool handle(detail::null<>) {
508  using namespace fmt::detail;
509  return fallback(gmtime_s(&tm_, &time_));
510  }
511 
512  bool fallback(int res) { return res == 0; }
513 
514 #if !FMT_MSC_VERSION
515  bool fallback(detail::null<>) {
516  std::tm* tm = std::gmtime(&time_);
517  if (tm) tm_ = *tm;
518  return tm != nullptr;
519  }
520 #endif
521  };
522  dispatcher gt(time);
523  // Too big time values may be unsupported.
524  if (!gt.run()) FMT_THROW(format_error("time_t value out of range"));
525  return gt.tm_;
526 }
527 
528 inline std::tm gmtime(
529  std::chrono::time_point<std::chrono::system_clock> time_point) {
530  return gmtime(std::chrono::system_clock::to_time_t(time_point));
531 }
532 
534 
535 // DEPRECATED!
536 template <typename Char>
537 FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,
538  format_specs<Char>& specs) -> const Char* {
539  FMT_ASSERT(begin != end, "");
540  auto align = align::none;
541  auto p = begin + code_point_length(begin);
542  if (end - p <= 0) p = begin;
543  for (;;) {
544  switch (to_ascii(*p)) {
545  case '<':
546  align = align::left;
547  break;
548  case '>':
549  align = align::right;
550  break;
551  case '^':
552  align = align::center;
553  break;
554  }
555  if (align != align::none) {
556  if (p != begin) {
557  auto c = *begin;
558  if (c == '}') return begin;
559  if (c == '{') {
560  throw_format_error("invalid fill character '{'");
561  return begin;
562  }
563  specs.fill = {begin, to_unsigned(p - begin)};
564  begin = p + 1;
565  } else {
566  ++begin;
567  }
568  break;
569  } else if (p == begin) {
570  break;
571  }
572  p = begin;
573  }
574  specs.align = align;
575  return begin;
576 }
577 
578 // Writes two-digit numbers a, b and c separated by sep to buf.
579 // The method by Pavel Novikov based on
580 // https://johnnylee-sde.github.io/Fast-unsigned-integer-to-time-string/.
581 inline void write_digit2_separated(char* buf, unsigned a, unsigned b,
582  unsigned c, char sep) {
583  unsigned long long digits =
585  // Convert each value to BCD.
586  // We have x = a * 10 + b and we want to convert it to BCD y = a * 16 + b.
587  // The difference is
588  // y - x = a * 6
589  // a can be found from x:
590  // a = floor(x / 10)
591  // then
592  // y = x + a * 6 = x + floor(x / 10) * 6
593  // floor(x / 10) is (x * 205) >> 11 (needs 16 bits).
594  digits += (((digits * 205) >> 11) & 0x000f00000f00000f) * 6;
595  // Put low nibbles to high bytes and high nibbles to low bytes.
596  digits = ((digits & 0x00f00000f00000f0) >> 4) |
597  ((digits & 0x000f00000f00000f) << 8);
598  auto usep = static_cast<unsigned long long>(sep);
599  // Add ASCII '0' to each digit byte and insert separators.
600  digits |= 0x3030003030003030 | (usep << 16) | (usep << 40);
601 
602  constexpr const size_t len = 8;
603  if (const_check(is_big_endian())) {
604  char tmp[len];
605  std::memcpy(tmp, &digits, len);
606  std::reverse_copy(tmp, tmp + len, buf);
607  } else {
608  std::memcpy(buf, &digits, len);
609  }
610 }
611 
612 template <typename Period> FMT_CONSTEXPR inline const char* get_units() {
617  if (std::is_same<Period, std::micro>::value) return "µs";
621  if (std::is_same<Period, std::ratio<1>>::value) return "s";
622  if (std::is_same<Period, std::deca>::value) return "das";
629  if (std::is_same<Period, std::exa>::value) return "Es";
630  if (std::is_same<Period, std::ratio<60>>::value) return "m";
631  if (std::is_same<Period, std::ratio<3600>>::value) return "h";
632  return nullptr;
633 }
634 
635 enum class numeric_system {
636  standard,
637  // Alternative numeric system, e.g. 十二 instead of 12 in ja_JP locale.
639 };
640 
641 // Glibc extensions for formatting numeric values.
642 enum class pad_type {
643  unspecified,
644  // Do not pad a numeric result string.
645  none,
646  // Pad a numeric result string with zeros even if the conversion specifier
647  // character uses space-padding by default.
648  zero,
649  // Pad a numeric result string with spaces.
650  space,
651 };
652 
653 template <typename OutputIt>
654 auto write_padding(OutputIt out, pad_type pad, int width) -> OutputIt {
655  if (pad == pad_type::none) return out;
656  return std::fill_n(out, width, pad == pad_type::space ? ' ' : '0');
657 }
658 
659 template <typename OutputIt>
660 auto write_padding(OutputIt out, pad_type pad) -> OutputIt {
661  if (pad != pad_type::none) *out++ = pad == pad_type::space ? ' ' : '0';
662  return out;
663 }
664 
665 // Parses a put_time-like format string and invokes handler actions.
666 template <typename Char, typename Handler>
667 FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin,
668  const Char* end,
669  Handler&& handler) {
670  if (begin == end || *begin == '}') return begin;
671  if (*begin != '%') FMT_THROW(format_error("invalid format"));
672  auto ptr = begin;
674  while (ptr != end) {
675  auto c = *ptr;
676  if (c == '}') break;
677  if (c != '%') {
678  ++ptr;
679  continue;
680  }
681  if (begin != ptr) handler.on_text(begin, ptr);
682  ++ptr; // consume '%'
683  if (ptr == end) FMT_THROW(format_error("invalid format"));
684  c = *ptr;
685  switch (c) {
686  case '_':
687  pad = pad_type::space;
688  ++ptr;
689  break;
690  case '-':
691  pad = pad_type::none;
692  ++ptr;
693  break;
694  case '0':
695  pad = pad_type::zero;
696  ++ptr;
697  break;
698  }
699  if (ptr == end) FMT_THROW(format_error("invalid format"));
700  c = *ptr++;
701  switch (c) {
702  case '%':
703  handler.on_text(ptr - 1, ptr);
704  break;
705  case 'n': {
706  const Char newline[] = {'\n'};
707  handler.on_text(newline, newline + 1);
708  break;
709  }
710  case 't': {
711  const Char tab[] = {'\t'};
712  handler.on_text(tab, tab + 1);
713  break;
714  }
715  // Year:
716  case 'Y':
717  handler.on_year(numeric_system::standard);
718  break;
719  case 'y':
720  handler.on_short_year(numeric_system::standard);
721  break;
722  case 'C':
723  handler.on_century(numeric_system::standard);
724  break;
725  case 'G':
726  handler.on_iso_week_based_year();
727  break;
728  case 'g':
729  handler.on_iso_week_based_short_year();
730  break;
731  // Day of the week:
732  case 'a':
733  handler.on_abbr_weekday();
734  break;
735  case 'A':
736  handler.on_full_weekday();
737  break;
738  case 'w':
739  handler.on_dec0_weekday(numeric_system::standard);
740  break;
741  case 'u':
742  handler.on_dec1_weekday(numeric_system::standard);
743  break;
744  // Month:
745  case 'b':
746  case 'h':
747  handler.on_abbr_month();
748  break;
749  case 'B':
750  handler.on_full_month();
751  break;
752  case 'm':
753  handler.on_dec_month(numeric_system::standard);
754  break;
755  // Day of the year/month:
756  case 'U':
757  handler.on_dec0_week_of_year(numeric_system::standard);
758  break;
759  case 'W':
760  handler.on_dec1_week_of_year(numeric_system::standard);
761  break;
762  case 'V':
763  handler.on_iso_week_of_year(numeric_system::standard);
764  break;
765  case 'j':
766  handler.on_day_of_year();
767  break;
768  case 'd':
769  handler.on_day_of_month(numeric_system::standard);
770  break;
771  case 'e':
772  handler.on_day_of_month_space(numeric_system::standard);
773  break;
774  // Hour, minute, second:
775  case 'H':
776  handler.on_24_hour(numeric_system::standard, pad);
777  break;
778  case 'I':
779  handler.on_12_hour(numeric_system::standard, pad);
780  break;
781  case 'M':
782  handler.on_minute(numeric_system::standard, pad);
783  break;
784  case 'S':
785  handler.on_second(numeric_system::standard, pad);
786  break;
787  // Other:
788  case 'c':
789  handler.on_datetime(numeric_system::standard);
790  break;
791  case 'x':
792  handler.on_loc_date(numeric_system::standard);
793  break;
794  case 'X':
795  handler.on_loc_time(numeric_system::standard);
796  break;
797  case 'D':
798  handler.on_us_date();
799  break;
800  case 'F':
801  handler.on_iso_date();
802  break;
803  case 'r':
804  handler.on_12_hour_time();
805  break;
806  case 'R':
807  handler.on_24_hour_time();
808  break;
809  case 'T':
810  handler.on_iso_time();
811  break;
812  case 'p':
813  handler.on_am_pm();
814  break;
815  case 'Q':
816  handler.on_duration_value();
817  break;
818  case 'q':
819  handler.on_duration_unit();
820  break;
821  case 'z':
822  handler.on_utc_offset(numeric_system::standard);
823  break;
824  case 'Z':
825  handler.on_tz_name();
826  break;
827  // Alternative representation:
828  case 'E': {
829  if (ptr == end) FMT_THROW(format_error("invalid format"));
830  c = *ptr++;
831  switch (c) {
832  case 'Y':
833  handler.on_year(numeric_system::alternative);
834  break;
835  case 'y':
836  handler.on_offset_year();
837  break;
838  case 'C':
839  handler.on_century(numeric_system::alternative);
840  break;
841  case 'c':
842  handler.on_datetime(numeric_system::alternative);
843  break;
844  case 'x':
845  handler.on_loc_date(numeric_system::alternative);
846  break;
847  case 'X':
848  handler.on_loc_time(numeric_system::alternative);
849  break;
850  case 'z':
851  handler.on_utc_offset(numeric_system::alternative);
852  break;
853  default:
854  FMT_THROW(format_error("invalid format"));
855  }
856  break;
857  }
858  case 'O':
859  if (ptr == end) FMT_THROW(format_error("invalid format"));
860  c = *ptr++;
861  switch (c) {
862  case 'y':
863  handler.on_short_year(numeric_system::alternative);
864  break;
865  case 'm':
866  handler.on_dec_month(numeric_system::alternative);
867  break;
868  case 'U':
869  handler.on_dec0_week_of_year(numeric_system::alternative);
870  break;
871  case 'W':
872  handler.on_dec1_week_of_year(numeric_system::alternative);
873  break;
874  case 'V':
875  handler.on_iso_week_of_year(numeric_system::alternative);
876  break;
877  case 'd':
878  handler.on_day_of_month(numeric_system::alternative);
879  break;
880  case 'e':
881  handler.on_day_of_month_space(numeric_system::alternative);
882  break;
883  case 'w':
884  handler.on_dec0_weekday(numeric_system::alternative);
885  break;
886  case 'u':
887  handler.on_dec1_weekday(numeric_system::alternative);
888  break;
889  case 'H':
890  handler.on_24_hour(numeric_system::alternative, pad);
891  break;
892  case 'I':
893  handler.on_12_hour(numeric_system::alternative, pad);
894  break;
895  case 'M':
896  handler.on_minute(numeric_system::alternative, pad);
897  break;
898  case 'S':
899  handler.on_second(numeric_system::alternative, pad);
900  break;
901  case 'z':
902  handler.on_utc_offset(numeric_system::alternative);
903  break;
904  default:
905  FMT_THROW(format_error("invalid format"));
906  }
907  break;
908  default:
909  FMT_THROW(format_error("invalid format"));
910  }
911  begin = ptr;
912  }
913  if (begin != ptr) handler.on_text(begin, ptr);
914  return ptr;
915 }
916 
917 template <typename Derived> struct null_chrono_spec_handler {
919  static_cast<Derived*>(this)->unsupported();
920  }
921  FMT_CONSTEXPR void on_year(numeric_system) { unsupported(); }
922  FMT_CONSTEXPR void on_short_year(numeric_system) { unsupported(); }
923  FMT_CONSTEXPR void on_offset_year() { unsupported(); }
924  FMT_CONSTEXPR void on_century(numeric_system) { unsupported(); }
925  FMT_CONSTEXPR void on_iso_week_based_year() { unsupported(); }
926  FMT_CONSTEXPR void on_iso_week_based_short_year() { unsupported(); }
927  FMT_CONSTEXPR void on_abbr_weekday() { unsupported(); }
928  FMT_CONSTEXPR void on_full_weekday() { unsupported(); }
931  FMT_CONSTEXPR void on_abbr_month() { unsupported(); }
932  FMT_CONSTEXPR void on_full_month() { unsupported(); }
933  FMT_CONSTEXPR void on_dec_month(numeric_system) { unsupported(); }
937  FMT_CONSTEXPR void on_day_of_year() { unsupported(); }
940  FMT_CONSTEXPR void on_24_hour(numeric_system) { unsupported(); }
941  FMT_CONSTEXPR void on_12_hour(numeric_system) { unsupported(); }
942  FMT_CONSTEXPR void on_minute(numeric_system) { unsupported(); }
943  FMT_CONSTEXPR void on_second(numeric_system) { unsupported(); }
944  FMT_CONSTEXPR void on_datetime(numeric_system) { unsupported(); }
945  FMT_CONSTEXPR void on_loc_date(numeric_system) { unsupported(); }
946  FMT_CONSTEXPR void on_loc_time(numeric_system) { unsupported(); }
947  FMT_CONSTEXPR void on_us_date() { unsupported(); }
948  FMT_CONSTEXPR void on_iso_date() { unsupported(); }
949  FMT_CONSTEXPR void on_12_hour_time() { unsupported(); }
950  FMT_CONSTEXPR void on_24_hour_time() { unsupported(); }
951  FMT_CONSTEXPR void on_iso_time() { unsupported(); }
952  FMT_CONSTEXPR void on_am_pm() { unsupported(); }
953  FMT_CONSTEXPR void on_duration_value() { unsupported(); }
954  FMT_CONSTEXPR void on_duration_unit() { unsupported(); }
955  FMT_CONSTEXPR void on_utc_offset(numeric_system) { unsupported(); }
956  FMT_CONSTEXPR void on_tz_name() { unsupported(); }
957 };
958 
959 struct tm_format_checker : null_chrono_spec_handler<tm_format_checker> {
960  FMT_NORETURN void unsupported() { FMT_THROW(format_error("no format")); }
961 
962  template <typename Char>
963  FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
998 };
999 
1000 inline const char* tm_wday_full_name(int wday) {
1001  static constexpr const char* full_name_list[] = {
1002  "Sunday", "Monday", "Tuesday", "Wednesday",
1003  "Thursday", "Friday", "Saturday"};
1004  return wday >= 0 && wday <= 6 ? full_name_list[wday] : "?";
1005 }
1006 inline const char* tm_wday_short_name(int wday) {
1007  static constexpr const char* short_name_list[] = {"Sun", "Mon", "Tue", "Wed",
1008  "Thu", "Fri", "Sat"};
1009  return wday >= 0 && wday <= 6 ? short_name_list[wday] : "???";
1010 }
1011 
1012 inline const char* tm_mon_full_name(int mon) {
1013  static constexpr const char* full_name_list[] = {
1014  "January", "February", "March", "April", "May", "June",
1015  "July", "August", "September", "October", "November", "December"};
1016  return mon >= 0 && mon <= 11 ? full_name_list[mon] : "?";
1017 }
1018 inline const char* tm_mon_short_name(int mon) {
1019  static constexpr const char* short_name_list[] = {
1020  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1021  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
1022  };
1023  return mon >= 0 && mon <= 11 ? short_name_list[mon] : "???";
1024 }
1025 
1026 template <typename T, typename = void>
1027 struct has_member_data_tm_gmtoff : std::false_type {};
1028 template <typename T>
1029 struct has_member_data_tm_gmtoff<T, void_t<decltype(T::tm_gmtoff)>>
1030  : std::true_type {};
1031 
1032 template <typename T, typename = void>
1033 struct has_member_data_tm_zone : std::false_type {};
1034 template <typename T>
1035 struct has_member_data_tm_zone<T, void_t<decltype(T::tm_zone)>>
1036  : std::true_type {};
1037 
1038 #if FMT_USE_TZSET
1039 inline void tzset_once() {
1040  static bool init = []() -> bool {
1041  _tzset();
1042  return true;
1043  }();
1044  ignore_unused(init);
1045 }
1046 #endif
1047 
1048 // Converts value to Int and checks that it's in the range [0, upper).
1052  (value >= 0 && to_unsigned(value) <= to_unsigned(upper)),
1053  "invalid value");
1054  (void)upper;
1055  return static_cast<Int>(value);
1056 }
1058 inline Int to_nonnegative_int(T value, Int upper) {
1059  if (value < 0 || value > static_cast<T>(upper))
1060  FMT_THROW(format_error("invalid value"));
1061  return static_cast<Int>(value);
1062 }
1063 
1064 constexpr long long pow10(std::uint32_t n) {
1065  return n == 0 ? 1 : 10 * pow10(n - 1);
1066 }
1067 
1068 // Counts the number of fractional digits in the range [0, 18] according to the
1069 // C++20 spec. If more than 18 fractional digits are required then returns 6 for
1070 // microseconds precision.
1071 template <long long Num, long long Den, int N = 0,
1072  bool Enabled = (N < 19) && (Num <= max_value<long long>() / 10)>
1074  static constexpr int value =
1076 };
1077 
1078 // Base case that doesn't instantiate any more templates
1079 // in order to avoid overflow.
1080 template <long long Num, long long Den, int N>
1081 struct count_fractional_digits<Num, Den, N, false> {
1082  static constexpr int value = (Num % Den == 0) ? N : 6;
1083 };
1084 
1085 // Format subseconds which are given as an integer type with an appropriate
1086 // number of digits.
1087 template <typename Char, typename OutputIt, typename Duration>
1088 void write_fractional_seconds(OutputIt& out, Duration d, int precision = -1) {
1089  constexpr auto num_fractional_digits =
1090  count_fractional_digits<Duration::period::num,
1091  Duration::period::den>::value;
1092 
1093  using subsecond_precision = std::chrono::duration<
1094  typename std::common_type<typename Duration::rep,
1095  std::chrono::seconds::rep>::type,
1096  std::ratio<1, detail::pow10(num_fractional_digits)>>;
1097 
1098  const auto fractional =
1099  d - std::chrono::duration_cast<std::chrono::seconds>(d);
1100  const auto subseconds =
1101  std::chrono::treat_as_floating_point<
1102  typename subsecond_precision::rep>::value
1103  ? fractional.count()
1104  : std::chrono::duration_cast<subsecond_precision>(fractional).count();
1105  auto n = static_cast<uint32_or_64_or_128_t<long long>>(subseconds);
1106  const int num_digits = detail::count_digits(n);
1107 
1108  int leading_zeroes = (std::max)(0, num_fractional_digits - num_digits);
1109  if (precision < 0) {
1111  if (std::ratio_less<typename subsecond_precision::period,
1112  std::chrono::seconds::period>::value) {
1113  *out++ = '.';
1114  out = std::fill_n(out, leading_zeroes, '0');
1115  out = format_decimal<Char>(out, n, num_digits).end;
1116  }
1117  } else {
1118  *out++ = '.';
1119  leading_zeroes = (std::min)(leading_zeroes, precision);
1120  out = std::fill_n(out, leading_zeroes, '0');
1121  int remaining = precision - leading_zeroes;
1122  if (remaining != 0 && remaining < num_digits) {
1123  n /= to_unsigned(detail::pow10(to_unsigned(num_digits - remaining)));
1124  out = format_decimal<Char>(out, n, remaining).end;
1125  return;
1126  }
1127  out = format_decimal<Char>(out, n, num_digits).end;
1128  remaining -= num_digits;
1129  out = std::fill_n(out, remaining, '0');
1130  }
1131 }
1132 
1133 // Format subseconds which are given as a floating point type with an
1134 // appropriate number of digits. We cannot pass the Duration here, as we
1135 // explicitly need to pass the Rep value in the chrono_formatter.
1136 template <typename Duration>
1137 void write_floating_seconds(memory_buffer& buf, Duration duration,
1138  int num_fractional_digits = -1) {
1139  using rep = typename Duration::rep;
1141 
1142  auto val = duration.count();
1143 
1144  if (num_fractional_digits < 0) {
1145  // For `std::round` with fallback to `round`:
1146  // On some toolchains `std::round` is not available (e.g. GCC 6).
1147  using namespace std;
1148  num_fractional_digits =
1149  count_fractional_digits<Duration::period::num,
1150  Duration::period::den>::value;
1151  if (num_fractional_digits < 6 && static_cast<rep>(round(val)) != val)
1152  num_fractional_digits = 6;
1153  }
1154 
1155  format_to(std::back_inserter(buf), FMT_STRING("{:.{}f}"),
1156  std::fmod(val * static_cast<rep>(Duration::period::num) /
1157  static_cast<rep>(Duration::period::den),
1158  static_cast<rep>(60)),
1159  num_fractional_digits);
1160 }
1161 
1162 template <typename OutputIt, typename Char,
1163  typename Duration = std::chrono::seconds>
1164 class tm_writer {
1165  private:
1166  static constexpr int days_per_week = 7;
1167 
1168  const std::locale& loc_;
1169  const bool is_classic_;
1170  OutputIt out_;
1171  const Duration* subsecs_;
1172  const std::tm& tm_;
1173 
1174  auto tm_sec() const noexcept -> int {
1175  FMT_ASSERT(tm_.tm_sec >= 0 && tm_.tm_sec <= 61, "");
1176  return tm_.tm_sec;
1177  }
1178  auto tm_min() const noexcept -> int {
1179  FMT_ASSERT(tm_.tm_min >= 0 && tm_.tm_min <= 59, "");
1180  return tm_.tm_min;
1181  }
1182  auto tm_hour() const noexcept -> int {
1183  FMT_ASSERT(tm_.tm_hour >= 0 && tm_.tm_hour <= 23, "");
1184  return tm_.tm_hour;
1185  }
1186  auto tm_mday() const noexcept -> int {
1187  FMT_ASSERT(tm_.tm_mday >= 1 && tm_.tm_mday <= 31, "");
1188  return tm_.tm_mday;
1189  }
1190  auto tm_mon() const noexcept -> int {
1191  FMT_ASSERT(tm_.tm_mon >= 0 && tm_.tm_mon <= 11, "");
1192  return tm_.tm_mon;
1193  }
1194  auto tm_year() const noexcept -> long long { return 1900ll + tm_.tm_year; }
1195  auto tm_wday() const noexcept -> int {
1196  FMT_ASSERT(tm_.tm_wday >= 0 && tm_.tm_wday <= 6, "");
1197  return tm_.tm_wday;
1198  }
1199  auto tm_yday() const noexcept -> int {
1200  FMT_ASSERT(tm_.tm_yday >= 0 && tm_.tm_yday <= 365, "");
1201  return tm_.tm_yday;
1202  }
1203 
1204  auto tm_hour12() const noexcept -> int {
1205  const auto h = tm_hour();
1206  const auto z = h < 12 ? h : h - 12;
1207  return z == 0 ? 12 : z;
1208  }
1209 
1210  // POSIX and the C Standard are unclear or inconsistent about what %C and %y
1211  // do if the year is negative or exceeds 9999. Use the convention that %C
1212  // concatenated with %y yields the same output as %Y, and that %Y contains at
1213  // least 4 characters, with more only if necessary.
1214  auto split_year_lower(long long year) const noexcept -> int {
1215  auto l = year % 100;
1216  if (l < 0) l = -l; // l in [0, 99]
1217  return static_cast<int>(l);
1218  }
1219 
1220  // Algorithm:
1221  // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_the_week_number_from_a_month_and_day_of_the_month_or_ordinal_date
1222  auto iso_year_weeks(long long curr_year) const noexcept -> int {
1223  const auto prev_year = curr_year - 1;
1224  const auto curr_p =
1225  (curr_year + curr_year / 4 - curr_year / 100 + curr_year / 400) %
1226  days_per_week;
1227  const auto prev_p =
1228  (prev_year + prev_year / 4 - prev_year / 100 + prev_year / 400) %
1229  days_per_week;
1230  return 52 + ((curr_p == 4 || prev_p == 3) ? 1 : 0);
1231  }
1232  auto iso_week_num(int tm_yday, int tm_wday) const noexcept -> int {
1233  return (tm_yday + 11 - (tm_wday == 0 ? days_per_week : tm_wday)) /
1234  days_per_week;
1235  }
1236  auto tm_iso_week_year() const noexcept -> long long {
1237  const auto year = tm_year();
1238  const auto w = iso_week_num(tm_yday(), tm_wday());
1239  if (w < 1) return year - 1;
1240  if (w > iso_year_weeks(year)) return year + 1;
1241  return year;
1242  }
1243  auto tm_iso_week_of_year() const noexcept -> int {
1244  const auto year = tm_year();
1245  const auto w = iso_week_num(tm_yday(), tm_wday());
1246  if (w < 1) return iso_year_weeks(year - 1);
1247  if (w > iso_year_weeks(year)) return 1;
1248  return w;
1249  }
1250 
1251  void write1(int value) {
1252  *out_++ = static_cast<char>('0' + to_unsigned(value) % 10);
1253  }
1254  void write2(int value) {
1255  const char* d = digits2(to_unsigned(value) % 100);
1256  *out_++ = *d++;
1257  *out_++ = *d;
1258  }
1259  void write2(int value, pad_type pad) {
1260  unsigned int v = to_unsigned(value) % 100;
1261  if (v >= 10) {
1262  const char* d = digits2(v);
1263  *out_++ = *d++;
1264  *out_++ = *d;
1265  } else {
1266  out_ = detail::write_padding(out_, pad);
1267  *out_++ = static_cast<char>('0' + v);
1268  }
1269  }
1270 
1271  void write_year_extended(long long year) {
1272  // At least 4 characters.
1273  int width = 4;
1274  if (year < 0) {
1275  *out_++ = '-';
1276  year = 0 - year;
1277  --width;
1278  }
1280  const int num_digits = count_digits(n);
1281  if (width > num_digits) out_ = std::fill_n(out_, width - num_digits, '0');
1282  out_ = format_decimal<Char>(out_, n, num_digits).end;
1283  }
1284  void write_year(long long year) {
1285  if (year >= 0 && year < 10000) {
1286  write2(static_cast<int>(year / 100));
1287  write2(static_cast<int>(year % 100));
1288  } else {
1289  write_year_extended(year);
1290  }
1291  }
1292 
1293  void write_utc_offset(long offset, numeric_system ns) {
1294  if (offset < 0) {
1295  *out_++ = '-';
1296  offset = -offset;
1297  } else {
1298  *out_++ = '+';
1299  }
1300  offset /= 60;
1301  write2(static_cast<int>(offset / 60));
1302  if (ns != numeric_system::standard) *out_++ = ':';
1303  write2(static_cast<int>(offset % 60));
1304  }
1306  void format_utc_offset_impl(const T& tm, numeric_system ns) {
1307  write_utc_offset(tm.tm_gmtoff, ns);
1308  }
1310  void format_utc_offset_impl(const T& tm, numeric_system ns) {
1311 #if defined(_WIN32) && defined(_UCRT)
1312 # if FMT_USE_TZSET
1313  tzset_once();
1314 # endif
1315  long offset = 0;
1316  _get_timezone(&offset);
1317  if (tm.tm_isdst) {
1318  long dstbias = 0;
1319  _get_dstbias(&dstbias);
1320  offset += dstbias;
1321  }
1322  write_utc_offset(-offset, ns);
1323 #else
1324  if (ns == numeric_system::standard) return format_localized('z');
1325 
1326  // Extract timezone offset from timezone conversion functions.
1327  std::tm gtm = tm;
1328  std::time_t gt = std::mktime(&gtm);
1329  std::tm ltm = gmtime(gt);
1330  std::time_t lt = std::mktime(&ltm);
1331  long offset = gt - lt;
1332  write_utc_offset(offset, ns);
1333 #endif
1334  }
1335 
1337  void format_tz_name_impl(const T& tm) {
1338  if (is_classic_)
1339  out_ = write_tm_str<Char>(out_, tm.tm_zone, loc_);
1340  else
1341  format_localized('Z');
1342  }
1344  void format_tz_name_impl(const T&) {
1345  format_localized('Z');
1346  }
1347 
1348  void format_localized(char format, char modifier = 0) {
1349  out_ = write<Char>(out_, tm_, loc_, format, modifier);
1350  }
1351 
1352  public:
1353  tm_writer(const std::locale& loc, OutputIt out, const std::tm& tm,
1354  const Duration* subsecs = nullptr)
1355  : loc_(loc),
1356  is_classic_(loc_ == get_classic_locale()),
1357  out_(out),
1358  subsecs_(subsecs),
1359  tm_(tm) {}
1360 
1361  OutputIt out() const { return out_; }
1362 
1363  FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) {
1364  out_ = copy_str<Char>(begin, end, out_);
1365  }
1366 
1368  if (is_classic_)
1369  out_ = write(out_, tm_wday_short_name(tm_wday()));
1370  else
1371  format_localized('a');
1372  }
1374  if (is_classic_)
1375  out_ = write(out_, tm_wday_full_name(tm_wday()));
1376  else
1377  format_localized('A');
1378  }
1380  if (is_classic_ || ns == numeric_system::standard) return write1(tm_wday());
1381  format_localized('w', 'O');
1382  }
1384  if (is_classic_ || ns == numeric_system::standard) {
1385  auto wday = tm_wday();
1386  write1(wday == 0 ? days_per_week : wday);
1387  } else {
1388  format_localized('u', 'O');
1389  }
1390  }
1391 
1392  void on_abbr_month() {
1393  if (is_classic_)
1394  out_ = write(out_, tm_mon_short_name(tm_mon()));
1395  else
1396  format_localized('b');
1397  }
1398  void on_full_month() {
1399  if (is_classic_)
1400  out_ = write(out_, tm_mon_full_name(tm_mon()));
1401  else
1402  format_localized('B');
1403  }
1404 
1406  if (is_classic_) {
1407  on_abbr_weekday();
1408  *out_++ = ' ';
1409  on_abbr_month();
1410  *out_++ = ' ';
1411  on_day_of_month_space(numeric_system::standard);
1412  *out_++ = ' ';
1413  on_iso_time();
1414  *out_++ = ' ';
1415  on_year(numeric_system::standard);
1416  } else {
1417  format_localized('c', ns == numeric_system::standard ? '\0' : 'E');
1418  }
1419  }
1421  if (is_classic_)
1422  on_us_date();
1423  else
1424  format_localized('x', ns == numeric_system::standard ? '\0' : 'E');
1425  }
1427  if (is_classic_)
1428  on_iso_time();
1429  else
1430  format_localized('X', ns == numeric_system::standard ? '\0' : 'E');
1431  }
1432  void on_us_date() {
1433  char buf[8];
1434  write_digit2_separated(buf, to_unsigned(tm_mon() + 1),
1435  to_unsigned(tm_mday()),
1436  to_unsigned(split_year_lower(tm_year())), '/');
1437  out_ = copy_str<Char>(std::begin(buf), std::end(buf), out_);
1438  }
1439  void on_iso_date() {
1440  auto year = tm_year();
1441  char buf[10];
1442  size_t offset = 0;
1443  if (year >= 0 && year < 10000) {
1444  copy2(buf, digits2(static_cast<size_t>(year / 100)));
1445  } else {
1446  offset = 4;
1447  write_year_extended(year);
1448  year = 0;
1449  }
1450  write_digit2_separated(buf + 2, static_cast<unsigned>(year % 100),
1451  to_unsigned(tm_mon() + 1), to_unsigned(tm_mday()),
1452  '-');
1453  out_ = copy_str<Char>(std::begin(buf) + offset, std::end(buf), out_);
1454  }
1455 
1456  void on_utc_offset(numeric_system ns) { format_utc_offset_impl(tm_, ns); }
1457  void on_tz_name() { format_tz_name_impl(tm_); }
1458 
1460  if (is_classic_ || ns == numeric_system::standard)
1461  return write_year(tm_year());
1462  format_localized('Y', 'E');
1463  }
1465  if (is_classic_ || ns == numeric_system::standard)
1466  return write2(split_year_lower(tm_year()));
1467  format_localized('y', 'O');
1468  }
1470  if (is_classic_) return write2(split_year_lower(tm_year()));
1471  format_localized('y', 'E');
1472  }
1473 
1475  if (is_classic_ || ns == numeric_system::standard) {
1476  auto year = tm_year();
1477  auto upper = year / 100;
1478  if (year >= -99 && year < 0) {
1479  // Zero upper on negative year.
1480  *out_++ = '-';
1481  *out_++ = '0';
1482  } else if (upper >= 0 && upper < 100) {
1483  write2(static_cast<int>(upper));
1484  } else {
1485  out_ = write<Char>(out_, upper);
1486  }
1487  } else {
1488  format_localized('C', 'E');
1489  }
1490  }
1491 
1493  if (is_classic_ || ns == numeric_system::standard)
1494  return write2(tm_mon() + 1);
1495  format_localized('m', 'O');
1496  }
1497 
1499  if (is_classic_ || ns == numeric_system::standard)
1500  return write2((tm_yday() + days_per_week - tm_wday()) / days_per_week);
1501  format_localized('U', 'O');
1502  }
1504  if (is_classic_ || ns == numeric_system::standard) {
1505  auto wday = tm_wday();
1506  write2((tm_yday() + days_per_week -
1507  (wday == 0 ? (days_per_week - 1) : (wday - 1))) /
1508  days_per_week);
1509  } else {
1510  format_localized('W', 'O');
1511  }
1512  }
1514  if (is_classic_ || ns == numeric_system::standard)
1515  return write2(tm_iso_week_of_year());
1516  format_localized('V', 'O');
1517  }
1518 
1519  void on_iso_week_based_year() { write_year(tm_iso_week_year()); }
1521  write2(split_year_lower(tm_iso_week_year()));
1522  }
1523 
1525  auto yday = tm_yday() + 1;
1526  write1(yday / 100);
1527  write2(yday % 100);
1528  }
1530  if (is_classic_ || ns == numeric_system::standard) return write2(tm_mday());
1531  format_localized('d', 'O');
1532  }
1534  if (is_classic_ || ns == numeric_system::standard) {
1535  auto mday = to_unsigned(tm_mday()) % 100;
1536  const char* d2 = digits2(mday);
1537  *out_++ = mday < 10 ? ' ' : d2[0];
1538  *out_++ = d2[1];
1539  } else {
1540  format_localized('e', 'O');
1541  }
1542  }
1543 
1545  if (is_classic_ || ns == numeric_system::standard)
1546  return write2(tm_hour(), pad);
1547  format_localized('H', 'O');
1548  }
1550  if (is_classic_ || ns == numeric_system::standard)
1551  return write2(tm_hour12(), pad);
1552  format_localized('I', 'O');
1553  }
1555  if (is_classic_ || ns == numeric_system::standard)
1556  return write2(tm_min(), pad);
1557  format_localized('M', 'O');
1558  }
1559 
1561  if (is_classic_ || ns == numeric_system::standard) {
1562  write2(tm_sec(), pad);
1563  if (subsecs_) {
1565  auto buf = memory_buffer();
1566  write_floating_seconds(buf, *subsecs_);
1567  if (buf.size() > 1) {
1568  // Remove the leading "0", write something like ".123".
1569  out_ = std::copy(buf.begin() + 1, buf.end(), out_);
1570  }
1571  } else {
1572  write_fractional_seconds<Char>(out_, *subsecs_);
1573  }
1574  }
1575  } else {
1576  // Currently no formatting of subseconds when a locale is set.
1577  format_localized('S', 'O');
1578  }
1579  }
1580 
1582  if (is_classic_) {
1583  char buf[8];
1584  write_digit2_separated(buf, to_unsigned(tm_hour12()),
1585  to_unsigned(tm_min()), to_unsigned(tm_sec()), ':');
1586  out_ = copy_str<Char>(std::begin(buf), std::end(buf), out_);
1587  *out_++ = ' ';
1588  on_am_pm();
1589  } else {
1590  format_localized('r');
1591  }
1592  }
1594  write2(tm_hour());
1595  *out_++ = ':';
1596  write2(tm_min());
1597  }
1598  void on_iso_time() {
1599  on_24_hour_time();
1600  *out_++ = ':';
1602  }
1603 
1604  void on_am_pm() {
1605  if (is_classic_) {
1606  *out_++ = tm_hour() < 12 ? 'A' : 'P';
1607  *out_++ = 'M';
1608  } else {
1609  format_localized('p');
1610  }
1611  }
1612 
1613  // These apply to chrono durations but not tm.
1616 };
1617 
1618 struct chrono_format_checker : null_chrono_spec_handler<chrono_format_checker> {
1619  bool has_precision_integral = false;
1620 
1622 
1623  template <typename Char>
1624  FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
1634  if (has_precision_integral) {
1635  FMT_THROW(format_error("precision not allowed for this argument type"));
1636  }
1637  }
1639 };
1640 
1641 template <typename T,
1643 inline bool isfinite(T) {
1644  return true;
1645 }
1646 
1648 inline T mod(T x, int y) {
1649  return x % static_cast<T>(y);
1650 }
1652 inline T mod(T x, int y) {
1653  return std::fmod(x, static_cast<T>(y));
1654 }
1655 
1656 // If T is an integral type, maps T to its unsigned counterpart, otherwise
1657 // leaves it unchanged (unlike std::make_unsigned).
1660  using type = T;
1661 };
1662 
1663 template <typename T> struct make_unsigned_or_unchanged<T, true> {
1665 };
1666 
1667 #if FMT_SAFE_DURATION_CAST
1668 // throwing version of safe_duration_cast
1669 template <typename To, typename FromRep, typename FromPeriod>
1670 To fmt_safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from) {
1671  int ec;
1672  To to = safe_duration_cast::safe_duration_cast<To>(from, ec);
1673  if (ec) FMT_THROW(format_error("cannot format duration"));
1674  return to;
1675 }
1676 #endif
1677 
1678 template <typename Rep, typename Period,
1680 inline std::chrono::duration<Rep, std::milli> get_milliseconds(
1681  std::chrono::duration<Rep, Period> d) {
1682  // this may overflow and/or the result may not fit in the
1683  // target type.
1684 #if FMT_SAFE_DURATION_CAST
1685  using CommonSecondsType =
1687  const auto d_as_common = fmt_safe_duration_cast<CommonSecondsType>(d);
1688  const auto d_as_whole_seconds =
1689  fmt_safe_duration_cast<std::chrono::seconds>(d_as_common);
1690  // this conversion should be nonproblematic
1691  const auto diff = d_as_common - d_as_whole_seconds;
1692  const auto ms =
1693  fmt_safe_duration_cast<std::chrono::duration<Rep, std::milli>>(diff);
1694  return ms;
1695 #else
1696  auto s = std::chrono::duration_cast<std::chrono::seconds>(d);
1697  return std::chrono::duration_cast<std::chrono::milliseconds>(d - s);
1698 #endif
1699 }
1700 
1701 template <typename Char, typename Rep, typename OutputIt,
1703 OutputIt format_duration_value(OutputIt out, Rep val, int) {
1704  return write<Char>(out, val);
1705 }
1706 
1707 template <typename Char, typename Rep, typename OutputIt,
1709 OutputIt format_duration_value(OutputIt out, Rep val, int precision) {
1710  auto specs = format_specs<Char>();
1711  specs.precision = precision;
1712  specs.type = precision >= 0 ? presentation_type::fixed_lower
1714  return write<Char>(out, val, specs);
1715 }
1716 
1717 template <typename Char, typename OutputIt>
1718 OutputIt copy_unit(string_view unit, OutputIt out, Char) {
1719  return std::copy(unit.begin(), unit.end(), out);
1720 }
1721 
1722 template <typename OutputIt>
1723 OutputIt copy_unit(string_view unit, OutputIt out, wchar_t) {
1724  // This works when wchar_t is UTF-32 because units only contain characters
1725  // that have the same representation in UTF-16 and UTF-32.
1726  utf8_to_utf16 u(unit);
1727  return std::copy(u.c_str(), u.c_str() + u.size(), out);
1728 }
1729 
1730 template <typename Char, typename Period, typename OutputIt>
1731 OutputIt format_duration_unit(OutputIt out) {
1732  if (const char* unit = get_units<Period>())
1733  return copy_unit(string_view(unit), out, Char());
1734  *out++ = '[';
1735  out = write<Char>(out, Period::num);
1736  if (const_check(Period::den != 1)) {
1737  *out++ = '/';
1738  out = write<Char>(out, Period::den);
1739  }
1740  *out++ = ']';
1741  *out++ = 's';
1742  return out;
1743 }
1744 
1745 class get_locale {
1746  private:
1747  union {
1748  std::locale locale_;
1749  };
1750  bool has_locale_ = false;
1751 
1752  public:
1753  get_locale(bool localized, locale_ref loc) : has_locale_(localized) {
1754  if (localized)
1755  ::new (&locale_) std::locale(loc.template get<std::locale>());
1756  }
1758  if (has_locale_) locale_.~locale();
1759  }
1760  operator const std::locale&() const {
1761  return has_locale_ ? locale_ : get_classic_locale();
1762  }
1763 };
1764 
1765 template <typename FormatContext, typename OutputIt, typename Rep,
1766  typename Period>
1768  FormatContext& context;
1769  OutputIt out;
1771  bool localized = false;
1772  // rep is unsigned to avoid overflow.
1773  using rep =
1774  conditional_t<std::is_integral<Rep>::value && sizeof(Rep) < sizeof(int),
1777  using seconds = std::chrono::duration<rep>;
1779  using milliseconds = std::chrono::duration<rep, std::milli>;
1780  bool negative;
1781 
1782  using char_type = typename FormatContext::char_type;
1784 
1785  chrono_formatter(FormatContext& ctx, OutputIt o,
1786  std::chrono::duration<Rep, Period> d)
1787  : context(ctx),
1788  out(o),
1789  val(static_cast<rep>(d.count())),
1790  negative(false) {
1791  if (d.count() < 0) {
1792  val = 0 - val;
1793  negative = true;
1794  }
1795 
1796  // this may overflow and/or the result may not fit in the
1797  // target type.
1798 #if FMT_SAFE_DURATION_CAST
1799  // might need checked conversion (rep!=Rep)
1800  auto tmpval = std::chrono::duration<rep, Period>(val);
1801  s = fmt_safe_duration_cast<seconds>(tmpval);
1802 #else
1803  s = std::chrono::duration_cast<seconds>(
1804  std::chrono::duration<rep, Period>(val));
1805 #endif
1806  }
1807 
1808  // returns true if nan or inf, writes to out.
1810  if (isfinite(val)) {
1811  return false;
1812  }
1813  if (isnan(val)) {
1814  write_nan();
1815  return true;
1816  }
1817  // must be +-inf
1818  if (val > 0) {
1819  write_pinf();
1820  } else {
1821  write_ninf();
1822  }
1823  return true;
1824  }
1825 
1826  Rep hour() const { return static_cast<Rep>(mod((s.count() / 3600), 24)); }
1827 
1828  Rep hour12() const {
1829  Rep hour = static_cast<Rep>(mod((s.count() / 3600), 12));
1830  return hour <= 0 ? 12 : hour;
1831  }
1832 
1833  Rep minute() const { return static_cast<Rep>(mod((s.count() / 60), 60)); }
1834  Rep second() const { return static_cast<Rep>(mod(s.count(), 60)); }
1835 
1836  std::tm time() const {
1837  auto time = std::tm();
1838  time.tm_hour = to_nonnegative_int(hour(), 24);
1839  time.tm_min = to_nonnegative_int(minute(), 60);
1840  time.tm_sec = to_nonnegative_int(second(), 60);
1841  return time;
1842  }
1843 
1844  void write_sign() {
1845  if (negative) {
1846  *out++ = '-';
1847  negative = false;
1848  }
1849  }
1850 
1851  void write(Rep value, int width, pad_type pad = pad_type::unspecified) {
1852  write_sign();
1853  if (isnan(value)) return write_nan();
1855  to_unsigned(to_nonnegative_int(value, max_value<int>()));
1856  int num_digits = detail::count_digits(n);
1857  if (width > num_digits) {
1858  out = detail::write_padding(out, pad, width - num_digits);
1859  }
1860  out = format_decimal<char_type>(out, n, num_digits).end;
1861  }
1862 
1863  void write_nan() { std::copy_n("nan", 3, out); }
1864  void write_pinf() { std::copy_n("inf", 3, out); }
1865  void write_ninf() { std::copy_n("-inf", 4, out); }
1866 
1867  template <typename Callback, typename... Args>
1868  void format_tm(const tm& time, Callback cb, Args... args) {
1869  if (isnan(val)) return write_nan();
1870  get_locale loc(localized, context.locale());
1871  auto w = tm_writer_type(loc, out, time);
1872  (w.*cb)(args...);
1873  out = w.out();
1874  }
1875 
1876  void on_text(const char_type* begin, const char_type* end) {
1877  std::copy(begin, end, out);
1878  }
1879 
1880  // These are not implemented because durations don't have date information.
1885  void on_abbr_month() {}
1886  void on_full_month() {}
1890  void on_us_date() {}
1891  void on_iso_date() {}
1893  void on_tz_name() {}
1896  void on_offset_year() {}
1904  void on_day_of_year() {}
1907 
1909  if (handle_nan_inf()) return;
1910 
1911  if (ns == numeric_system::standard) return write(hour(), 2, pad);
1912  auto time = tm();
1913  time.tm_hour = to_nonnegative_int(hour(), 24);
1914  format_tm(time, &tm_writer_type::on_24_hour, ns, pad);
1915  }
1916 
1918  if (handle_nan_inf()) return;
1919 
1920  if (ns == numeric_system::standard) return write(hour12(), 2, pad);
1921  auto time = tm();
1922  time.tm_hour = to_nonnegative_int(hour12(), 12);
1923  format_tm(time, &tm_writer_type::on_12_hour, ns, pad);
1924  }
1925 
1927  if (handle_nan_inf()) return;
1928 
1929  if (ns == numeric_system::standard) return write(minute(), 2, pad);
1930  auto time = tm();
1931  time.tm_min = to_nonnegative_int(minute(), 60);
1932  format_tm(time, &tm_writer_type::on_minute, ns, pad);
1933  }
1934 
1936  if (handle_nan_inf()) return;
1937 
1938  if (ns == numeric_system::standard) {
1940  auto buf = memory_buffer();
1941  write_floating_seconds(buf, std::chrono::duration<rep, Period>(val),
1942  precision);
1943  if (negative) *out++ = '-';
1944  if (buf.size() < 2 || buf[1] == '.') {
1945  out = detail::write_padding(out, pad);
1946  }
1947  out = std::copy(buf.begin(), buf.end(), out);
1948  } else {
1949  write(second(), 2, pad);
1950  write_fractional_seconds<char_type>(
1951  out, std::chrono::duration<rep, Period>(val), precision);
1952  }
1953  return;
1954  }
1955  auto time = tm();
1956  time.tm_sec = to_nonnegative_int(second(), 60);
1957  format_tm(time, &tm_writer_type::on_second, ns, pad);
1958  }
1959 
1961  if (handle_nan_inf()) return;
1962  format_tm(time(), &tm_writer_type::on_12_hour_time);
1963  }
1964 
1966  if (handle_nan_inf()) {
1967  *out++ = ':';
1968  handle_nan_inf();
1969  return;
1970  }
1971 
1972  write(hour(), 2);
1973  *out++ = ':';
1974  write(minute(), 2);
1975  }
1976 
1977  void on_iso_time() {
1978  on_24_hour_time();
1979  *out++ = ':';
1980  if (handle_nan_inf()) return;
1982  }
1983 
1984  void on_am_pm() {
1985  if (handle_nan_inf()) return;
1986  format_tm(time(), &tm_writer_type::on_am_pm);
1987  }
1988 
1990  if (handle_nan_inf()) return;
1991  write_sign();
1992  out = format_duration_value<char_type>(out, val, precision);
1993  }
1994 
1996  out = format_duration_unit<char_type, Period>(out);
1997  }
1998 };
1999 
2001 
2002 #if defined(__cpp_lib_chrono) && __cpp_lib_chrono >= 201907
2003 using weekday = std::chrono::weekday;
2004 #else
2005 // A fallback version of weekday.
2006 class weekday {
2007  private:
2008  unsigned char value;
2009 
2010  public:
2011  weekday() = default;
2012  explicit constexpr weekday(unsigned wd) noexcept
2013  : value(static_cast<unsigned char>(wd != 7 ? wd : 0)) {}
2014  constexpr unsigned c_encoding() const noexcept { return value; }
2015 };
2016 
2018 #endif
2019 
2020 // A rudimentary weekday formatter.
2021 template <typename Char> struct formatter<weekday, Char> {
2022  private:
2023  bool localized = false;
2024 
2025  public:
2027  -> decltype(ctx.begin()) {
2028  auto begin = ctx.begin(), end = ctx.end();
2029  if (begin != end && *begin == 'L') {
2030  ++begin;
2031  localized = true;
2032  }
2033  return begin;
2034  }
2035 
2036  template <typename FormatContext>
2037  auto format(weekday wd, FormatContext& ctx) const -> decltype(ctx.out()) {
2038  auto time = std::tm();
2039  time.tm_wday = static_cast<int>(wd.c_encoding());
2040  detail::get_locale loc(localized, ctx.locale());
2041  auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), time);
2042  w.on_abbr_weekday();
2043  return w.out();
2044  }
2045 };
2046 
2047 template <typename Rep, typename Period, typename Char>
2048 struct formatter<std::chrono::duration<Rep, Period>, Char> {
2049  private:
2050  format_specs<Char> specs;
2051  int precision = -1;
2053  arg_ref_type width_ref;
2054  arg_ref_type precision_ref;
2055  bool localized = false;
2056  basic_string_view<Char> format_str;
2057  using duration = std::chrono::duration<Rep, Period>;
2058 
2059  using iterator = typename basic_format_parse_context<Char>::iterator;
2060  struct parse_range {
2061  iterator begin;
2062  iterator end;
2063  };
2064 
2065  FMT_CONSTEXPR parse_range do_parse(basic_format_parse_context<Char>& ctx) {
2066  auto begin = ctx.begin(), end = ctx.end();
2067  if (begin == end || *begin == '}') return {begin, begin};
2068 
2069  begin = detail::parse_align(begin, end, specs);
2070  if (begin == end) return {begin, begin};
2071 
2072  begin = detail::parse_dynamic_spec(begin, end, specs.width, width_ref, ctx);
2073  if (begin == end) return {begin, begin};
2074 
2075  auto checker = detail::chrono_format_checker();
2076  if (*begin == '.') {
2077  checker.has_precision_integral = !std::is_floating_point<Rep>::value;
2078  begin =
2079  detail::parse_precision(begin, end, precision, precision_ref, ctx);
2080  }
2081  if (begin != end && *begin == 'L') {
2082  ++begin;
2083  localized = true;
2084  }
2086  return {begin, end};
2087  }
2088 
2089  public:
2091  -> decltype(ctx.begin()) {
2092  auto range = do_parse(ctx);
2093  format_str = basic_string_view<Char>(
2094  &*range.begin, detail::to_unsigned(range.end - range.begin));
2095  return range.end;
2096  }
2097 
2098  template <typename FormatContext>
2099  auto format(const duration& d, FormatContext& ctx) const
2100  -> decltype(ctx.out()) {
2101  auto specs_copy = specs;
2102  auto precision_copy = precision;
2103  auto begin = format_str.begin(), end = format_str.end();
2104  // As a possible future optimization, we could avoid extra copying if width
2105  // is not specified.
2107  auto out = std::back_inserter(buf);
2108  detail::handle_dynamic_spec<detail::width_checker>(specs_copy.width,
2109  width_ref, ctx);
2110  detail::handle_dynamic_spec<detail::precision_checker>(precision_copy,
2111  precision_ref, ctx);
2112  if (begin == end || *begin == '}') {
2113  out = detail::format_duration_value<Char>(out, d.count(), precision_copy);
2114  detail::format_duration_unit<Char, Period>(out);
2115  } else {
2116  detail::chrono_formatter<FormatContext, decltype(out), Rep, Period> f(
2117  ctx, out, d);
2118  f.precision = precision_copy;
2119  f.localized = localized;
2121  }
2122  return detail::write(
2123  ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs_copy);
2124  }
2125 };
2126 
2127 template <typename Char, typename Duration>
2128 struct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
2129  Char> : formatter<std::tm, Char> {
2132  }
2133 
2134  template <typename FormatContext>
2135  auto format(std::chrono::time_point<std::chrono::system_clock, Duration> val,
2136  FormatContext& ctx) const -> decltype(ctx.out()) {
2137  using period = typename Duration::period;
2138  if (period::num != 1 || period::den != 1 ||
2140  const auto epoch = val.time_since_epoch();
2141  auto subsecs = std::chrono::duration_cast<Duration>(
2142  epoch - std::chrono::duration_cast<std::chrono::seconds>(epoch));
2143 
2144  if (subsecs.count() < 0) {
2145  auto second = std::chrono::seconds(1);
2146  if (epoch.count() < ((Duration::min)() + second).count())
2147  FMT_THROW(format_error("duration is too small"));
2148  subsecs += second;
2149  val -= second;
2150  }
2151 
2153  gmtime(std::chrono::time_point_cast<std::chrono::seconds>(val)), ctx,
2154  &subsecs);
2155  }
2156 
2158  gmtime(std::chrono::time_point_cast<std::chrono::seconds>(val)), ctx);
2159  }
2160 };
2161 
2162 #if FMT_USE_LOCAL_TIME
2163 template <typename Char, typename Duration>
2164 struct formatter<std::chrono::local_time<Duration>, Char>
2165  : formatter<std::tm, Char> {
2168  }
2169 
2170  template <typename FormatContext>
2171  auto format(std::chrono::local_time<Duration> val, FormatContext& ctx) const
2172  -> decltype(ctx.out()) {
2173  using period = typename Duration::period;
2174  if (period::num != 1 || period::den != 1 ||
2176  const auto epoch = val.time_since_epoch();
2177  const auto subsecs = std::chrono::duration_cast<Duration>(
2178  epoch - std::chrono::duration_cast<std::chrono::seconds>(epoch));
2179 
2181  localtime(std::chrono::time_point_cast<std::chrono::seconds>(val)),
2182  ctx, &subsecs);
2183  }
2184 
2186  localtime(std::chrono::time_point_cast<std::chrono::seconds>(val)),
2187  ctx);
2188  }
2189 };
2190 #endif
2191 
2192 #if FMT_USE_UTC_TIME
2193 template <typename Char, typename Duration>
2194 struct formatter<std::chrono::time_point<std::chrono::utc_clock, Duration>,
2195  Char>
2196  : formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
2197  Char> {
2198  template <typename FormatContext>
2199  auto format(std::chrono::time_point<std::chrono::utc_clock, Duration> val,
2200  FormatContext& ctx) const -> decltype(ctx.out()) {
2201  return formatter<
2202  std::chrono::time_point<std::chrono::system_clock, Duration>,
2203  Char>::format(std::chrono::utc_clock::to_sys(val), ctx);
2204  }
2205 };
2206 #endif
2207 
2208 template <typename Char> struct formatter<std::tm, Char> {
2209  private:
2210  format_specs<Char> specs;
2211  detail::arg_ref<Char> width_ref;
2212 
2213  protected:
2215 
2217  -> decltype(ctx.begin()) {
2218  auto begin = ctx.begin(), end = ctx.end();
2219  if (begin == end || *begin == '}') return begin;
2220 
2221  begin = detail::parse_align(begin, end, specs);
2222  if (begin == end) return end;
2223 
2224  begin = detail::parse_dynamic_spec(begin, end, specs.width, width_ref, ctx);
2225  if (begin == end) return end;
2226 
2227  end = detail::parse_chrono_format(begin, end, detail::tm_format_checker());
2228  // Replace default format_str only if the new spec is not empty.
2229  if (end != begin) format_str = {begin, detail::to_unsigned(end - begin)};
2230  return end;
2231  }
2232 
2233  template <typename FormatContext, typename Duration>
2234  auto do_format(const std::tm& tm, FormatContext& ctx,
2235  const Duration* subsecs) const -> decltype(ctx.out()) {
2236  auto specs_copy = specs;
2238  auto out = std::back_inserter(buf);
2239  detail::handle_dynamic_spec<detail::width_checker>(specs_copy.width,
2240  width_ref, ctx);
2241 
2242  const auto loc_ref = ctx.locale();
2243  detail::get_locale loc(static_cast<bool>(loc_ref), loc_ref);
2244  auto w =
2245  detail::tm_writer<decltype(out), Char, Duration>(loc, out, tm, subsecs);
2246  detail::parse_chrono_format(format_str.begin(), format_str.end(), w);
2247  return detail::write(
2248  ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs_copy);
2249  }
2250 
2251  public:
2253  -> decltype(ctx.begin()) {
2254  return this->do_parse(ctx);
2255  }
2256 
2257  template <typename FormatContext>
2258  auto format(const std::tm& tm, FormatContext& ctx) const
2259  -> decltype(ctx.out()) {
2260  return do_format<FormatContext, std::chrono::seconds>(tm, ctx, nullptr);
2261  }
2262 };
2263 
2266 
2267 #endif // FMT_CHRONO_H_
FMT_CONSTEXPR void on_iso_week_based_short_year()
Definition: chrono.h:926
#define FMT_STRING(s)
Definition: format.h:1993
type
Definition: core.h:556
void on_dec1_weekday(numeric_system)
Definition: chrono.h:1884
FMT_NORETURN FMT_API void throw_format_error(const char *message)
Definition: format-inl.h:39
FMT_CONSTEXPR void on_day_of_month(numeric_system)
Definition: chrono.h:938
#define FMT_ENABLE_IF(...)
Definition: core.h:289
typename FormatContext::char_type char_type
Definition: chrono.h:1782
FMT_CONSTEXPR void on_am_pm()
Definition: chrono.h:952
#define FMT_BEGIN_EXPORT
Definition: core.h:186
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glcorearb.h:2540
std::string upper(string_view a)
Return an all-upper case version of a (locale-independent).
Definition: strutil.h:500
FMT_CONSTEXPR To lossless_integral_conversion(const From from, int &ec)
Definition: chrono.h:75
void write_pinf()
Definition: chrono.h:1864
SYS_API double fmod(double x, double y)
auto format(std::chrono::time_point< std::chrono::system_clock, Duration > val, FormatContext &ctx) const -> decltype(ctx.out())
Definition: chrono.h:2135
void on_dec0_week_of_year(numeric_system ns)
Definition: chrono.h:1498
void on_abbr_month()
Definition: chrono.h:1885
void on_text(const char_type *begin, const char_type *end)
Definition: chrono.h:1876
void write_fractional_seconds(OutputIt &out, Duration d, int precision=-1)
Definition: chrono.h:1088
#define FMT_END_DETAIL_NAMESPACE
Definition: format.h:53
std::locale locale_
Definition: chrono.h:1748
FMT_BEGIN_DETAIL_NAMESPACE FMT_CONSTEXPR auto parse_align(const Char *begin, const Char *end, format_specs< Char > &specs) -> const Char *
Definition: chrono.h:537
bool_constant< is_integral< T >::value &&!std::is_same< T, bool >::value &&!std::is_same< T, char >::value &&!std::is_same< T, wchar_t >::value > is_integer
Definition: format.h:824
void on_tz_name()
Definition: chrono.h:1457
FMT_CONSTEXPR void on_text(const Char *, const Char *)
Definition: chrono.h:1624
GLenum GLint * range
Definition: glcorearb.h:1925
#define FMT_NORETURN
Definition: core.h:146
constexpr weekday(unsigned wd) noexcept
Definition: chrono.h:2012
FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system)
Definition: chrono.h:978
void on_day_of_year()
Definition: chrono.h:1524
OutputIt format_duration_value(OutputIt out, Rep val, int)
Definition: chrono.h:1703
void on_minute(numeric_system ns, pad_type pad)
Definition: chrono.h:1926
void write_digit2_separated(char *buf, unsigned a, unsigned b, unsigned c, char sep)
Definition: chrono.h:581
FMT_CONSTEXPR void on_abbr_weekday()
Definition: chrono.h:970
T mod(T x, int y)
Definition: chrono.h:1648
auto do_format(const std::tm &tm, FormatContext &ctx, const Duration *subsecs) const -> decltype(ctx.out())
Definition: chrono.h:2234
FMT_NORETURN void unsupported()
Definition: chrono.h:1621
void on_am_pm()
Definition: chrono.h:1984
void on_century(numeric_system ns)
Definition: chrono.h:1474
FMT_CONSTEXPR void on_text(const Char *begin, const Char *end)
Definition: chrono.h:1363
pad_type
Definition: chrono.h:642
void on_am_pm()
Definition: chrono.h:1604
FMT_CONSTEXPR auto data() noexcept-> T *
Definition: core.h:907
int precision
Definition: core.h:2062
void
Definition: png.h:1083
FMT_INLINE auto end() noexcept-> T *
Definition: core.h:895
FMT_CONSTEXPR void on_12_hour_time()
Definition: chrono.h:1629
void on_offset_year()
Definition: chrono.h:1469
GLint left
Definition: glcorearb.h:2005
Rep minute() const
Definition: chrono.h:1833
T negative(const T &val)
Return the unary negation of the given value.
Definition: Math.h:128
FMT_CONSTEXPR void on_duration_value()
Definition: chrono.h:953
FMT_CONSTEXPR void on_12_hour(numeric_system, pad_type)
Definition: chrono.h:984
GT_API const UT_StringHolder time
typename std::conditional< B, T, F >::type conditional_t
Definition: core.h:266
OIIO_UTIL_API bool copy(string_view from, string_view to, std::string &err)
FMT_CONSTEXPR void on_us_date()
Definition: chrono.h:990
const GLdouble * v
Definition: glcorearb.h:837
To safe_duration_cast(std::chrono::duration< FromRep, FromPeriod > from, int &ec)
Definition: chrono.h:191
Rep second() const
Definition: chrono.h:1834
void on_dec1_week_of_year(numeric_system ns)
Definition: chrono.h:1503
FMT_CONSTEXPR void ignore_unused(const T &...)
Definition: core.h:302
OutputIt out() const
Definition: chrono.h:1361
void on_iso_week_of_year(numeric_system)
Definition: chrono.h:1903
GLsizei const GLfloat * value
Definition: glcorearb.h:824
FMT_CONSTEXPR void on_tz_name()
Definition: chrono.h:956
FMT_CONSTEXPR auto do_parse(basic_format_parse_context< Char > &ctx) -> decltype(ctx.begin())
Definition: chrono.h:2216
FMT_INLINE auto begin() noexcept-> T *
Definition: core.h:894
FMT_CONSTEXPR auto parse(basic_format_parse_context< Char > &ctx) -> decltype(ctx.begin())
Definition: chrono.h:2026
tm_writer(const std::locale &loc, OutputIt out, const std::tm &tm, const Duration *subsecs=nullptr)
Definition: chrono.h:1353
void on_day_of_month(numeric_system)
Definition: chrono.h:1905
FMT_CONSTEXPR void on_century(numeric_system)
Definition: chrono.h:967
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
GLdouble right
Definition: glad.h:2817
auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale &loc) -> OutputIt
Definition: chrono.h:362
auto format(const std::tm &tm, FormatContext &ctx) const -> decltype(ctx.out())
Definition: chrono.h:2258
FMT_CONSTEXPR void on_tz_name()
Definition: chrono.h:997
FMT_CONSTEXPR void on_year(numeric_system)
Definition: chrono.h:964
FMT_CONSTEXPR void on_12_hour_time()
Definition: chrono.h:949
void on_24_hour_time()
Definition: chrono.h:1593
void write_floating_seconds(memory_buffer &buf, Duration duration, int num_fractional_digits=-1)
Definition: chrono.h:1137
FMT_CONSTEXPR const char * get_units()
Definition: chrono.h:612
const std::locale & get_classic_locale()
Definition: chrono.h:329
std::tm gmtime(std::time_t time)
Definition: chrono.h:493
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GLdouble s
Definition: glad.h:3009
void on_offset_year()
Definition: chrono.h:1896
void on_second(numeric_system ns, pad_type pad)
Definition: chrono.h:1560
FMT_CONSTEXPR void on_iso_time()
Definition: chrono.h:1631
FMT_CONSTEXPR auto to_unsigned(Int value) -> typename std::make_unsigned< Int >::type
Definition: core.h:374
auto c_str() const -> const wchar_t *
Definition: format.h:1417
get_locale(bool localized, locale_ref loc)
Definition: chrono.h:1753
Rep hour12() const
Definition: chrono.h:1828
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
void on_loc_date(numeric_system ns)
Definition: chrono.h:1420
conditional_t< num_bits< T >()<=32 &&!FMT_REDUCE_INT_INSTANTIATIONS, uint32_t, conditional_t< num_bits< T >()<=64, uint64_t, uint128_t >> uint32_or_64_or_128_t
Definition: format.h:1158
GLint y
Definition: glcorearb.h:103
FMT_CONSTEXPR void on_duration_value() const
Definition: chrono.h:1633
void on_year(numeric_system ns)
Definition: chrono.h:1459
typename std::make_unsigned< T >::type type
Definition: chrono.h:1664
conditional_t< std::is_integral< Rep >::value &&sizeof(Rep)< sizeof(int), unsigned, typename make_unsigned_or_unchanged< Rep >::type > rep
Definition: chrono.h:1775
std::chrono::duration< rep, std::milli > milliseconds
Definition: chrono.h:1779
ImageBuf OIIO_API checker(int width, int height, int depth, cspan< float > color1, cspan< float > color2, int xoffset, int yoffset, int zoffset, ROI roi, int nthreads=0)
**But if you need a result
Definition: thread.h:622
FMT_CONSTEXPR void on_12_hour(numeric_system, pad_type)
Definition: chrono.h:1626
FMT_CONSTEXPR void on_year(numeric_system)
Definition: chrono.h:921
FMT_CONSTEXPR void on_day_of_year()
Definition: chrono.h:937
FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T &value) -> OutputIt
Definition: format.h:629
void on_minute(numeric_system ns, pad_type pad)
Definition: chrono.h:1554
auto format(weekday wd, FormatContext &ctx) const -> decltype(ctx.out())
Definition: chrono.h:2037
FMT_CONSTEXPR void on_24_hour_time()
Definition: chrono.h:993
void on_abbr_weekday()
Definition: chrono.h:1367
static constexpr const size_t max_size
Definition: chrono.h:335
FMT_CONSTEXPR void on_abbr_month()
Definition: chrono.h:931
FMT_CONSTEXPR void on_full_month()
Definition: chrono.h:932
constexpr auto in(type t, int set) -> bool
Definition: core.h:611
void on_day_of_year()
Definition: chrono.h:1904
void on_24_hour_time()
Definition: chrono.h:1965
FMT_CONSTEXPR void on_iso_date()
Definition: chrono.h:948
void write_sign()
Definition: chrono.h:1844
FMT_INLINE auto get_iterator(Buf &buf, OutputIt) -> decltype(buf.out())
Definition: core.h:1119
void on_12_hour(numeric_system ns, pad_type pad)
Definition: chrono.h:1917
#define FMT_END_NAMESPACE
Definition: core.h:179
void pad(T &out, int n)
Definition: ImfXdr.h:407
#define FMT_THROW(x)
Definition: format.h:120
FMT_CONSTEXPR auto parse_precision(const Char *begin, const Char *end, int &value, arg_ref< Char > &ref, basic_format_parse_context< Char > &ctx) -> const Char *
Definition: core.h:2277
auto format(const duration &d, FormatContext &ctx) const -> decltype(ctx.out())
Definition: chrono.h:2099
void on_us_date()
Definition: chrono.h:1890
FormatContext & context
Definition: chrono.h:1768
basic_string_view< char > string_view
Definition: core.h:501
FMT_CONSTEXPR void on_iso_week_based_short_year()
Definition: chrono.h:969
#define FMT_BEGIN_DETAIL_NAMESPACE
Definition: format.h:52
FMT_CONSTEXPR void on_loc_time(numeric_system)
Definition: chrono.h:989
constexpr auto end() const noexcept-> iterator
Definition: core.h:446
FMT_CONSTEXPR void on_loc_date(numeric_system)
Definition: chrono.h:945
FMT_CONSTEXPR void on_dec0_weekday(numeric_system)
Definition: chrono.h:972
FMT_CONSTEXPR void on_iso_week_based_year()
Definition: chrono.h:925
void on_duration_unit()
Definition: chrono.h:1995
FMT_CONSTEXPR void on_second(numeric_system)
Definition: chrono.h:943
void on_day_of_month_space(numeric_system)
Definition: chrono.h:1906
GLdouble n
Definition: glcorearb.h:2008
FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system)
Definition: chrono.h:935
GLfloat f
Definition: glcorearb.h:1926
FMT_CONSTEXPR void on_24_hour(numeric_system)
Definition: chrono.h:940
void on_duration_value()
Definition: chrono.h:1614
GLintptr offset
Definition: glcorearb.h:665
Int to_nonnegative_int(T value, Int upper)
Definition: chrono.h:1050
OutputIt copy_unit(string_view unit, OutputIt out, Char)
Definition: chrono.h:1718
const char * tm_wday_full_name(int wday)
Definition: chrono.h:1000
void write_codecvt(codecvt_result< CodeUnit > &out, string_view in_buf, const std::locale &loc)
Definition: chrono.h:343
void on_iso_time()
Definition: chrono.h:1977
null gmtime_r(...)
Definition: chrono.h:326
constexpr auto end() const noexcept-> iterator
Definition: core.h:679
const char * tm_mon_full_name(int mon)
Definition: chrono.h:1012
~get_locale()
Definition: chrono.h:1757
FMT_CONSTEXPR void on_duration_unit()
Definition: chrono.h:954
const Char * iterator
Definition: core.h:662
void on_us_date()
Definition: chrono.h:1432
void on_24_hour(numeric_system ns, pad_type pad)
Definition: chrono.h:1908
FMT_CONSTEXPR void on_iso_time()
Definition: chrono.h:951
FMT_CONSTEXPR void on_offset_year()
Definition: chrono.h:966
void on_iso_week_based_year()
Definition: chrono.h:1898
void on_datetime(numeric_system)
Definition: chrono.h:1887
const char * tm_mon_short_name(int mon)
Definition: chrono.h:1018
auto size() const -> size_t
Definition: format.h:1416
void on_iso_date()
Definition: chrono.h:1439
void on_full_month()
Definition: chrono.h:1398
FMT_CONSTEXPR void on_loc_date(numeric_system)
Definition: chrono.h:988
FMT_CONSTEXPR void on_dec1_weekday(numeric_system)
Definition: chrono.h:930
FMT_CONSTEXPR void on_iso_week_of_year(numeric_system)
Definition: chrono.h:936
GLuint GLuint end
Definition: glcorearb.h:475
GLint GLint GLsizei GLint GLenum format
Definition: glcorearb.h:108
void on_iso_week_of_year(numeric_system ns)
Definition: chrono.h:1513
FMT_CONSTEXPR void on_duration_unit()
Definition: chrono.h:1638
FMT_CONSTEXPR void on_abbr_month()
Definition: chrono.h:974
FMT_CONSTEXPR auto parse(basic_format_parse_context< Char > &ctx) -> decltype(ctx.begin())
Definition: chrono.h:2090
FMT_CONSTEXPR auto parse_align(char c) -> align_t
Definition: core.h:2178
void on_dec0_week_of_year(numeric_system)
Definition: chrono.h:1901
basic_memory_buffer< char > memory_buffer
Definition: format.h:1036
void on_duration_value()
Definition: chrono.h:1989
FMT_CONSTEXPR void on_abbr_weekday()
Definition: chrono.h:927
FMT_CONSTEXPR void on_full_month()
Definition: chrono.h:975
void on_12_hour_time()
Definition: chrono.h:1960
constexpr bool isnan(T value)
Definition: format.h:2797
null gmtime_s(...)
Definition: chrono.h:327
void on_century(numeric_system)
Definition: chrono.h:1897
FMT_CONSTEXPR void on_24_hour_time()
Definition: chrono.h:950
FMT_CONSTEXPR void on_utc_offset(numeric_system)
Definition: chrono.h:955
FMT_CONSTEXPR auto code_point_length(const Char *begin) -> int
Definition: core.h:2130
void on_loc_time(numeric_system ns)
Definition: chrono.h:1426
png_const_structrp png_const_inforp int * unit
Definition: png.h:2161
CodeUnit buf[max_size]
Definition: chrono.h:336
FMT_CONSTEXPR void on_minute(numeric_system, pad_type)
Definition: chrono.h:985
FMT_CONSTEXPR void on_dec1_weekday(numeric_system)
Definition: chrono.h:973
FMT_CONSTEXPR void on_dec0_weekday(numeric_system)
Definition: chrono.h:929
numeric_system
Definition: chrono.h:635
OutputIt format_duration_unit(OutputIt out)
Definition: chrono.h:1731
constexpr auto size() const noexcept-> size_t
Definition: core.h:901
FMT_CONSTEXPR void on_short_year(numeric_system)
Definition: chrono.h:965
void write_nan()
Definition: chrono.h:1863
void on_abbr_weekday()
Definition: chrono.h:1881
vfloat4 round(const vfloat4 &a)
Definition: simd.h:7647
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
void on_24_hour(numeric_system ns, pad_type pad)
Definition: chrono.h:1544
GLint GLenum GLint x
Definition: glcorearb.h:409
FMT_CONSTEXPR void on_full_weekday()
Definition: chrono.h:928
FMT_CONSTEXPR void on_iso_date()
Definition: chrono.h:991
FMT_NORETURN void unsupported()
Definition: chrono.h:960
FMT_CONSTEXPR void on_minute(numeric_system)
Definition: chrono.h:942
void on_dec0_weekday(numeric_system ns)
Definition: chrono.h:1379
FMT_CONSTEXPR void on_day_of_month_space(numeric_system)
Definition: chrono.h:939
FMT_CONSTEXPR void on_day_of_month_space(numeric_system)
Definition: chrono.h:982
void format_tm(const tm &time, Callback cb, Args...args)
Definition: chrono.h:1868
GLdouble t
Definition: glad.h:2397
void write(Rep value, int width, pad_type pad=pad_type::unspecified)
Definition: chrono.h:1851
std::tm time() const
Definition: chrono.h:1836
void on_duration_unit()
Definition: chrono.h:1615
FMT_CONSTEXPR void unsupported()
Definition: chrono.h:918
void on_full_weekday()
Definition: chrono.h:1882
FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system)
Definition: chrono.h:934
void on_loc_date(numeric_system)
Definition: chrono.h:1888
FMT_CONSTEXPR void on_12_hour(numeric_system)
Definition: chrono.h:941
FMT_CONSTEXPR void on_24_hour(numeric_system, pad_type)
Definition: chrono.h:983
void on_short_year(numeric_system ns)
Definition: chrono.h:1464
bool handle_nan_inf()
Definition: chrono.h:1809
FMT_BEGIN_DETAIL_NAMESPACE constexpr auto is_negative(T value) -> bool
Definition: format.h:1136
GLenum GLint GLint * precision
Definition: glcorearb.h:1925
FMT_CONSTEXPR void on_minute(numeric_system, pad_type)
Definition: chrono.h:1627
basic_string_view< Char > format_str
Definition: chrono.h:2214
FMT_CONSTEXPR void on_24_hour(numeric_system, pad_type)
Definition: chrono.h:1625
FMT_CONSTEXPR void on_short_year(numeric_system)
Definition: chrono.h:922
null localtime_r FMT_NOMACRO(...)
Definition: chrono.h:324
FMT_CONSTEXPR void on_iso_week_based_year()
Definition: chrono.h:968
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:2002
FMT_CONSTEXPR To safe_float_conversion(const From from, int &ec)
Definition: chrono.h:157
FMT_CONSTEXPR void on_loc_time(numeric_system)
Definition: chrono.h:946
void on_abbr_month()
Definition: chrono.h:1392
void on_utc_offset(numeric_system)
Definition: chrono.h:1892
std::integral_constant< bool, std::numeric_limits< T >::is_signed||std::is_same< T, int128_opt >::value > is_signed
Definition: format.h:818
FMT_CONSTEXPR const Char * parse_chrono_format(const Char *begin, const Char *end, Handler &&handler)
Definition: chrono.h:667
exint Int
Definition: APEX_Include.h:61
typename pvt::make_void< Ts...>::type void_t
Definition: type_traits.h:37
void on_dec1_weekday(numeric_system ns)
Definition: chrono.h:1383
FMT_CONSTEXPR auto parse(basic_format_parse_context< Char > &ctx) -> decltype(ctx.begin())
Definition: chrono.h:2252
void on_iso_week_based_year()
Definition: chrono.h:1519
FMT_CONSTEXPR void on_utc_offset(numeric_system)
Definition: chrono.h:996
void on_iso_time()
Definition: chrono.h:1598
std::chrono::duration< rep > seconds
Definition: chrono.h:1777
#define FMT_CONSTEXPR
Definition: core.h:104
void on_dec_month(numeric_system)
Definition: chrono.h:1900
void on_dec1_week_of_year(numeric_system)
Definition: chrono.h:1902
chrono_formatter(FormatContext &ctx, OutputIt o, std::chrono::duration< Rep, Period > d)
Definition: chrono.h:1785
FMT_CONSTEXPR void on_am_pm()
Definition: chrono.h:1632
null localtime_s(...)
Definition: chrono.h:325
FMT_CONSTEXPR void on_24_hour_time()
Definition: chrono.h:1630
void on_iso_date()
Definition: chrono.h:1891
FMT_CONSTEXPR void on_iso_week_of_year(numeric_system)
Definition: chrono.h:979
void on_iso_week_based_short_year()
Definition: chrono.h:1899
FMT_CONSTEXPR auto parse_dynamic_spec(const Char *begin, const Char *end, int &value, arg_ref< Char > &ref, basic_format_parse_context< Char > &ctx) -> const Char *
Definition: core.h:2255
void on_tz_name()
Definition: chrono.h:1893
FMT_CONSTEXPR void on_century(numeric_system)
Definition: chrono.h:924
void on_full_weekday()
Definition: chrono.h:1373
auto write_tm_str(OutputIt out, string_view sv, const std::locale &loc) -> OutputIt
Definition: chrono.h:391
void on_day_of_month(numeric_system ns)
Definition: chrono.h:1529
void do_write(buffer< Char > &buf, const std::tm &time, const std::locale &loc, char format, char modifier)
Definition: chrono.h:406
FMT_CONSTEXPR void on_12_hour_time()
Definition: chrono.h:992
FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system)
Definition: chrono.h:977
auto ptr(T p) -> const void *
Definition: format.h:4331
GLuint GLfloat * val
Definition: glcorearb.h:1608
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
GA_API const UT_StringHolder N
FMT_INLINE auto format_to(OutputIt out, format_string< T...> fmt, T &&...args) -> OutputIt
Definition: core.h:2843
void on_iso_week_based_short_year()
Definition: chrono.h:1520
void on_day_of_month_space(numeric_system ns)
Definition: chrono.h:1533
**If you just want to fire and args
Definition: thread.h:618
auto write_padding(OutputIt out, pad_type pad, int width) -> OutputIt
Definition: chrono.h:654
void on_short_year(numeric_system)
Definition: chrono.h:1895
FMT_CONSTEXPR void on_datetime(numeric_system)
Definition: chrono.h:987
GLint GLsizei width
Definition: glcorearb.h:103
constexpr const char * digits2(size_t value)
Definition: format.h:1168
void on_year(numeric_system)
Definition: chrono.h:1894
constexpr unsigned c_encoding() const noexcept
Definition: chrono.h:2014
To fmt_safe_duration_cast(std::chrono::duration< FromRep, FromPeriod > from)
Definition: chrono.h:1670
auto write(OutputIt out, const std::tm &time, const std::locale &loc, char format, char modifier=0) -> OutputIt
Definition: chrono.h:419
void on_second(numeric_system ns, pad_type pad)
Definition: chrono.h:1935
FMT_CONSTEXPR void on_offset_year()
Definition: chrono.h:923
FMT_CONSTEXPR20 auto count_digits(uint64_t n) -> int
Definition: format.h:1228
void on_full_month()
Definition: chrono.h:1886
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
FMT_CONSTEXPR void on_datetime(numeric_system)
Definition: chrono.h:944
FMT_CONSTEXPR void on_second(numeric_system, pad_type)
Definition: chrono.h:986
FMT_CONSTEXPR void on_dec_month(numeric_system)
Definition: chrono.h:933
FMT_CONSTEXPR auto is_utf8() -> bool
Definition: core.h:380
void on_dec0_weekday(numeric_system)
Definition: chrono.h:1883
constexpr long long pow10(std::uint32_t n)
Definition: chrono.h:1064
FMT_CONSTEXPR void on_full_weekday()
Definition: chrono.h:971
FMT_CONSTEXPR void on_day_of_month(numeric_system)
Definition: chrono.h:981
constexpr auto begin() const noexcept-> iterator
Definition: core.h:445
#define FMT_ASSERT(condition, message)
Definition: core.h:336
#define FMT_BEGIN_NAMESPACE
Definition: core.h:176
Rep hour() const
Definition: chrono.h:1826
OutputIt out
Definition: chrono.h:1769
constexpr auto to_ascii(Char c) -> char
Definition: core.h:2120
void on_12_hour_time()
Definition: chrono.h:1581
void on_loc_time(numeric_system)
Definition: chrono.h:1889
constexpr FMT_INLINE auto const_check(T value) -> T
Definition: core.h:323
FMT_CONSTEXPR void on_second(numeric_system, pad_type)
Definition: chrono.h:1628
FMT_CONSTEXPR void on_iso_time()
Definition: chrono.h:994
bool isfinite(T)
Definition: chrono.h:1643
constexpr auto begin() const noexcept-> iterator
Definition: core.h:672
#define FMT_END_EXPORT
Definition: core.h:187
auto is_big_endian() -> bool
Definition: format.h:346
const char * tm_wday_short_name(int wday)
Definition: chrono.h:1006
void on_dec_month(numeric_system ns)
Definition: chrono.h:1492
std::chrono::duration< Rep, std::milli > get_milliseconds(std::chrono::duration< Rep, Period > d)
Definition: chrono.h:1680
bool convert(basic_string_view< WChar > s)
Definition: format.h:1445
void on_datetime(numeric_system ns)
Definition: chrono.h:1405
CodeUnit * end
Definition: chrono.h:337
void on_utc_offset(numeric_system ns)
Definition: chrono.h:1456
FMT_CONSTEXPR void on_dec_month(numeric_system)
Definition: chrono.h:976
FMT_BEGIN_EXPORT std::tm localtime(std::time_t time)
Definition: chrono.h:444
FMT_CONSTEXPR20 FMT_INLINE void copy2(Char *dst, const char *src)
Definition: format.h:1331
GLint GLsizei count
Definition: glcorearb.h:405
void on_12_hour(numeric_system ns, pad_type pad)
Definition: chrono.h:1549
void write_ninf()
Definition: chrono.h:1865
FMT_CONSTEXPR void on_day_of_year()
Definition: chrono.h:980
FMT_CONSTEXPR void on_text(const Char *, const Char *)
Definition: chrono.h:963
FMT_CONSTEXPR void on_us_date()
Definition: chrono.h:947
FMT_CONSTEXPR void on_am_pm()
Definition: chrono.h:995
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:566