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


plotjuggler
Author(s): Davide Faconti
autogenerated on Mon Nov 11 2024 03:23:43