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 <chrono>
12 #include <ctime>
13 #include <locale>
14 #include <sstream>
15 
16 #include "format.h"
17 #include "locale.h"
18 
20 
21 // Enable safe chrono durations, unless explicitly disabled.
22 #ifndef FMT_SAFE_DURATION_CAST
23 # define FMT_SAFE_DURATION_CAST 1
24 #endif
25 #if FMT_SAFE_DURATION_CAST
26 
27 // For conversion between std::chrono::durations without undefined
28 // behaviour or erroneous results.
29 // This is a stripped down version of duration_cast, for inclusion in fmt.
30 // See https://github.com/pauldreik/safe_duration_cast
31 //
32 // Copyright Paul Dreik 2019
33 namespace safe_duration_cast {
34 
35 template <typename To, typename From,
39 FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {
40  ec = 0;
41  using F = std::numeric_limits<From>;
42  using T = std::numeric_limits<To>;
43  static_assert(F::is_integer, "From must be integral");
44  static_assert(T::is_integer, "To must be integral");
45 
46  // A and B are both signed, or both unsigned.
47  if (F::digits <= T::digits) {
48  // From fits in To without any problem.
49  } else {
50  // From does not always fit in To, resort to a dynamic check.
51  if (from < (T::min)() || from > (T::max)()) {
52  // outside range.
53  ec = 1;
54  return {};
55  }
56  }
57  return static_cast<To>(from);
58 }
59 
64 template <typename To, typename From,
68 FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {
69  ec = 0;
70  using F = std::numeric_limits<From>;
71  using T = std::numeric_limits<To>;
72  static_assert(F::is_integer, "From must be integral");
73  static_assert(T::is_integer, "To must be integral");
74 
76  // From may be negative, not allowed!
77  if (fmt::detail::is_negative(from)) {
78  ec = 1;
79  return {};
80  }
81  // From is positive. Can it always fit in To?
82  if (F::digits > T::digits &&
83  from > static_cast<From>(detail::max_value<To>())) {
84  ec = 1;
85  return {};
86  }
87  }
88 
89  if (!F::is_signed && T::is_signed && F::digits >= T::digits &&
90  from > static_cast<From>(detail::max_value<To>())) {
91  ec = 1;
92  return {};
93  }
94  return static_cast<To>(from); // Lossless conversion.
95 }
96 
97 template <typename To, typename From,
99 FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {
100  ec = 0;
101  return from;
102 } // function
103 
104 // clang-format off
117 // clang-format on
118 template <typename To, typename From,
120 FMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) {
121  ec = 0;
122  using T = std::numeric_limits<To>;
123  static_assert(std::is_floating_point<From>::value, "From must be floating");
124  static_assert(std::is_floating_point<To>::value, "To must be floating");
125 
126  // catch the only happy case
127  if (std::isfinite(from)) {
128  if (from >= T::lowest() && from <= (T::max)()) {
129  return static_cast<To>(from);
130  }
131  // not within range.
132  ec = 1;
133  return {};
134  }
135 
136  // nan and inf will be preserved
137  return static_cast<To>(from);
138 } // function
139 
140 template <typename To, typename From,
142 FMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) {
143  ec = 0;
144  static_assert(std::is_floating_point<From>::value, "From must be floating");
145  return from;
146 }
147 
151 template <typename To, typename FromRep, typename FromPeriod,
154 To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
155  int& ec) {
156  using From = std::chrono::duration<FromRep, FromPeriod>;
157  ec = 0;
158  // the basic idea is that we need to convert from count() in the from type
159  // to count() in the To type, by multiplying it with this:
160  struct Factor
161  : std::ratio_divide<typename From::period, typename To::period> {};
162 
163  static_assert(Factor::num > 0, "num must be positive");
164  static_assert(Factor::den > 0, "den must be positive");
165 
166  // the conversion is like this: multiply from.count() with Factor::num
167  // /Factor::den and convert it to To::rep, all this without
168  // overflow/underflow. let's start by finding a suitable type that can hold
169  // both To, From and Factor::num
170  using IntermediateRep =
171  typename std::common_type<typename From::rep, typename To::rep,
172  decltype(Factor::num)>::type;
173 
174  // safe conversion to IntermediateRep
175  IntermediateRep count =
176  lossless_integral_conversion<IntermediateRep>(from.count(), ec);
177  if (ec) return {};
178  // multiply with Factor::num without overflow or underflow
179  if (detail::const_check(Factor::num != 1)) {
180  const auto max1 = detail::max_value<IntermediateRep>() / Factor::num;
181  if (count > max1) {
182  ec = 1;
183  return {};
184  }
185  const auto min1 =
187  if (count < min1) {
188  ec = 1;
189  return {};
190  }
191  count *= Factor::num;
192  }
193 
194  if (detail::const_check(Factor::den != 1)) count /= Factor::den;
195  auto tocount = lossless_integral_conversion<typename To::rep>(count, ec);
196  return ec ? To() : To(tocount);
197 }
198 
202 template <typename To, typename FromRep, typename FromPeriod,
205 To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
206  int& ec) {
207  using From = std::chrono::duration<FromRep, FromPeriod>;
208  ec = 0;
209  if (std::isnan(from.count())) {
210  // nan in, gives nan out. easy.
211  return To{std::numeric_limits<typename To::rep>::quiet_NaN()};
212  }
213  // maybe we should also check if from is denormal, and decide what to do about
214  // it.
215 
216  // +-inf should be preserved.
217  if (std::isinf(from.count())) {
218  return To{from.count()};
219  }
220 
221  // the basic idea is that we need to convert from count() in the from type
222  // to count() in the To type, by multiplying it with this:
223  struct Factor
224  : std::ratio_divide<typename From::period, typename To::period> {};
225 
226  static_assert(Factor::num > 0, "num must be positive");
227  static_assert(Factor::den > 0, "den must be positive");
228 
229  // the conversion is like this: multiply from.count() with Factor::num
230  // /Factor::den and convert it to To::rep, all this without
231  // overflow/underflow. let's start by finding a suitable type that can hold
232  // both To, From and Factor::num
233  using IntermediateRep =
234  typename std::common_type<typename From::rep, typename To::rep,
235  decltype(Factor::num)>::type;
236 
237  // force conversion of From::rep -> IntermediateRep to be safe,
238  // even if it will never happen be narrowing in this context.
239  IntermediateRep count =
240  safe_float_conversion<IntermediateRep>(from.count(), ec);
241  if (ec) {
242  return {};
243  }
244 
245  // multiply with Factor::num without overflow or underflow
246  if (Factor::num != 1) {
247  constexpr auto max1 = detail::max_value<IntermediateRep>() /
248  static_cast<IntermediateRep>(Factor::num);
249  if (count > max1) {
250  ec = 1;
251  return {};
252  }
253  constexpr auto min1 = std::numeric_limits<IntermediateRep>::lowest() /
254  static_cast<IntermediateRep>(Factor::num);
255  if (count < min1) {
256  ec = 1;
257  return {};
258  }
259  count *= static_cast<IntermediateRep>(Factor::num);
260  }
261 
262  // this can't go wrong, right? den>0 is checked earlier.
263  if (Factor::den != 1) {
264  using common_t = typename std::common_type<IntermediateRep, intmax_t>::type;
265  count /= static_cast<common_t>(Factor::den);
266  }
267 
268  // convert to the to type, safely
269  using ToRep = typename To::rep;
270 
271  const ToRep tocount = safe_float_conversion<ToRep>(count, ec);
272  if (ec) {
273  return {};
274  }
275  return To{tocount};
276 }
277 } // namespace safe_duration_cast
278 #endif
279 
280 // Prevents expansion of a preceding token as a function-style macro.
281 // Usage: f FMT_NOMACRO()
282 #define FMT_NOMACRO
283 
284 namespace detail {
285 inline null<> localtime_r FMT_NOMACRO(...) { return null<>(); }
286 inline null<> localtime_s(...) { return null<>(); }
287 inline null<> gmtime_r(...) { return null<>(); }
288 inline null<> gmtime_s(...) { return null<>(); }
289 } // namespace detail
290 
291 // Thread-safe replacement for std::localtime
292 inline std::tm localtime(std::time_t time) {
293  struct dispatcher {
294  std::time_t time_;
295  std::tm tm_;
296 
297  dispatcher(std::time_t t) : time_(t) {}
298 
299  bool run() {
300  using namespace fmt::detail;
301  return handle(localtime_r(&time_, &tm_));
302  }
303 
304  bool handle(std::tm* tm) { return tm != nullptr; }
305 
306  bool handle(detail::null<>) {
307  using namespace fmt::detail;
308  return fallback(localtime_s(&tm_, &time_));
309  }
310 
311  bool fallback(int res) { return res == 0; }
312 
313 #if !FMT_MSC_VER
314  bool fallback(detail::null<>) {
315  using namespace fmt::detail;
316  std::tm* tm = std::localtime(&time_);
317  if (tm) tm_ = *tm;
318  return tm != nullptr;
319  }
320 #endif
321  };
322  dispatcher lt(time);
323  // Too big time values may be unsupported.
324  if (!lt.run()) FMT_THROW(format_error("time_t value out of range"));
325  return lt.tm_;
326 }
327 
328 inline std::tm localtime(
329  std::chrono::time_point<std::chrono::system_clock> time_point) {
330  return localtime(std::chrono::system_clock::to_time_t(time_point));
331 }
332 
333 // Thread-safe replacement for std::gmtime
334 inline std::tm gmtime(std::time_t time) {
335  struct dispatcher {
336  std::time_t time_;
337  std::tm tm_;
338 
339  dispatcher(std::time_t t) : time_(t) {}
340 
341  bool run() {
342  using namespace fmt::detail;
343  return handle(gmtime_r(&time_, &tm_));
344  }
345 
346  bool handle(std::tm* tm) { return tm != nullptr; }
347 
348  bool handle(detail::null<>) {
349  using namespace fmt::detail;
350  return fallback(gmtime_s(&tm_, &time_));
351  }
352 
353  bool fallback(int res) { return res == 0; }
354 
355 #if !FMT_MSC_VER
356  bool fallback(detail::null<>) {
357  std::tm* tm = std::gmtime(&time_);
358  if (tm) tm_ = *tm;
359  return tm != nullptr;
360  }
361 #endif
362  };
363  dispatcher gt(time);
364  // Too big time values may be unsupported.
365  if (!gt.run()) FMT_THROW(format_error("time_t value out of range"));
366  return gt.tm_;
367 }
368 
369 inline std::tm gmtime(
370  std::chrono::time_point<std::chrono::system_clock> time_point) {
371  return gmtime(std::chrono::system_clock::to_time_t(time_point));
372 }
373 
374 namespace detail {
375 inline size_t strftime(char* str, size_t count, const char* format,
376  const std::tm* time) {
377  return std::strftime(str, count, format, time);
378 }
379 
380 inline size_t strftime(wchar_t* str, size_t count, const wchar_t* format,
381  const std::tm* time) {
382  return std::wcsftime(str, count, format, time);
383 }
384 } // namespace detail
385 
386 template <typename Char>
387 struct formatter<std::chrono::time_point<std::chrono::system_clock>, Char>
388  : formatter<std::tm, Char> {
389  template <typename FormatContext>
390  auto format(std::chrono::time_point<std::chrono::system_clock> val,
391  FormatContext& ctx) -> decltype(ctx.out()) {
392  std::tm time = localtime(val);
393  return formatter<std::tm, Char>::format(time, ctx);
394  }
395 };
396 
397 template <typename Char> struct formatter<std::tm, Char> {
398  template <typename ParseContext>
399  auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
400  auto it = ctx.begin();
401  if (it != ctx.end() && *it == ':') ++it;
402  auto end = it;
403  while (end != ctx.end() && *end != '}') ++end;
404  tm_format.reserve(detail::to_unsigned(end - it + 1));
405  tm_format.append(it, end);
406  tm_format.push_back('\0');
407  return end;
408  }
409 
410  template <typename FormatContext>
411  auto format(const std::tm& tm, FormatContext& ctx) -> decltype(ctx.out()) {
413  size_t start = buf.size();
414  for (;;) {
415  size_t size = buf.capacity() - start;
416  size_t count = detail::strftime(&buf[start], size, &tm_format[0], &tm);
417  if (count != 0) {
418  buf.resize(start + count);
419  break;
420  }
421  if (size >= tm_format.size() * 256) {
422  // If the buffer is 256 times larger than the format string, assume
423  // that `strftime` gives an empty result. There doesn't seem to be a
424  // better way to distinguish the two cases:
425  // https://github.com/fmtlib/fmt/issues/367
426  break;
427  }
428  const size_t MIN_GROWTH = 10;
429  buf.reserve(buf.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH));
430  }
431  return std::copy(buf.begin(), buf.end(), ctx.out());
432  }
433 
435 };
436 
437 namespace detail {
438 template <typename Period> FMT_CONSTEXPR const char* get_units() {
439  return nullptr;
440 }
441 template <> FMT_CONSTEXPR const char* get_units<std::atto>() { return "as"; }
442 template <> FMT_CONSTEXPR const char* get_units<std::femto>() { return "fs"; }
443 template <> FMT_CONSTEXPR const char* get_units<std::pico>() { return "ps"; }
444 template <> FMT_CONSTEXPR const char* get_units<std::nano>() { return "ns"; }
445 template <> FMT_CONSTEXPR const char* get_units<std::micro>() { return "µs"; }
446 template <> FMT_CONSTEXPR const char* get_units<std::milli>() { return "ms"; }
447 template <> FMT_CONSTEXPR const char* get_units<std::centi>() { return "cs"; }
448 template <> FMT_CONSTEXPR const char* get_units<std::deci>() { return "ds"; }
449 template <> FMT_CONSTEXPR const char* get_units<std::ratio<1>>() { return "s"; }
450 template <> FMT_CONSTEXPR const char* get_units<std::deca>() { return "das"; }
451 template <> FMT_CONSTEXPR const char* get_units<std::hecto>() { return "hs"; }
452 template <> FMT_CONSTEXPR const char* get_units<std::kilo>() { return "ks"; }
453 template <> FMT_CONSTEXPR const char* get_units<std::mega>() { return "Ms"; }
454 template <> FMT_CONSTEXPR const char* get_units<std::giga>() { return "Gs"; }
455 template <> FMT_CONSTEXPR const char* get_units<std::tera>() { return "Ts"; }
456 template <> FMT_CONSTEXPR const char* get_units<std::peta>() { return "Ps"; }
457 template <> FMT_CONSTEXPR const char* get_units<std::exa>() { return "Es"; }
458 template <> FMT_CONSTEXPR const char* get_units<std::ratio<60>>() {
459  return "m";
460 }
461 template <> FMT_CONSTEXPR const char* get_units<std::ratio<3600>>() {
462  return "h";
463 }
464 
465 enum class numeric_system {
466  standard,
467  // Alternative numeric system, e.g. 十二 instead of 12 in ja_JP locale.
469 };
470 
471 // Parses a put_time-like format string and invokes handler actions.
472 template <typename Char, typename Handler>
473 FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin,
474  const Char* end,
475  Handler&& handler) {
476  auto ptr = begin;
477  while (ptr != end) {
478  auto c = *ptr;
479  if (c == '}') break;
480  if (c != '%') {
481  ++ptr;
482  continue;
483  }
484  if (begin != ptr) handler.on_text(begin, ptr);
485  ++ptr; // consume '%'
486  if (ptr == end) FMT_THROW(format_error("invalid format"));
487  c = *ptr++;
488  switch (c) {
489  case '%':
490  handler.on_text(ptr - 1, ptr);
491  break;
492  case 'n': {
493  const Char newline[] = {'\n'};
494  handler.on_text(newline, newline + 1);
495  break;
496  }
497  case 't': {
498  const Char tab[] = {'\t'};
499  handler.on_text(tab, tab + 1);
500  break;
501  }
502  // Day of the week:
503  case 'a':
504  handler.on_abbr_weekday();
505  break;
506  case 'A':
507  handler.on_full_weekday();
508  break;
509  case 'w':
510  handler.on_dec0_weekday(numeric_system::standard);
511  break;
512  case 'u':
513  handler.on_dec1_weekday(numeric_system::standard);
514  break;
515  // Month:
516  case 'b':
517  handler.on_abbr_month();
518  break;
519  case 'B':
520  handler.on_full_month();
521  break;
522  // Hour, minute, second:
523  case 'H':
524  handler.on_24_hour(numeric_system::standard);
525  break;
526  case 'I':
527  handler.on_12_hour(numeric_system::standard);
528  break;
529  case 'M':
530  handler.on_minute(numeric_system::standard);
531  break;
532  case 'S':
533  handler.on_second(numeric_system::standard);
534  break;
535  // Other:
536  case 'c':
537  handler.on_datetime(numeric_system::standard);
538  break;
539  case 'x':
540  handler.on_loc_date(numeric_system::standard);
541  break;
542  case 'X':
543  handler.on_loc_time(numeric_system::standard);
544  break;
545  case 'D':
546  handler.on_us_date();
547  break;
548  case 'F':
549  handler.on_iso_date();
550  break;
551  case 'r':
552  handler.on_12_hour_time();
553  break;
554  case 'R':
555  handler.on_24_hour_time();
556  break;
557  case 'T':
558  handler.on_iso_time();
559  break;
560  case 'p':
561  handler.on_am_pm();
562  break;
563  case 'Q':
564  handler.on_duration_value();
565  break;
566  case 'q':
567  handler.on_duration_unit();
568  break;
569  case 'z':
570  handler.on_utc_offset();
571  break;
572  case 'Z':
573  handler.on_tz_name();
574  break;
575  // Alternative representation:
576  case 'E': {
577  if (ptr == end) FMT_THROW(format_error("invalid format"));
578  c = *ptr++;
579  switch (c) {
580  case 'c':
581  handler.on_datetime(numeric_system::alternative);
582  break;
583  case 'x':
584  handler.on_loc_date(numeric_system::alternative);
585  break;
586  case 'X':
587  handler.on_loc_time(numeric_system::alternative);
588  break;
589  default:
590  FMT_THROW(format_error("invalid format"));
591  }
592  break;
593  }
594  case 'O':
595  if (ptr == end) FMT_THROW(format_error("invalid format"));
596  c = *ptr++;
597  switch (c) {
598  case 'w':
599  handler.on_dec0_weekday(numeric_system::alternative);
600  break;
601  case 'u':
602  handler.on_dec1_weekday(numeric_system::alternative);
603  break;
604  case 'H':
605  handler.on_24_hour(numeric_system::alternative);
606  break;
607  case 'I':
608  handler.on_12_hour(numeric_system::alternative);
609  break;
610  case 'M':
611  handler.on_minute(numeric_system::alternative);
612  break;
613  case 'S':
614  handler.on_second(numeric_system::alternative);
615  break;
616  default:
617  FMT_THROW(format_error("invalid format"));
618  }
619  break;
620  default:
621  FMT_THROW(format_error("invalid format"));
622  }
623  begin = ptr;
624  }
625  if (begin != ptr) handler.on_text(begin, ptr);
626  return ptr;
627 }
628 
631 
632  template <typename Char> void on_text(const Char*, const Char*) {}
633  FMT_NORETURN void on_abbr_weekday() { report_no_date(); }
634  FMT_NORETURN void on_full_weekday() { report_no_date(); }
635  FMT_NORETURN void on_dec0_weekday(numeric_system) { report_no_date(); }
636  FMT_NORETURN void on_dec1_weekday(numeric_system) { report_no_date(); }
637  FMT_NORETURN void on_abbr_month() { report_no_date(); }
638  FMT_NORETURN void on_full_month() { report_no_date(); }
643  FMT_NORETURN void on_datetime(numeric_system) { report_no_date(); }
644  FMT_NORETURN void on_loc_date(numeric_system) { report_no_date(); }
645  FMT_NORETURN void on_loc_time(numeric_system) { report_no_date(); }
646  FMT_NORETURN void on_us_date() { report_no_date(); }
647  FMT_NORETURN void on_iso_date() { report_no_date(); }
648  void on_12_hour_time() {}
649  void on_24_hour_time() {}
650  void on_iso_time() {}
651  void on_am_pm() {}
654  FMT_NORETURN void on_utc_offset() { report_no_date(); }
655  FMT_NORETURN void on_tz_name() { report_no_date(); }
656 };
657 
659 inline bool isnan(T) {
660  return false;
661 }
663 inline bool isnan(T value) {
664  return std::isnan(value);
665 }
666 
668 inline bool isfinite(T) {
669  return true;
670 }
672 inline bool isfinite(T value) {
673  return std::isfinite(value);
674 }
675 
676 // Converts value to int and checks that it's in the range [0, upper).
678 inline int to_nonnegative_int(T value, int upper) {
679  FMT_ASSERT(value >= 0 && value <= upper, "invalid value");
680  (void)upper;
681  return static_cast<int>(value);
682 }
684 inline int to_nonnegative_int(T value, int upper) {
685  FMT_ASSERT(
686  std::isnan(value) || (value >= 0 && value <= static_cast<T>(upper)),
687  "invalid value");
688  (void)upper;
689  return static_cast<int>(value);
690 }
691 
693 inline T mod(T x, int y) {
694  return x % static_cast<T>(y);
695 }
697 inline T mod(T x, int y) {
698  return std::fmod(x, static_cast<T>(y));
699 }
700 
701 // If T is an integral type, maps T to its unsigned counterpart, otherwise
702 // leaves it unchanged (unlike std::make_unsigned).
705  using type = T;
706 };
707 
708 template <typename T> struct make_unsigned_or_unchanged<T, true> {
710 };
711 
712 #if FMT_SAFE_DURATION_CAST
713 // throwing version of safe_duration_cast
714 template <typename To, typename FromRep, typename FromPeriod>
715 To fmt_safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from) {
716  int ec;
717  To to = safe_duration_cast::safe_duration_cast<To>(from, ec);
718  if (ec) FMT_THROW(format_error("cannot format duration"));
719  return to;
720 }
721 #endif
722 
723 template <typename Rep, typename Period,
725 inline std::chrono::duration<Rep, std::milli> get_milliseconds(
726  std::chrono::duration<Rep, Period> d) {
727  // this may overflow and/or the result may not fit in the
728  // target type.
729 #if FMT_SAFE_DURATION_CAST
730  using CommonSecondsType =
732  const auto d_as_common = fmt_safe_duration_cast<CommonSecondsType>(d);
733  const auto d_as_whole_seconds =
734  fmt_safe_duration_cast<std::chrono::seconds>(d_as_common);
735  // this conversion should be nonproblematic
736  const auto diff = d_as_common - d_as_whole_seconds;
737  const auto ms =
738  fmt_safe_duration_cast<std::chrono::duration<Rep, std::milli>>(diff);
739  return ms;
740 #else
741  auto s = std::chrono::duration_cast<std::chrono::seconds>(d);
742  return std::chrono::duration_cast<std::chrono::milliseconds>(d - s);
743 #endif
744 }
745 
746 template <typename Rep, typename Period,
748 inline std::chrono::duration<Rep, std::milli> get_milliseconds(
749  std::chrono::duration<Rep, Period> d) {
750  using common_type = typename std::common_type<Rep, std::intmax_t>::type;
751  auto ms = mod(d.count() * static_cast<common_type>(Period::num) /
752  static_cast<common_type>(Period::den) * 1000,
753  1000);
754  return std::chrono::duration<Rep, std::milli>(static_cast<Rep>(ms));
755 }
756 
757 template <typename Char, typename Rep, typename OutputIt>
758 OutputIt format_duration_value(OutputIt out, Rep val, int precision) {
759  const Char pr_f[] = {'{', ':', '.', '{', '}', 'f', '}', 0};
760  if (precision >= 0) return format_to(out, pr_f, val, precision);
761  const Char fp_f[] = {'{', ':', 'g', '}', 0};
762  const Char format[] = {'{', '}', 0};
763  return format_to(out, std::is_floating_point<Rep>::value ? fp_f : format,
764  val);
765 }
766 template <typename Char, typename OutputIt>
767 OutputIt copy_unit(string_view unit, OutputIt out, Char) {
768  return std::copy(unit.begin(), unit.end(), out);
769 }
770 
771 template <typename OutputIt>
772 OutputIt copy_unit(string_view unit, OutputIt out, wchar_t) {
773  // This works when wchar_t is UTF-32 because units only contain characters
774  // that have the same representation in UTF-16 and UTF-32.
775  utf8_to_utf16 u(unit);
776  return std::copy(u.c_str(), u.c_str() + u.size(), out);
777 }
778 
779 template <typename Char, typename Period, typename OutputIt>
780 OutputIt format_duration_unit(OutputIt out) {
781  if (const char* unit = get_units<Period>())
782  return copy_unit(string_view(unit), out, Char());
783  const Char num_f[] = {'[', '{', '}', ']', 's', 0};
784  if (const_check(Period::den == 1)) return format_to(out, num_f, Period::num);
785  const Char num_def_f[] = {'[', '{', '}', '/', '{', '}', ']', 's', 0};
786  return format_to(out, num_def_f, Period::num, Period::den);
787 }
788 
789 template <typename FormatContext, typename OutputIt, typename Rep,
790  typename Period>
792  FormatContext& context;
793  OutputIt out;
795  // rep is unsigned to avoid overflow.
796  using rep =
797  conditional_t<std::is_integral<Rep>::value && sizeof(Rep) < sizeof(int),
800  using seconds = std::chrono::duration<rep>;
802  using milliseconds = std::chrono::duration<rep, std::milli>;
803  bool negative;
804 
805  using char_type = typename FormatContext::char_type;
806 
807  explicit chrono_formatter(FormatContext& ctx, OutputIt o,
808  std::chrono::duration<Rep, Period> d)
809  : context(ctx),
810  out(o),
811  val(static_cast<rep>(d.count())),
812  negative(false) {
813  if (d.count() < 0) {
814  val = 0 - val;
815  negative = true;
816  }
817 
818  // this may overflow and/or the result may not fit in the
819  // target type.
820 #if FMT_SAFE_DURATION_CAST
821  // might need checked conversion (rep!=Rep)
822  auto tmpval = std::chrono::duration<rep, Period>(val);
823  s = fmt_safe_duration_cast<seconds>(tmpval);
824 #else
825  s = std::chrono::duration_cast<seconds>(
826  std::chrono::duration<rep, Period>(val));
827 #endif
828  }
829 
830  // returns true if nan or inf, writes to out.
831  bool handle_nan_inf() {
832  if (isfinite(val)) {
833  return false;
834  }
835  if (isnan(val)) {
836  write_nan();
837  return true;
838  }
839  // must be +-inf
840  if (val > 0) {
841  write_pinf();
842  } else {
843  write_ninf();
844  }
845  return true;
846  }
847 
848  Rep hour() const { return static_cast<Rep>(mod((s.count() / 3600), 24)); }
849 
850  Rep hour12() const {
851  Rep hour = static_cast<Rep>(mod((s.count() / 3600), 12));
852  return hour <= 0 ? 12 : hour;
853  }
854 
855  Rep minute() const { return static_cast<Rep>(mod((s.count() / 60), 60)); }
856  Rep second() const { return static_cast<Rep>(mod(s.count(), 60)); }
857 
858  std::tm time() const {
859  auto time = std::tm();
860  time.tm_hour = to_nonnegative_int(hour(), 24);
861  time.tm_min = to_nonnegative_int(minute(), 60);
862  time.tm_sec = to_nonnegative_int(second(), 60);
863  return time;
864  }
865 
866  void write_sign() {
867  if (negative) {
868  *out++ = '-';
869  negative = false;
870  }
871  }
872 
873  void write(Rep value, int width) {
874  write_sign();
875  if (isnan(value)) return write_nan();
877  to_unsigned(to_nonnegative_int(value, max_value<int>()));
878  int num_digits = detail::count_digits(n);
879  if (width > num_digits) out = std::fill_n(out, width - num_digits, '0');
880  out = format_decimal<char_type>(out, n, num_digits).end;
881  }
882 
883  void write_nan() { std::copy_n("nan", 3, out); }
884  void write_pinf() { std::copy_n("inf", 3, out); }
885  void write_ninf() { std::copy_n("-inf", 4, out); }
886 
887  void format_localized(const tm& time, char format, char modifier = 0) {
888  if (isnan(val)) return write_nan();
889  auto locale = context.locale().template get<std::locale>();
890  auto& facet = std::use_facet<std::time_put<char_type>>(locale);
891  std::basic_ostringstream<char_type> os;
892  os.imbue(locale);
893  facet.put(os, os, ' ', &time, format, modifier);
894  auto str = os.str();
895  std::copy(str.begin(), str.end(), out);
896  }
897 
898  void on_text(const char_type* begin, const char_type* end) {
899  std::copy(begin, end, out);
900  }
901 
902  // These are not implemented because durations don't have date information.
903  void on_abbr_weekday() {}
904  void on_full_weekday() {}
907  void on_abbr_month() {}
908  void on_full_month() {}
912  void on_us_date() {}
913  void on_iso_date() {}
914  void on_utc_offset() {}
915  void on_tz_name() {}
916 
918  if (handle_nan_inf()) return;
919 
920  if (ns == numeric_system::standard) return write(hour(), 2);
921  auto time = tm();
922  time.tm_hour = to_nonnegative_int(hour(), 24);
923  format_localized(time, 'H', 'O');
924  }
925 
927  if (handle_nan_inf()) return;
928 
929  if (ns == numeric_system::standard) return write(hour12(), 2);
930  auto time = tm();
931  time.tm_hour = to_nonnegative_int(hour12(), 12);
932  format_localized(time, 'I', 'O');
933  }
934 
936  if (handle_nan_inf()) return;
937 
938  if (ns == numeric_system::standard) return write(minute(), 2);
939  auto time = tm();
940  time.tm_min = to_nonnegative_int(minute(), 60);
941  format_localized(time, 'M', 'O');
942  }
943 
945  if (handle_nan_inf()) return;
946 
947  if (ns == numeric_system::standard) {
948  write(second(), 2);
949 #if FMT_SAFE_DURATION_CAST
950  // convert rep->Rep
951  using duration_rep = std::chrono::duration<rep, Period>;
952  using duration_Rep = std::chrono::duration<Rep, Period>;
953  auto tmpval = fmt_safe_duration_cast<duration_Rep>(duration_rep{val});
954 #else
955  auto tmpval = std::chrono::duration<Rep, Period>(val);
956 #endif
957  auto ms = get_milliseconds(tmpval);
958  if (ms != std::chrono::milliseconds(0)) {
959  *out++ = '.';
960  write(ms.count(), 3);
961  }
962  return;
963  }
964  auto time = tm();
965  time.tm_sec = to_nonnegative_int(second(), 60);
966  format_localized(time, 'S', 'O');
967  }
968 
970  if (handle_nan_inf()) return;
971  format_localized(time(), 'r');
972  }
973 
975  if (handle_nan_inf()) {
976  *out++ = ':';
977  handle_nan_inf();
978  return;
979  }
980 
981  write(hour(), 2);
982  *out++ = ':';
983  write(minute(), 2);
984  }
985 
986  void on_iso_time() {
987  on_24_hour_time();
988  *out++ = ':';
989  if (handle_nan_inf()) return;
990  write(second(), 2);
991  }
992 
993  void on_am_pm() {
994  if (handle_nan_inf()) return;
995  format_localized(time(), 'p');
996  }
997 
999  if (handle_nan_inf()) return;
1000  write_sign();
1001  out = format_duration_value<char_type>(out, val, precision);
1002  }
1003 
1005  out = format_duration_unit<char_type, Period>(out);
1006  }
1007 };
1008 } // namespace detail
1009 
1010 template <typename Rep, typename Period, typename Char>
1011 struct formatter<std::chrono::duration<Rep, Period>, Char> {
1012  private:
1019  using duration = std::chrono::duration<Rep, Period>;
1020 
1021  struct spec_handler {
1025 
1026  template <typename Id> FMT_CONSTEXPR arg_ref_type make_arg_ref(Id arg_id) {
1027  context.check_arg_id(arg_id);
1028  return arg_ref_type(arg_id);
1029  }
1030 
1032  context.check_arg_id(arg_id);
1033  return arg_ref_type(arg_id);
1034  }
1035 
1037  return arg_ref_type(context.next_arg_id());
1038  }
1039 
1040  void on_error(const char* msg) { FMT_THROW(format_error(msg)); }
1041  void on_fill(basic_string_view<Char> fill) { f.specs.fill = fill; }
1042  void on_align(align_t align) { f.specs.align = align; }
1043  void on_width(int width) { f.specs.width = width; }
1044  void on_precision(int _precision) { f.precision = _precision; }
1045  void end_precision() {}
1046 
1047  template <typename Id> void on_dynamic_width(Id arg_id) {
1048  f.width_ref = make_arg_ref(arg_id);
1049  }
1050 
1051  template <typename Id> void on_dynamic_precision(Id arg_id) {
1052  f.precision_ref = make_arg_ref(arg_id);
1053  }
1054  };
1055 
1057  struct parse_range {
1060  };
1061 
1063  auto begin = ctx.begin(), end = ctx.end();
1064  if (begin == end || *begin == '}') return {begin, begin};
1065  spec_handler handler{*this, ctx, format_str};
1066  begin = detail::parse_align(begin, end, handler);
1067  if (begin == end) return {begin, begin};
1068  begin = detail::parse_width(begin, end, handler);
1069  if (begin == end) return {begin, begin};
1070  if (*begin == '.') {
1072  begin = detail::parse_precision(begin, end, handler);
1073  else
1074  handler.on_error("precision not allowed for this argument type");
1075  }
1077  return {begin, end};
1078  }
1079 
1080  public:
1081  formatter() : precision(-1) {}
1082 
1084  -> decltype(ctx.begin()) {
1085  auto range = do_parse(ctx);
1086  format_str = basic_string_view<Char>(
1087  &*range.begin, detail::to_unsigned(range.end - range.begin));
1088  return range.end;
1089  }
1090 
1091  template <typename FormatContext>
1092  auto format(const duration& d, FormatContext& ctx) -> decltype(ctx.out()) {
1093  auto begin = format_str.begin(), end = format_str.end();
1094  // As a possible future optimization, we could avoid extra copying if width
1095  // is not specified.
1097  auto out = std::back_inserter(buf);
1098  detail::handle_dynamic_spec<detail::width_checker>(specs.width, width_ref,
1099  ctx);
1100  detail::handle_dynamic_spec<detail::precision_checker>(precision,
1101  precision_ref, ctx);
1102  if (begin == end || *begin == '}') {
1103  out = detail::format_duration_value<Char>(out, d.count(), precision);
1104  detail::format_duration_unit<Char, Period>(out);
1105  } else {
1107  ctx, out, d);
1108  f.precision = precision;
1109  parse_chrono_format(begin, end, f);
1110  }
1111  return detail::write(
1112  ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs);
1113  }
1114 };
1115 
1117 
1118 #endif // FMT_CHRONO_H_
void on_loc_time(numeric_system)
Definition: chrono.h:911
#define FMT_ENABLE_IF(...)
Definition: core.h:269
Definition: format.h:1173
FMT_CONSTEXPR To lossless_integral_conversion(const From from, int &ec)
Definition: chrono.h:39
enum MQTTPropertyCodes value
FMT_NORETURN void on_loc_date(numeric_system)
Definition: chrono.h:644
std::tm time() const
Definition: chrono.h:858
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:2351
Rep minute() const
Definition: chrono.h:855
#define FMT_NORETURN
Definition: core.h:149
FMT_NORETURN void on_tz_name()
Definition: chrono.h:655
FMT_CONSTEXPR const Char * parse_width(const Char *begin, const Char *end, Handler &&handler)
Definition: format.h:2790
FMT_INLINE std::basic_string< Char > format(const S &format_str, Args &&...args)
Definition: core.h:2081
size_t size() const
Definition: format.h:1129
FMT_NORETURN void on_abbr_month()
Definition: chrono.h:637
void reserve(size_t new_capacity)
Definition: format.h:730
void on_dec0_weekday(numeric_system)
Definition: chrono.h:905
const wchar_t * c_str() const
Definition: format.h:1130
Rep hour() const
Definition: chrono.h:848
typename std::conditional< B, T, F >::type conditional_t
Definition: core.h:253
To safe_duration_cast(std::chrono::duration< FromRep, FromPeriod > from, int &ec)
Definition: chrono.h:154
std::chrono::duration< rep > seconds
Definition: chrono.h:800
void on_minute(numeric_system ns)
Definition: chrono.h:935
MQTTClient d
Definition: test10.c:1656
constexpr T const_check(T value)
Definition: core.h:274
OutputIt format_duration_unit(OutputIt out)
Definition: chrono.h:780
constexpr iterator end() const FMT_NOEXCEPT
Definition: core.h:574
FMT_CONSTEXPR const Char * parse_align(const Char *begin, const Char *end, Handler &&handler)
Definition: format.h:2747
void on_text(const Char *, const Char *)
Definition: chrono.h:632
std::tm gmtime(std::time_t time)
Definition: chrono.h:334
void format_localized(const tm &time, char format, char modifier=0)
Definition: chrono.h:887
FMT_CONSTEXPR parse_range do_parse(basic_format_parse_context< Char > &ctx)
Definition: chrono.h:1062
size_t size() const FMT_NOEXCEPT
Definition: core.h:698
size_t strftime(char *str, size_t count, const char *format, const std::tm *time)
Definition: chrono.h:375
std::chrono::duration< rep, std::milli > milliseconds
Definition: chrono.h:802
Definition: json.hpp:4042
T * end() FMT_NOEXCEPT
Definition: core.h:692
void on_second(numeric_system)
Definition: chrono.h:642
OutputIt write(OutputIt out, basic_string_view< StrChar > s, const basic_format_specs< Char > &specs)
Definition: format.h:1568
std::tm localtime(std::time_t time)
Definition: chrono.h:292
std::integral_constant< bool, std::numeric_limits< T >::is_signed||std::is_same< T, int128_t >::value > is_signed
Definition: format.h:787
FMT_CONSTEXPR const Char * parse_precision(const Char *begin, const Char *end, Handler &&handler)
Definition: format.h:2807
void on_second(numeric_system ns)
Definition: chrono.h:944
FormatContext & context
Definition: chrono.h:792
void on_loc_date(numeric_system)
Definition: chrono.h:910
#define FMT_END_NAMESPACE
Definition: core.h:190
#define FMT_THROW(x)
Definition: format.h:113
basic_string_view< char > string_view
Definition: core.h:432
void on_datetime(numeric_system)
Definition: chrono.h:909
FMT_NORETURN void on_utc_offset()
Definition: chrono.h:654
FMT_CONSTEXPR std::make_unsigned< Int >::type to_unsigned(Int value)
Definition: core.h:317
T * begin() FMT_NOEXCEPT
Definition: core.h:691
constexpr size_t count()
Definition: core.h:960
size_t strftime(wchar_t *str, size_t count, const wchar_t *format, const std::tm *time)
Definition: chrono.h:380
FMT_NORETURN void on_full_weekday()
Definition: chrono.h:634
null gmtime_r(...)
Definition: chrono.h:287
numeric_system
Definition: chrono.h:465
auto format(std::chrono::time_point< std::chrono::system_clock > val, FormatContext &ctx) -> decltype(ctx.out())
Definition: chrono.h:390
void * align(std::size_t alignment, std::size_t size, void *&ptr, std::size_t &space, std::size_t &required_space)
Definition: sol.hpp:9768
T mod(T x, int y)
Definition: chrono.h:693
#define min(A, B)
Definition: Log.c:64
#define max(A, B)
Definition: Socket.h:88
Definition: chrono.h:284
#define FMT_NOMACRO
Definition: chrono.h:282
constexpr iterator begin() const FMT_NOEXCEPT
Definition: core.h:569
auto parse(ParseContext &ctx) -> decltype(ctx.begin())
Definition: chrono.h:399
void on_24_hour(numeric_system)
Definition: chrono.h:639
FMT_NORETURN void on_dec0_weekday(numeric_system)
Definition: chrono.h:635
void on_dec1_weekday(numeric_system)
Definition: chrono.h:906
FMT_NORETURN void report_no_date()
Definition: chrono.h:630
type
Definition: format.h:1174
null gmtime_s(...)
Definition: chrono.h:288
Rep second() const
Definition: chrono.h:856
void on_12_hour(numeric_system ns)
Definition: chrono.h:926
FMT_CONSTEXPR int next_arg_id()
Definition: core.h:585
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:813
j template void())
Definition: json.hpp:3707
char upper
Definition: utf-8.c:50
FMT_NORETURN void on_abbr_weekday()
Definition: chrono.h:633
void write(Rep value, int width)
Definition: chrono.h:873
FMT_NORETURN void on_us_date()
Definition: chrono.h:646
void on_text(const char_type *begin, const char_type *end)
Definition: chrono.h:898
FMT_NORETURN void on_dec1_weekday(numeric_system)
Definition: chrono.h:636
OutputIt format_to(OutputIt out, const S &format_str, Args &&...args)
Definition: core.h:2009
def run()
Definition: mqttsas.py:276
FMT_CONSTEXPR To safe_float_conversion(const From from, int &ec)
Definition: chrono.h:120
FMT_NORETURN void on_full_month()
Definition: chrono.h:638
FMT_CONSTEXPR arg_ref_type make_arg_ref(basic_string_view< Char > arg_id)
Definition: chrono.h:1031
FMT_NORETURN void on_loc_time(numeric_system)
Definition: chrono.h:645
MQTTClient c
Definition: test10.c:1656
#define FMT_CONSTEXPR
Definition: core.h:98
float time
Definition: mqtt_test.py:17
const void * ptr(const T *p)
Definition: format.h:3610
constexpr iterator end() const
Definition: core.h:394
null localtime_s(...)
Definition: chrono.h:286
void on_12_hour(numeric_system)
Definition: chrono.h:640
FMT_CONSTEXPR auto parse(basic_format_parse_context< Char > &ctx) -> decltype(ctx.begin())
Definition: chrono.h:1083
constexpr iterator begin() const
Definition: core.h:393
To fmt_safe_duration_cast(std::chrono::duration< FromRep, FromPeriod > from)
Definition: chrono.h:715
basic_memory_buffer< Char > tm_format
Definition: chrono.h:434
void resize(size_t count)
Definition: format.h:727
FMT_NORETURN void on_datetime(numeric_system)
Definition: chrono.h:643
typename std::make_unsigned< T >::type type
Definition: chrono.h:709
FMT_CONSTEXPR const Char * parse_chrono_format(const Char *begin, const Char *end, Handler &&handler)
Definition: chrono.h:473
std::chrono::duration< Rep, Period > duration
Definition: chrono.h:1019
#define FMT_ASSERT(condition, message)
Definition: core.h:284
std::chrono::duration< Rep, std::milli > get_milliseconds(std::chrono::duration< Rep, Period > d)
Definition: chrono.h:725
chrono_formatter(FormatContext &ctx, OutputIt o, std::chrono::duration< Rep, Period > d)
Definition: chrono.h:807
#define FMT_BEGIN_NAMESPACE
Definition: core.h:195
FMT_CONSTEXPR const char * get_units()
Definition: chrono.h:438
FMT_NORETURN void on_iso_date()
Definition: chrono.h:647
FMT_CONSTEXPR void check_arg_id(int)
Definition: core.h:597
Rep hour12() const
Definition: chrono.h:850
auto format(const duration &d, FormatContext &ctx) -> decltype(ctx.out())
Definition: chrono.h:1092
conditional_t< std::is_integral< Rep >::value &&sizeof(Rep)< sizeof(int), unsigned, typename make_unsigned_or_unchanged< Rep >::type > rep
Definition: chrono.h:798
typename basic_format_parse_context< Char >::iterator iterator
Definition: chrono.h:1056
bool isfinite(T)
Definition: chrono.h:668
int to_nonnegative_int(T value, int upper)
Definition: chrono.h:678
typename FormatContext::char_type char_type
Definition: chrono.h:805
FMT_CONSTEXPR bool is_negative(T value)
Definition: format.h:792
void on_minute(numeric_system)
Definition: chrono.h:641
auto format(const std::tm &tm, FormatContext &ctx) -> decltype(ctx.out())
Definition: chrono.h:411
bool isnan(T)
Definition: chrono.h:659
T * data() FMT_NOEXCEPT
Definition: core.h:704
OutputIt format_duration_value(OutputIt out, Rep val, int precision)
Definition: chrono.h:758
FMT_CONSTEXPR arg_ref_type make_arg_ref(detail::auto_id)
Definition: chrono.h:1036
int count_digits(uint64_t n)
Definition: format.h:924
void on_24_hour(numeric_system ns)
Definition: chrono.h:917
size_t capacity() const FMT_NOEXCEPT
Definition: core.h:701
FMT_NOINLINE OutputIt fill(OutputIt it, size_t n, const fill_t< Char > &fill)
Definition: format.h:1483
OutputIt copy_unit(string_view unit, OutputIt out, wchar_t)
Definition: chrono.h:772


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:47:33