WPILibC++ 2023.4.3-108-ge5452e3
chrono.h
Go to the documentation of this file.
1// Formatting library for C++ - chrono support
2//
3// Copyright (c) 2012 - present, Victor Zverovich
4// All rights reserved.
5//
6// For the license information refer to format.h.
7
8#ifndef FMT_CHRONO_H_
9#define FMT_CHRONO_H_
10
11#include <algorithm>
12#include <chrono>
13#include <cmath> // std::isfinite
14#include <cstring> // std::memcpy
15#include <ctime>
16#include <iterator>
17#include <locale>
18#include <ostream>
19#include <type_traits>
20
21#include "format.h"
22
24
25// Enable tzset.
26#ifndef FMT_USE_TZSET
27// UWP doesn't provide _tzset.
28# if FMT_HAS_INCLUDE("winapifamily.h")
29# include <winapifamily.h>
30# endif
31# if defined(_WIN32) && (!defined(WINAPI_FAMILY) || \
32 (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
33# define FMT_USE_TZSET 1
34# else
35# define FMT_USE_TZSET 0
36# endif
37#endif
38
39// Enable safe chrono durations, unless explicitly disabled.
40#ifndef FMT_SAFE_DURATION_CAST
41# define FMT_SAFE_DURATION_CAST 1
42#endif
43#if FMT_SAFE_DURATION_CAST
44
45// For conversion between std::chrono::durations without undefined
46// behaviour or erroneous results.
47// This is a stripped down version of duration_cast, for inclusion in fmt.
48// See https://github.com/pauldreik/safe_duration_cast
49//
50// Copyright Paul Dreik 2019
52
53template <typename To, typename From,
54 FMT_ENABLE_IF(!std::is_same<From, To>::value &&
58 ec = 0;
59 using F = std::numeric_limits<From>;
60 using T = std::numeric_limits<To>;
61 static_assert(F::is_integer, "From must be integral");
62 static_assert(T::is_integer, "To must be integral");
63
64 // A and B are both signed, or both unsigned.
65 if (detail::const_check(F::digits <= T::digits)) {
66 // From fits in To without any problem.
67 } else {
68 // From does not always fit in To, resort to a dynamic check.
69 if (from < (T::min)() || from > (T::max)()) {
70 // outside range.
71 ec = 1;
72 return {};
73 }
74 }
75 return static_cast<To>(from);
76}
77
78/**
79 * converts From to To, without loss. If the dynamic value of from
80 * can't be converted to To without loss, ec is set.
81 */
82template <typename To, typename From,
83 FMT_ENABLE_IF(!std::is_same<From, To>::value &&
86FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {
87 ec = 0;
88 using F = std::numeric_limits<From>;
89 using T = std::numeric_limits<To>;
90 static_assert(F::is_integer, "From must be integral");
91 static_assert(T::is_integer, "To must be integral");
92
94 // From may be negative, not allowed!
96 ec = 1;
97 return {};
98 }
99 // From is positive. Can it always fit in To?
100 if (detail::const_check(F::digits > T::digits) &&
101 from > static_cast<From>(detail::max_value<To>())) {
102 ec = 1;
103 return {};
104 }
105 }
106
108 F::digits >= T::digits) &&
109 from > static_cast<From>(detail::max_value<To>())) {
110 ec = 1;
111 return {};
112 }
113 return static_cast<To>(from); // Lossless conversion.
114}
115
116template <typename To, typename From,
117 FMT_ENABLE_IF(std::is_same<From, To>::value)>
118FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) {
119 ec = 0;
120 return from;
121} // function
122
123// clang-format off
124/**
125 * converts From to To if possible, otherwise ec is set.
126 *
127 * input | output
128 * ---------------------------------|---------------
129 * NaN | NaN
130 * Inf | Inf
131 * normal, fits in output | converted (possibly lossy)
132 * normal, does not fit in output | ec is set
133 * subnormal | best effort
134 * -Inf | -Inf
135 */
136// clang-format on
137template <typename To, typename From,
138 FMT_ENABLE_IF(!std::is_same<From, To>::value)>
139FMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) {
140 ec = 0;
141 using T = std::numeric_limits<To>;
142 static_assert(std::is_floating_point<From>::value, "From must be floating");
143 static_assert(std::is_floating_point<To>::value, "To must be floating");
144
145 // catch the only happy case
146 if (std::isfinite(from)) {
147 if (from >= T::lowest() && from <= (T::max)()) {
148 return static_cast<To>(from);
149 }
150 // not within range.
151 ec = 1;
152 return {};
153 }
154
155 // nan and inf will be preserved
156 return static_cast<To>(from);
157} // function
158
159template <typename To, typename From,
160 FMT_ENABLE_IF(std::is_same<From, To>::value)>
161FMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) {
162 ec = 0;
163 static_assert(std::is_floating_point<From>::value, "From must be floating");
164 return from;
165}
166
167/**
168 * safe duration cast between integral durations
169 */
170template <typename To, typename FromRep, typename FromPeriod,
171 FMT_ENABLE_IF(std::is_integral<FromRep>::value),
172 FMT_ENABLE_IF(std::is_integral<typename To::rep>::value)>
173To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
174 int& ec) {
175 using From = std::chrono::duration<FromRep, FromPeriod>;
176 ec = 0;
177 // the basic idea is that we need to convert from count() in the from type
178 // to count() in the To type, by multiplying it with this:
179 struct Factor
180 : std::ratio_divide<typename From::period, typename To::period> {};
181
182 static_assert(Factor::num > 0, "num must be positive");
183 static_assert(Factor::den > 0, "den must be positive");
184
185 // the conversion is like this: multiply from.count() with Factor::num
186 // /Factor::den and convert it to To::rep, all this without
187 // overflow/underflow. let's start by finding a suitable type that can hold
188 // both To, From and Factor::num
189 using IntermediateRep =
190 typename std::common_type<typename From::rep, typename To::rep,
191 decltype(Factor::num)>::type;
192
193 // safe conversion to IntermediateRep
194 IntermediateRep count =
195 lossless_integral_conversion<IntermediateRep>(from.count(), ec);
196 if (ec) return {};
197 // multiply with Factor::num without overflow or underflow
198 if (detail::const_check(Factor::num != 1)) {
199 const auto max1 = detail::max_value<IntermediateRep>() / Factor::num;
200 if (count > max1) {
201 ec = 1;
202 return {};
203 }
204 const auto min1 =
206 if (!std::is_unsigned<IntermediateRep>::value && count < min1) {
207 ec = 1;
208 return {};
209 }
210 count *= Factor::num;
211 }
212
213 if (detail::const_check(Factor::den != 1)) count /= Factor::den;
214 auto tocount = lossless_integral_conversion<typename To::rep>(count, ec);
215 return ec ? To() : To(tocount);
216}
217
218/**
219 * safe duration_cast between floating point durations
220 */
221template <typename To, typename FromRep, typename FromPeriod,
222 FMT_ENABLE_IF(std::is_floating_point<FromRep>::value),
223 FMT_ENABLE_IF(std::is_floating_point<typename To::rep>::value)>
224To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from,
225 int& ec) {
226 using From = std::chrono::duration<FromRep, FromPeriod>;
227 ec = 0;
228 if (std::isnan(from.count())) {
229 // nan in, gives nan out. easy.
230 return To{std::numeric_limits<typename To::rep>::quiet_NaN()};
231 }
232 // maybe we should also check if from is denormal, and decide what to do about
233 // it.
234
235 // +-inf should be preserved.
236 if (std::isinf(from.count())) {
237 return To{from.count()};
238 }
239
240 // the basic idea is that we need to convert from count() in the from type
241 // to count() in the To type, by multiplying it with this:
242 struct Factor
243 : std::ratio_divide<typename From::period, typename To::period> {};
244
245 static_assert(Factor::num > 0, "num must be positive");
246 static_assert(Factor::den > 0, "den must be positive");
247
248 // the conversion is like this: multiply from.count() with Factor::num
249 // /Factor::den and convert it to To::rep, all this without
250 // overflow/underflow. let's start by finding a suitable type that can hold
251 // both To, From and Factor::num
252 using IntermediateRep =
253 typename std::common_type<typename From::rep, typename To::rep,
254 decltype(Factor::num)>::type;
255
256 // force conversion of From::rep -> IntermediateRep to be safe,
257 // even if it will never happen be narrowing in this context.
258 IntermediateRep count =
259 safe_float_conversion<IntermediateRep>(from.count(), ec);
260 if (ec) {
261 return {};
262 }
263
264 // multiply with Factor::num without overflow or underflow
265 if (detail::const_check(Factor::num != 1)) {
266 constexpr auto max1 = detail::max_value<IntermediateRep>() /
267 static_cast<IntermediateRep>(Factor::num);
268 if (count > max1) {
269 ec = 1;
270 return {};
271 }
272 constexpr auto min1 = std::numeric_limits<IntermediateRep>::lowest() /
273 static_cast<IntermediateRep>(Factor::num);
274 if (count < min1) {
275 ec = 1;
276 return {};
277 }
278 count *= static_cast<IntermediateRep>(Factor::num);
279 }
280
281 // this can't go wrong, right? den>0 is checked earlier.
282 if (detail::const_check(Factor::den != 1)) {
284 count /= static_cast<common_t>(Factor::den);
285 }
286
287 // convert to the to type, safely
288 using ToRep = typename To::rep;
289
290 const ToRep tocount = safe_float_conversion<ToRep>(count, ec);
291 if (ec) {
292 return {};
293 }
294 return To{tocount};
295}
296} // namespace safe_duration_cast
297#endif
298
299// Prevents expansion of a preceding token as a function-style macro.
300// Usage: f FMT_NOMACRO()
301#define FMT_NOMACRO
302
303namespace detail {
304template <typename T = void> struct null {};
305inline null<> localtime_r FMT_NOMACRO(...) { return null<>(); }
306inline null<> localtime_s(...) { return null<>(); }
307inline null<> gmtime_r(...) { return null<>(); }
308inline null<> gmtime_s(...) { return null<>(); }
309
310inline const std::locale& get_classic_locale() {
311 static const auto& locale = std::locale::classic();
312 return locale;
313}
314
315template <typename CodeUnit> struct codecvt_result {
316 static constexpr const size_t max_size = 32;
317 CodeUnit buf[max_size];
318 CodeUnit* end;
319};
320template <typename CodeUnit>
321constexpr const size_t codecvt_result<CodeUnit>::max_size;
322
323template <typename CodeUnit>
325 const std::locale& loc) {
326#if FMT_CLANG_VERSION
327# pragma clang diagnostic push
328# pragma clang diagnostic ignored "-Wdeprecated"
329 auto& f = std::use_facet<std::codecvt<CodeUnit, char, std::mbstate_t>>(loc);
330# pragma clang diagnostic pop
331#else
332 auto& f = std::use_facet<std::codecvt<CodeUnit, char, std::mbstate_t>>(loc);
333#endif
334 auto mb = std::mbstate_t();
335 const char* from_next = nullptr;
336 auto result = f.in(mb, in_buf.begin(), in_buf.end(), from_next,
337 std::begin(out.buf), std::end(out.buf), out.end);
338 if (result != std::codecvt_base::ok)
339 FMT_THROW(format_error("failed to format time"));
340}
341
342template <typename OutputIt>
343auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale& loc)
344 -> OutputIt {
345 if (detail::is_utf8() && loc != get_classic_locale()) {
346 // char16_t and char32_t codecvts are broken in MSVC (linkage errors) and
347 // gcc-4.
348#if FMT_MSC_VERSION != 0 || \
349 (defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI))
350 // The _GLIBCXX_USE_DUAL_ABI macro is always defined in libstdc++ from gcc-5
351 // and newer.
352 using code_unit = wchar_t;
353#else
354 using code_unit = char32_t;
355#endif
356
357 using unit_t = codecvt_result<code_unit>;
358 unit_t unit;
359 write_codecvt(unit, in, loc);
360 // In UTF-8 is used one to four one-byte code units.
362 for (code_unit* p = unit.buf; p != unit.end; ++p) {
363 uint32_t c = static_cast<uint32_t>(*p);
364 if (sizeof(code_unit) == 2 && c >= 0xd800 && c <= 0xdfff) {
365 // surrogate pair
366 ++p;
367 if (p == unit.end || (c & 0xfc00) != 0xd800 ||
368 (*p & 0xfc00) != 0xdc00) {
369 FMT_THROW(format_error("failed to format time"));
370 }
371 c = (c << 10) + static_cast<uint32_t>(*p) - 0x35fdc00;
372 }
373 if (c < 0x80) {
374 buf.push_back(static_cast<char>(c));
375 } else if (c < 0x800) {
376 buf.push_back(static_cast<char>(0xc0 | (c >> 6)));
377 buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));
378 } else if ((c >= 0x800 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xffff)) {
379 buf.push_back(static_cast<char>(0xe0 | (c >> 12)));
380 buf.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6)));
381 buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));
382 } else if (c >= 0x10000 && c <= 0x10ffff) {
383 buf.push_back(static_cast<char>(0xf0 | (c >> 18)));
384 buf.push_back(static_cast<char>(0x80 | ((c & 0x3ffff) >> 12)));
385 buf.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6)));
386 buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));
387 } else {
388 FMT_THROW(format_error("failed to format time"));
389 }
390 }
391 return copy_str<char>(buf.data(), buf.data() + buf.size(), out);
392 }
393 return copy_str<char>(in.data(), in.data() + in.size(), out);
394}
395
396template <typename Char, typename OutputIt,
397 FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
398auto write_tm_str(OutputIt out, string_view sv, const std::locale& loc)
399 -> OutputIt {
401 write_codecvt(unit, sv, loc);
402 return copy_str<Char>(unit.buf, unit.end, out);
403}
404
405template <typename Char, typename OutputIt,
406 FMT_ENABLE_IF(std::is_same<Char, char>::value)>
407auto write_tm_str(OutputIt out, string_view sv, const std::locale& loc)
408 -> OutputIt {
409 return write_encoded_tm_str(out, sv, loc);
410}
411
412template <typename Char>
413inline void do_write(buffer<Char>& buf, const std::tm& time,
414 const std::locale& loc, char format, char modifier) {
415 auto&& format_buf = formatbuf<std::basic_streambuf<Char>>(buf);
416 auto&& os = std::basic_ostream<Char>(&format_buf);
417 os.imbue(loc);
418 using iterator = std::ostreambuf_iterator<Char>;
419 const auto& facet = std::use_facet<std::time_put<Char, iterator>>(loc);
420 auto end = facet.put(os, os, Char(' '), &time, format, modifier);
421 if (end.failed()) FMT_THROW(format_error("failed to format time"));
422}
423
424template <typename Char, typename OutputIt,
425 FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
426auto write(OutputIt out, const std::tm& time, const std::locale& loc,
427 char format, char modifier = 0) -> OutputIt {
428 auto&& buf = get_buffer<Char>(out);
429 do_write<Char>(buf, time, loc, format, modifier);
430 return buf.out();
431}
432
433template <typename Char, typename OutputIt,
434 FMT_ENABLE_IF(std::is_same<Char, char>::value)>
435auto write(OutputIt out, const std::tm& time, const std::locale& loc,
436 char format, char modifier = 0) -> OutputIt {
437 auto&& buf = basic_memory_buffer<Char>();
438 do_write<char>(buf, time, loc, format, modifier);
439 return write_encoded_tm_str(out, string_view(buf.data(), buf.size()), loc);
440}
441
442} // namespace detail
443
445
446/**
447 Converts given time since epoch as ``std::time_t`` value into calendar time,
448 expressed in local time. Unlike ``std::localtime``, this function is
449 thread-safe on most platforms.
450 */
451inline std::tm localtime(std::time_t time) {
452 struct dispatcher {
453 std::time_t time_;
454 std::tm tm_;
455
456 dispatcher(std::time_t t) : time_(t) {}
457
458 bool run() {
459 using namespace fmt::detail;
460 return handle(localtime_r(&time_, &tm_));
461 }
462
463 bool handle(std::tm* tm) { return tm != nullptr; }
464
465 bool handle(detail::null<>) {
466 using namespace fmt::detail;
467 return fallback(localtime_s(&tm_, &time_));
468 }
469
470 bool fallback(int res) { return res == 0; }
471
472#if !FMT_MSC_VERSION
473 bool fallback(detail::null<>) {
474 using namespace fmt::detail;
475 std::tm* tm = std::localtime(&time_);
476 if (tm) tm_ = *tm;
477 return tm != nullptr;
478 }
479#endif
480 };
481 dispatcher lt(time);
482 // Too big time values may be unsupported.
483 if (!lt.run()) FMT_THROW(format_error("time_t value out of range"));
484 return lt.tm_;
485}
486
487inline std::tm localtime(
488 std::chrono::time_point<std::chrono::system_clock> time_point) {
489 return localtime(std::chrono::system_clock::to_time_t(time_point));
490}
491
492/**
493 Converts given time since epoch as ``std::time_t`` value into calendar time,
494 expressed in Coordinated Universal Time (UTC). Unlike ``std::gmtime``, this
495 function is thread-safe on most platforms.
496 */
497inline std::tm gmtime(std::time_t time) {
498 struct dispatcher {
499 std::time_t time_;
500 std::tm tm_;
501
502 dispatcher(std::time_t t) : time_(t) {}
503
504 bool run() {
505 using namespace fmt::detail;
506 return handle(gmtime_r(&time_, &tm_));
507 }
508
509 bool handle(std::tm* tm) { return tm != nullptr; }
510
511 bool handle(detail::null<>) {
512 using namespace fmt::detail;
513 return fallback(gmtime_s(&tm_, &time_));
514 }
515
516 bool fallback(int res) { return res == 0; }
517
518#if !FMT_MSC_VERSION
519 bool fallback(detail::null<>) {
520 std::tm* tm = std::gmtime(&time_);
521 if (tm) tm_ = *tm;
522 return tm != nullptr;
523 }
524#endif
525 };
526 dispatcher gt(time);
527 // Too big time values may be unsupported.
528 if (!gt.run()) FMT_THROW(format_error("time_t value out of range"));
529 return gt.tm_;
530}
531
532inline std::tm gmtime(
533 std::chrono::time_point<std::chrono::system_clock> time_point) {
534 return gmtime(std::chrono::system_clock::to_time_t(time_point));
535}
536
538
539// Writes two-digit numbers a, b and c separated by sep to buf.
540// The method by Pavel Novikov based on
541// https://johnnylee-sde.github.io/Fast-unsigned-integer-to-time-string/.
542inline void write_digit2_separated(char* buf, unsigned a, unsigned b,
543 unsigned c, char sep) {
544 unsigned long long digits =
545 a | (b << 24) | (static_cast<unsigned long long>(c) << 48);
546 // Convert each value to BCD.
547 // We have x = a * 10 + b and we want to convert it to BCD y = a * 16 + b.
548 // The difference is
549 // y - x = a * 6
550 // a can be found from x:
551 // a = floor(x / 10)
552 // then
553 // y = x + a * 6 = x + floor(x / 10) * 6
554 // floor(x / 10) is (x * 205) >> 11 (needs 16 bits).
555 digits += (((digits * 205) >> 11) & 0x000f00000f00000f) * 6;
556 // Put low nibbles to high bytes and high nibbles to low bytes.
557 digits = ((digits & 0x00f00000f00000f0) >> 4) |
558 ((digits & 0x000f00000f00000f) << 8);
559 auto usep = static_cast<unsigned long long>(sep);
560 // Add ASCII '0' to each digit byte and insert separators.
561 digits |= 0x3030003030003030 | (usep << 16) | (usep << 40);
562
563 constexpr const size_t len = 8;
564 if (const_check(is_big_endian())) {
565 char tmp[len];
566 std::memcpy(tmp, &digits, len);
567 std::reverse_copy(tmp, tmp + len, buf);
568 } else {
569 std::memcpy(buf, &digits, len);
570 }
571}
572
573template <typename Period> FMT_CONSTEXPR inline const char* get_units() {
574 if (std::is_same<Period, std::atto>::value) return "as";
575 if (std::is_same<Period, std::femto>::value) return "fs";
576 if (std::is_same<Period, std::pico>::value) return "ps";
577 if (std::is_same<Period, std::nano>::value) return "ns";
578 if (std::is_same<Period, std::micro>::value) return "µs";
579 if (std::is_same<Period, std::milli>::value) return "ms";
580 if (std::is_same<Period, std::centi>::value) return "cs";
581 if (std::is_same<Period, std::deci>::value) return "ds";
582 if (std::is_same<Period, std::ratio<1>>::value) return "s";
583 if (std::is_same<Period, std::deca>::value) return "das";
584 if (std::is_same<Period, std::hecto>::value) return "hs";
585 if (std::is_same<Period, std::kilo>::value) return "ks";
586 if (std::is_same<Period, std::mega>::value) return "Ms";
587 if (std::is_same<Period, std::giga>::value) return "Gs";
588 if (std::is_same<Period, std::tera>::value) return "Ts";
589 if (std::is_same<Period, std::peta>::value) return "Ps";
590 if (std::is_same<Period, std::exa>::value) return "Es";
591 if (std::is_same<Period, std::ratio<60>>::value) return "m";
592 if (std::is_same<Period, std::ratio<3600>>::value) return "h";
593 return nullptr;
594}
595
596enum class numeric_system {
597 standard,
598 // Alternative numeric system, e.g. 十二 instead of 12 in ja_JP locale.
600};
601
602// Parses a put_time-like format string and invokes handler actions.
603template <typename Char, typename Handler>
604FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin,
605 const Char* end,
606 Handler&& handler) {
607 auto ptr = begin;
608 while (ptr != end) {
609 auto c = *ptr;
610 if (c == '}') break;
611 if (c != '%') {
612 ++ptr;
613 continue;
614 }
615 if (begin != ptr) handler.on_text(begin, ptr);
616 ++ptr; // consume '%'
617 if (ptr == end) FMT_THROW(format_error("invalid format"));
618 c = *ptr++;
619 switch (c) {
620 case '%':
621 handler.on_text(ptr - 1, ptr);
622 break;
623 case 'n': {
624 const Char newline[] = {'\n'};
625 handler.on_text(newline, newline + 1);
626 break;
627 }
628 case 't': {
629 const Char tab[] = {'\t'};
630 handler.on_text(tab, tab + 1);
631 break;
632 }
633 // Year:
634 case 'Y':
635 handler.on_year(numeric_system::standard);
636 break;
637 case 'y':
638 handler.on_short_year(numeric_system::standard);
639 break;
640 case 'C':
641 handler.on_century(numeric_system::standard);
642 break;
643 case 'G':
644 handler.on_iso_week_based_year();
645 break;
646 case 'g':
647 handler.on_iso_week_based_short_year();
648 break;
649 // Day of the week:
650 case 'a':
651 handler.on_abbr_weekday();
652 break;
653 case 'A':
654 handler.on_full_weekday();
655 break;
656 case 'w':
657 handler.on_dec0_weekday(numeric_system::standard);
658 break;
659 case 'u':
660 handler.on_dec1_weekday(numeric_system::standard);
661 break;
662 // Month:
663 case 'b':
664 case 'h':
665 handler.on_abbr_month();
666 break;
667 case 'B':
668 handler.on_full_month();
669 break;
670 case 'm':
671 handler.on_dec_month(numeric_system::standard);
672 break;
673 // Day of the year/month:
674 case 'U':
675 handler.on_dec0_week_of_year(numeric_system::standard);
676 break;
677 case 'W':
678 handler.on_dec1_week_of_year(numeric_system::standard);
679 break;
680 case 'V':
681 handler.on_iso_week_of_year(numeric_system::standard);
682 break;
683 case 'j':
684 handler.on_day_of_year();
685 break;
686 case 'd':
687 handler.on_day_of_month(numeric_system::standard);
688 break;
689 case 'e':
690 handler.on_day_of_month_space(numeric_system::standard);
691 break;
692 // Hour, minute, second:
693 case 'H':
694 handler.on_24_hour(numeric_system::standard);
695 break;
696 case 'I':
697 handler.on_12_hour(numeric_system::standard);
698 break;
699 case 'M':
700 handler.on_minute(numeric_system::standard);
701 break;
702 case 'S':
703 handler.on_second(numeric_system::standard);
704 break;
705 // Other:
706 case 'c':
707 handler.on_datetime(numeric_system::standard);
708 break;
709 case 'x':
710 handler.on_loc_date(numeric_system::standard);
711 break;
712 case 'X':
713 handler.on_loc_time(numeric_system::standard);
714 break;
715 case 'D':
716 handler.on_us_date();
717 break;
718 case 'F':
719 handler.on_iso_date();
720 break;
721 case 'r':
722 handler.on_12_hour_time();
723 break;
724 case 'R':
725 handler.on_24_hour_time();
726 break;
727 case 'T':
728 handler.on_iso_time();
729 break;
730 case 'p':
731 handler.on_am_pm();
732 break;
733 case 'Q':
734 handler.on_duration_value();
735 break;
736 case 'q':
737 handler.on_duration_unit();
738 break;
739 case 'z':
740 handler.on_utc_offset();
741 break;
742 case 'Z':
743 handler.on_tz_name();
744 break;
745 // Alternative representation:
746 case 'E': {
747 if (ptr == end) FMT_THROW(format_error("invalid format"));
748 c = *ptr++;
749 switch (c) {
750 case 'Y':
751 handler.on_year(numeric_system::alternative);
752 break;
753 case 'y':
754 handler.on_offset_year();
755 break;
756 case 'C':
757 handler.on_century(numeric_system::alternative);
758 break;
759 case 'c':
760 handler.on_datetime(numeric_system::alternative);
761 break;
762 case 'x':
763 handler.on_loc_date(numeric_system::alternative);
764 break;
765 case 'X':
766 handler.on_loc_time(numeric_system::alternative);
767 break;
768 default:
769 FMT_THROW(format_error("invalid format"));
770 }
771 break;
772 }
773 case 'O':
774 if (ptr == end) FMT_THROW(format_error("invalid format"));
775 c = *ptr++;
776 switch (c) {
777 case 'y':
778 handler.on_short_year(numeric_system::alternative);
779 break;
780 case 'm':
781 handler.on_dec_month(numeric_system::alternative);
782 break;
783 case 'U':
784 handler.on_dec0_week_of_year(numeric_system::alternative);
785 break;
786 case 'W':
787 handler.on_dec1_week_of_year(numeric_system::alternative);
788 break;
789 case 'V':
790 handler.on_iso_week_of_year(numeric_system::alternative);
791 break;
792 case 'd':
793 handler.on_day_of_month(numeric_system::alternative);
794 break;
795 case 'e':
796 handler.on_day_of_month_space(numeric_system::alternative);
797 break;
798 case 'w':
799 handler.on_dec0_weekday(numeric_system::alternative);
800 break;
801 case 'u':
802 handler.on_dec1_weekday(numeric_system::alternative);
803 break;
804 case 'H':
805 handler.on_24_hour(numeric_system::alternative);
806 break;
807 case 'I':
808 handler.on_12_hour(numeric_system::alternative);
809 break;
810 case 'M':
811 handler.on_minute(numeric_system::alternative);
812 break;
813 case 'S':
814 handler.on_second(numeric_system::alternative);
815 break;
816 default:
817 FMT_THROW(format_error("invalid format"));
818 }
819 break;
820 default:
821 FMT_THROW(format_error("invalid format"));
822 }
823 begin = ptr;
824 }
825 if (begin != ptr) handler.on_text(begin, ptr);
826 return ptr;
827}
828
829template <typename Derived> struct null_chrono_spec_handler {
831 static_cast<Derived*>(this)->unsupported();
832 }
869};
870
871struct tm_format_checker : null_chrono_spec_handler<tm_format_checker> {
873
874 template <typename Char>
875 FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
910};
911
912inline const char* tm_wday_full_name(int wday) {
913 static constexpr const char* full_name_list[] = {
914 "Sunday", "Monday", "Tuesday", "Wednesday",
915 "Thursday", "Friday", "Saturday"};
916 return wday >= 0 && wday <= 6 ? full_name_list[wday] : "?";
917}
918inline const char* tm_wday_short_name(int wday) {
919 static constexpr const char* short_name_list[] = {"Sun", "Mon", "Tue", "Wed",
920 "Thu", "Fri", "Sat"};
921 return wday >= 0 && wday <= 6 ? short_name_list[wday] : "???";
922}
923
924inline const char* tm_mon_full_name(int mon) {
925 static constexpr const char* full_name_list[] = {
926 "January", "February", "March", "April", "May", "June",
927 "July", "August", "September", "October", "November", "December"};
928 return mon >= 0 && mon <= 11 ? full_name_list[mon] : "?";
929}
930inline const char* tm_mon_short_name(int mon) {
931 static constexpr const char* short_name_list[] = {
932 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
933 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
934 };
935 return mon >= 0 && mon <= 11 ? short_name_list[mon] : "???";
936}
937
938template <typename T, typename = void>
939struct has_member_data_tm_gmtoff : std::false_type {};
940template <typename T>
941struct has_member_data_tm_gmtoff<T, void_t<decltype(T::tm_gmtoff)>>
942 : std::true_type {};
943
944template <typename T, typename = void>
945struct has_member_data_tm_zone : std::false_type {};
946template <typename T>
947struct has_member_data_tm_zone<T, void_t<decltype(T::tm_zone)>>
948 : std::true_type {};
949
950#if FMT_USE_TZSET
951inline void tzset_once() {
952 static bool init = []() -> bool {
953 _tzset();
954 return true;
955 }();
956 ignore_unused(init);
957}
958#endif
959
960template <typename OutputIt, typename Char> class tm_writer {
961 private:
962 static constexpr int days_per_week = 7;
963
964 const std::locale& loc_;
965 const bool is_classic_;
966 OutputIt out_;
967 const std::tm& tm_;
968
969 auto tm_sec() const noexcept -> int {
970 FMT_ASSERT(tm_.tm_sec >= 0 && tm_.tm_sec <= 61, "");
971 return tm_.tm_sec;
972 }
973 auto tm_min() const noexcept -> int {
974 FMT_ASSERT(tm_.tm_min >= 0 && tm_.tm_min <= 59, "");
975 return tm_.tm_min;
976 }
977 auto tm_hour() const noexcept -> int {
978 FMT_ASSERT(tm_.tm_hour >= 0 && tm_.tm_hour <= 23, "");
979 return tm_.tm_hour;
980 }
981 auto tm_mday() const noexcept -> int {
982 FMT_ASSERT(tm_.tm_mday >= 1 && tm_.tm_mday <= 31, "");
983 return tm_.tm_mday;
984 }
985 auto tm_mon() const noexcept -> int {
986 FMT_ASSERT(tm_.tm_mon >= 0 && tm_.tm_mon <= 11, "");
987 return tm_.tm_mon;
988 }
989 auto tm_year() const noexcept -> long long { return 1900ll + tm_.tm_year; }
990 auto tm_wday() const noexcept -> int {
991 FMT_ASSERT(tm_.tm_wday >= 0 && tm_.tm_wday <= 6, "");
992 return tm_.tm_wday;
993 }
994 auto tm_yday() const noexcept -> int {
995 FMT_ASSERT(tm_.tm_yday >= 0 && tm_.tm_yday <= 365, "");
996 return tm_.tm_yday;
997 }
998
999 auto tm_hour12() const noexcept -> int {
1000 const auto h = tm_hour();
1001 const auto z = h < 12 ? h : h - 12;
1002 return z == 0 ? 12 : z;
1003 }
1004
1005 // POSIX and the C Standard are unclear or inconsistent about what %C and %y
1006 // do if the year is negative or exceeds 9999. Use the convention that %C
1007 // concatenated with %y yields the same output as %Y, and that %Y contains at
1008 // least 4 characters, with more only if necessary.
1009 auto split_year_lower(long long year) const noexcept -> int {
1010 auto l = year % 100;
1011 if (l < 0) l = -l; // l in [0, 99]
1012 return static_cast<int>(l);
1013 }
1014
1015 // Algorithm:
1016 // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_the_week_number_from_a_month_and_day_of_the_month_or_ordinal_date
1017 auto iso_year_weeks(long long curr_year) const noexcept -> int {
1018 const auto prev_year = curr_year - 1;
1019 const auto curr_p =
1020 (curr_year + curr_year / 4 - curr_year / 100 + curr_year / 400) %
1021 days_per_week;
1022 const auto prev_p =
1023 (prev_year + prev_year / 4 - prev_year / 100 + prev_year / 400) %
1024 days_per_week;
1025 return 52 + ((curr_p == 4 || prev_p == 3) ? 1 : 0);
1026 }
1027 auto iso_week_num(int tm_yday, int tm_wday) const noexcept -> int {
1028 return (tm_yday + 11 - (tm_wday == 0 ? days_per_week : tm_wday)) /
1029 days_per_week;
1030 }
1031 auto tm_iso_week_year() const noexcept -> long long {
1032 const auto year = tm_year();
1033 const auto w = iso_week_num(tm_yday(), tm_wday());
1034 if (w < 1) return year - 1;
1035 if (w > iso_year_weeks(year)) return year + 1;
1036 return year;
1037 }
1038 auto tm_iso_week_of_year() const noexcept -> int {
1039 const auto year = tm_year();
1040 const auto w = iso_week_num(tm_yday(), tm_wday());
1041 if (w < 1) return iso_year_weeks(year - 1);
1042 if (w > iso_year_weeks(year)) return 1;
1043 return w;
1044 }
1045
1046 void write1(int value) {
1047 *out_++ = static_cast<char>('0' + to_unsigned(value) % 10);
1048 }
1049 void write2(int value) {
1050 const char* d = digits2(to_unsigned(value) % 100);
1051 *out_++ = *d++;
1052 *out_++ = *d;
1053 }
1054
1055 void write_year_extended(long long year) {
1056 // At least 4 characters.
1057 int width = 4;
1058 if (year < 0) {
1059 *out_++ = '-';
1060 year = 0 - year;
1061 --width;
1062 }
1064 const int num_digits = count_digits(n);
1065 if (width > num_digits) out_ = std::fill_n(out_, width - num_digits, '0');
1066 out_ = format_decimal<Char>(out_, n, num_digits).end;
1067 }
1068 void write_year(long long year) {
1069 if (year >= 0 && year < 10000) {
1070 write2(static_cast<int>(year / 100));
1071 write2(static_cast<int>(year % 100));
1072 } else {
1073 write_year_extended(year);
1074 }
1075 }
1076
1077 void write_utc_offset(long offset) {
1078 if (offset < 0) {
1079 *out_++ = '-';
1080 offset = -offset;
1081 } else {
1082 *out_++ = '+';
1083 }
1084 offset /= 60;
1085 write2(static_cast<int>(offset / 60));
1086 write2(static_cast<int>(offset % 60));
1087 }
1088 template <typename T, FMT_ENABLE_IF(has_member_data_tm_gmtoff<T>::value)>
1089 void format_utc_offset_impl(const T& tm) {
1090 write_utc_offset(tm.tm_gmtoff);
1091 }
1092 template <typename T, FMT_ENABLE_IF(!has_member_data_tm_gmtoff<T>::value)>
1093 void format_utc_offset_impl(const T& tm) {
1094#if defined(_WIN32) && defined(_UCRT)
1095# if FMT_USE_TZSET
1096 tzset_once();
1097# endif
1098 long offset = 0;
1099 _get_timezone(&offset);
1100 if (tm.tm_isdst) {
1101 long dstbias = 0;
1102 _get_dstbias(&dstbias);
1103 offset += dstbias;
1104 }
1105 write_utc_offset(-offset);
1106#else
1107 ignore_unused(tm);
1108 format_localized('z');
1109#endif
1110 }
1111
1112 template <typename T, FMT_ENABLE_IF(has_member_data_tm_zone<T>::value)>
1113 void format_tz_name_impl(const T& tm) {
1114 if (is_classic_)
1115 out_ = write_tm_str<Char>(out_, tm.tm_zone, loc_);
1116 else
1117 format_localized('Z');
1118 }
1119 template <typename T, FMT_ENABLE_IF(!has_member_data_tm_zone<T>::value)>
1120 void format_tz_name_impl(const T&) {
1121 format_localized('Z');
1122 }
1123
1124 void format_localized(char format, char modifier = 0) {
1125 out_ = write<Char>(out_, tm_, loc_, format, modifier);
1126 }
1127
1128 public:
1129 tm_writer(const std::locale& loc, OutputIt out, const std::tm& tm)
1130 : loc_(loc),
1131 is_classic_(loc_ == get_classic_locale()),
1132 out_(out),
1133 tm_(tm) {}
1134
1135 OutputIt out() const { return out_; }
1136
1137 FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) {
1138 out_ = copy_str<Char>(begin, end, out_);
1139 }
1140
1142 if (is_classic_)
1143 out_ = write(out_, tm_wday_short_name(tm_wday()));
1144 else
1145 format_localized('a');
1146 }
1148 if (is_classic_)
1149 out_ = write(out_, tm_wday_full_name(tm_wday()));
1150 else
1151 format_localized('A');
1152 }
1154 if (is_classic_ || ns == numeric_system::standard) return write1(tm_wday());
1155 format_localized('w', 'O');
1156 }
1158 if (is_classic_ || ns == numeric_system::standard) {
1159 auto wday = tm_wday();
1160 write1(wday == 0 ? days_per_week : wday);
1161 } else {
1162 format_localized('u', 'O');
1163 }
1164 }
1165
1167 if (is_classic_)
1168 out_ = write(out_, tm_mon_short_name(tm_mon()));
1169 else
1170 format_localized('b');
1171 }
1173 if (is_classic_)
1174 out_ = write(out_, tm_mon_full_name(tm_mon()));
1175 else
1176 format_localized('B');
1177 }
1178
1180 if (is_classic_) {
1182 *out_++ = ' ';
1183 on_abbr_month();
1184 *out_++ = ' ';
1186 *out_++ = ' ';
1187 on_iso_time();
1188 *out_++ = ' ';
1190 } else {
1191 format_localized('c', ns == numeric_system::standard ? '\0' : 'E');
1192 }
1193 }
1195 if (is_classic_)
1196 on_us_date();
1197 else
1198 format_localized('x', ns == numeric_system::standard ? '\0' : 'E');
1199 }
1201 if (is_classic_)
1202 on_iso_time();
1203 else
1204 format_localized('X', ns == numeric_system::standard ? '\0' : 'E');
1205 }
1206 void on_us_date() {
1207 char buf[8];
1208 write_digit2_separated(buf, to_unsigned(tm_mon() + 1),
1209 to_unsigned(tm_mday()),
1210 to_unsigned(split_year_lower(tm_year())), '/');
1211 out_ = copy_str<Char>(std::begin(buf), std::end(buf), out_);
1212 }
1214 auto year = tm_year();
1215 char buf[10];
1216 size_t offset = 0;
1217 if (year >= 0 && year < 10000) {
1218 copy2(buf, digits2(static_cast<size_t>(year / 100)));
1219 } else {
1220 offset = 4;
1221 write_year_extended(year);
1222 year = 0;
1223 }
1224 write_digit2_separated(buf + 2, static_cast<unsigned>(year % 100),
1225 to_unsigned(tm_mon() + 1), to_unsigned(tm_mday()),
1226 '-');
1227 out_ = copy_str<Char>(std::begin(buf) + offset, std::end(buf), out_);
1228 }
1229
1230 void on_utc_offset() { format_utc_offset_impl(tm_); }
1231 void on_tz_name() { format_tz_name_impl(tm_); }
1232
1234 if (is_classic_ || ns == numeric_system::standard)
1235 return write_year(tm_year());
1236 format_localized('Y', 'E');
1237 }
1239 if (is_classic_ || ns == numeric_system::standard)
1240 return write2(split_year_lower(tm_year()));
1241 format_localized('y', 'O');
1242 }
1244 if (is_classic_) return write2(split_year_lower(tm_year()));
1245 format_localized('y', 'E');
1246 }
1247
1249 if (is_classic_ || ns == numeric_system::standard) {
1250 auto year = tm_year();
1251 auto upper = year / 100;
1252 if (year >= -99 && year < 0) {
1253 // Zero upper on negative year.
1254 *out_++ = '-';
1255 *out_++ = '0';
1256 } else if (upper >= 0 && upper < 100) {
1257 write2(static_cast<int>(upper));
1258 } else {
1259 out_ = write<Char>(out_, upper);
1260 }
1261 } else {
1262 format_localized('C', 'E');
1263 }
1264 }
1265
1267 if (is_classic_ || ns == numeric_system::standard)
1268 return write2(tm_mon() + 1);
1269 format_localized('m', 'O');
1270 }
1271
1273 if (is_classic_ || ns == numeric_system::standard)
1274 return write2((tm_yday() + days_per_week - tm_wday()) / days_per_week);
1275 format_localized('U', 'O');
1276 }
1278 if (is_classic_ || ns == numeric_system::standard) {
1279 auto wday = tm_wday();
1280 write2((tm_yday() + days_per_week -
1281 (wday == 0 ? (days_per_week - 1) : (wday - 1))) /
1282 days_per_week);
1283 } else {
1284 format_localized('W', 'O');
1285 }
1286 }
1288 if (is_classic_ || ns == numeric_system::standard)
1289 return write2(tm_iso_week_of_year());
1290 format_localized('V', 'O');
1291 }
1292
1293 void on_iso_week_based_year() { write_year(tm_iso_week_year()); }
1295 write2(split_year_lower(tm_iso_week_year()));
1296 }
1297
1299 auto yday = tm_yday() + 1;
1300 write1(yday / 100);
1301 write2(yday % 100);
1302 }
1304 if (is_classic_ || ns == numeric_system::standard) return write2(tm_mday());
1305 format_localized('d', 'O');
1306 }
1308 if (is_classic_ || ns == numeric_system::standard) {
1309 auto mday = to_unsigned(tm_mday()) % 100;
1310 const char* d2 = digits2(mday);
1311 *out_++ = mday < 10 ? ' ' : d2[0];
1312 *out_++ = d2[1];
1313 } else {
1314 format_localized('e', 'O');
1315 }
1316 }
1317
1319 if (is_classic_ || ns == numeric_system::standard) return write2(tm_hour());
1320 format_localized('H', 'O');
1321 }
1323 if (is_classic_ || ns == numeric_system::standard)
1324 return write2(tm_hour12());
1325 format_localized('I', 'O');
1326 }
1328 if (is_classic_ || ns == numeric_system::standard) return write2(tm_min());
1329 format_localized('M', 'O');
1330 }
1332 if (is_classic_ || ns == numeric_system::standard) return write2(tm_sec());
1333 format_localized('S', 'O');
1334 }
1335
1337 if (is_classic_) {
1338 char buf[8];
1339 write_digit2_separated(buf, to_unsigned(tm_hour12()),
1340 to_unsigned(tm_min()), to_unsigned(tm_sec()), ':');
1341 out_ = copy_str<Char>(std::begin(buf), std::end(buf), out_);
1342 *out_++ = ' ';
1343 on_am_pm();
1344 } else {
1345 format_localized('r');
1346 }
1347 }
1349 write2(tm_hour());
1350 *out_++ = ':';
1351 write2(tm_min());
1352 }
1354 char buf[8];
1355 write_digit2_separated(buf, to_unsigned(tm_hour()), to_unsigned(tm_min()),
1356 to_unsigned(tm_sec()), ':');
1357 out_ = copy_str<Char>(std::begin(buf), std::end(buf), out_);
1358 }
1359
1360 void on_am_pm() {
1361 if (is_classic_) {
1362 *out_++ = tm_hour() < 12 ? 'A' : 'P';
1363 *out_++ = 'M';
1364 } else {
1365 format_localized('p');
1366 }
1367 }
1368
1369 // These apply to chrono durations but not tm.
1372};
1373
1374struct chrono_format_checker : null_chrono_spec_handler<chrono_format_checker> {
1376
1377 template <typename Char>
1378 FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
1389};
1390
1391template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
1392inline bool isfinite(T) {
1393 return true;
1394}
1395
1396// Converts value to Int and checks that it's in the range [0, upper).
1397template <typename T, typename Int, FMT_ENABLE_IF(std::is_integral<T>::value)>
1398inline Int to_nonnegative_int(T value, Int upper) {
1399 FMT_ASSERT(std::is_unsigned<Int>::value ||
1400 (value >= 0 && to_unsigned(value) <= to_unsigned(upper)),
1401 "invalid value");
1402 (void)upper;
1403 return static_cast<Int>(value);
1404}
1405template <typename T, typename Int, FMT_ENABLE_IF(!std::is_integral<T>::value)>
1406inline Int to_nonnegative_int(T value, Int upper) {
1407 if (value < 0 || value > static_cast<T>(upper))
1408 FMT_THROW(format_error("invalid value"));
1409 return static_cast<Int>(value);
1410}
1411
1412template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
1413inline T mod(T x, int y) {
1414 return x % static_cast<T>(y);
1415}
1416template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
1417inline T mod(T x, int y) {
1418 return std::fmod(x, static_cast<T>(y));
1419}
1420
1421// If T is an integral type, maps T to its unsigned counterpart, otherwise
1422// leaves it unchanged (unlike std::make_unsigned).
1423template <typename T, bool INTEGRAL = std::is_integral<T>::value>
1425 using type = T;
1426};
1427
1428template <typename T> struct make_unsigned_or_unchanged<T, true> {
1430};
1431
1432#if FMT_SAFE_DURATION_CAST
1433// throwing version of safe_duration_cast
1434template <typename To, typename FromRep, typename FromPeriod>
1435To fmt_safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from) {
1436 int ec;
1437 To to = safe_duration_cast::safe_duration_cast<To>(from, ec);
1438 if (ec) FMT_THROW(format_error("cannot format duration"));
1439 return to;
1440}
1441#endif
1442
1443template <typename Rep, typename Period,
1444 FMT_ENABLE_IF(std::is_integral<Rep>::value)>
1445inline std::chrono::duration<Rep, std::milli> get_milliseconds(
1446 std::chrono::duration<Rep, Period> d) {
1447 // this may overflow and/or the result may not fit in the
1448 // target type.
1449#if FMT_SAFE_DURATION_CAST
1450 using CommonSecondsType =
1451 typename std::common_type<decltype(d), std::chrono::seconds>::type;
1452 const auto d_as_common = fmt_safe_duration_cast<CommonSecondsType>(d);
1453 const auto d_as_whole_seconds =
1454 fmt_safe_duration_cast<std::chrono::seconds>(d_as_common);
1455 // this conversion should be nonproblematic
1456 const auto diff = d_as_common - d_as_whole_seconds;
1457 const auto ms =
1458 fmt_safe_duration_cast<std::chrono::duration<Rep, std::milli>>(diff);
1459 return ms;
1460#else
1461 auto s = std::chrono::duration_cast<std::chrono::seconds>(d);
1462 return std::chrono::duration_cast<std::chrono::milliseconds>(d - s);
1463#endif
1464}
1465
1466// Counts the number of fractional digits in the range [0, 18] according to the
1467// C++20 spec. If more than 18 fractional digits are required then returns 6 for
1468// microseconds precision.
1469template <long long Num, long long Den, int N = 0,
1470 bool Enabled = (N < 19) && (Num <= max_value<long long>() / 10)>
1472 static constexpr int value =
1474};
1475
1476// Base case that doesn't instantiate any more templates
1477// in order to avoid overflow.
1478template <long long Num, long long Den, int N>
1480 static constexpr int value = (Num % Den == 0) ? N : 6;
1481};
1482
1483constexpr long long pow10(std::uint32_t n) {
1484 return n == 0 ? 1 : 10 * pow10(n - 1);
1485}
1486
1487template <class Rep, class Period,
1489constexpr std::chrono::duration<Rep, Period> abs(
1490 std::chrono::duration<Rep, Period> d) {
1491 // We need to compare the duration using the count() method directly
1492 // due to a compiler bug in clang-11 regarding the spaceship operator,
1493 // when -Wzero-as-null-pointer-constant is enabled.
1494 // In clang-12 the bug has been fixed. See
1495 // https://bugs.llvm.org/show_bug.cgi?id=46235 and the reproducible example:
1496 // https://www.godbolt.org/z/Knbb5joYx.
1497 return d.count() >= d.zero().count() ? d : -d;
1498}
1499
1500template <class Rep, class Period,
1502constexpr std::chrono::duration<Rep, Period> abs(
1503 std::chrono::duration<Rep, Period> d) {
1504 return d;
1505}
1506
1507template <typename Char, typename Rep, typename OutputIt,
1508 FMT_ENABLE_IF(std::is_integral<Rep>::value)>
1509OutputIt format_duration_value(OutputIt out, Rep val, int) {
1510 return write<Char>(out, val);
1511}
1512
1513template <typename Char, typename Rep, typename OutputIt,
1514 FMT_ENABLE_IF(std::is_floating_point<Rep>::value)>
1515OutputIt format_duration_value(OutputIt out, Rep val, int precision) {
1516 auto specs = basic_format_specs<Char>();
1517 specs.precision = precision;
1518 specs.type = precision >= 0 ? presentation_type::fixed_lower
1520 return write<Char>(out, val, specs);
1521}
1522
1523template <typename Char, typename OutputIt>
1524OutputIt copy_unit(string_view unit, OutputIt out, Char) {
1525 return std::copy(unit.begin(), unit.end(), out);
1526}
1527
1528template <typename OutputIt>
1529OutputIt copy_unit(string_view unit, OutputIt out, wchar_t) {
1530 // This works when wchar_t is UTF-32 because units only contain characters
1531 // that have the same representation in UTF-16 and UTF-32.
1532 utf8_to_utf16 u(unit);
1533 return std::copy(u.c_str(), u.c_str() + u.size(), out);
1534}
1535
1536template <typename Char, typename Period, typename OutputIt>
1537OutputIt format_duration_unit(OutputIt out) {
1538 if (const char* unit = get_units<Period>())
1539 return copy_unit(string_view(unit), out, Char());
1540 *out++ = '[';
1541 out = write<Char>(out, Period::num);
1542 if (const_check(Period::den != 1)) {
1543 *out++ = '/';
1544 out = write<Char>(out, Period::den);
1545 }
1546 *out++ = ']';
1547 *out++ = 's';
1548 return out;
1549}
1550
1552 private:
1553 union {
1554 std::locale locale_;
1555 };
1556 bool has_locale_ = false;
1557
1558 public:
1559 get_locale(bool localized, locale_ref loc) : has_locale_(localized) {
1560 if (localized)
1561 ::new (&locale_) std::locale(loc.template get<std::locale>());
1562 }
1564 if (has_locale_) locale_.~locale();
1565 }
1566 operator const std::locale&() const {
1567 return has_locale_ ? locale_ : get_classic_locale();
1568 }
1569};
1570
1571template <typename FormatContext, typename OutputIt, typename Rep,
1572 typename Period>
1574 FormatContext& context;
1575 OutputIt out;
1577 bool localized = false;
1578 // rep is unsigned to avoid overflow.
1579 using rep =
1580 conditional_t<std::is_integral<Rep>::value && sizeof(Rep) < sizeof(int),
1581 unsigned, typename make_unsigned_or_unchanged<Rep>::type>;
1583 using seconds = std::chrono::duration<rep>;
1585 using milliseconds = std::chrono::duration<rep, std::milli>;
1587
1588 using char_type = typename FormatContext::char_type;
1590
1591 chrono_formatter(FormatContext& ctx, OutputIt o,
1592 std::chrono::duration<Rep, Period> d)
1593 : context(ctx),
1594 out(o),
1595 val(static_cast<rep>(d.count())),
1596 negative(false) {
1597 if (d.count() < 0) {
1598 val = 0 - val;
1599 negative = true;
1600 }
1601
1602 // this may overflow and/or the result may not fit in the
1603 // target type.
1604#if FMT_SAFE_DURATION_CAST
1605 // might need checked conversion (rep!=Rep)
1606 auto tmpval = std::chrono::duration<rep, Period>(val);
1607 s = fmt_safe_duration_cast<seconds>(tmpval);
1608#else
1609 s = std::chrono::duration_cast<seconds>(
1610 std::chrono::duration<rep, Period>(val));
1611#endif
1612 }
1613
1614 // returns true if nan or inf, writes to out.
1616 if (isfinite(val)) {
1617 return false;
1618 }
1619 if (isnan(val)) {
1620 write_nan();
1621 return true;
1622 }
1623 // must be +-inf
1624 if (val > 0) {
1625 write_pinf();
1626 } else {
1627 write_ninf();
1628 }
1629 return true;
1630 }
1631
1632 Rep hour() const { return static_cast<Rep>(mod((s.count() / 3600), 24)); }
1633
1634 Rep hour12() const {
1635 Rep hour = static_cast<Rep>(mod((s.count() / 3600), 12));
1636 return hour <= 0 ? 12 : hour;
1637 }
1638
1639 Rep minute() const { return static_cast<Rep>(mod((s.count() / 60), 60)); }
1640 Rep second() const { return static_cast<Rep>(mod(s.count(), 60)); }
1641
1642 std::tm time() const {
1643 auto time = std::tm();
1644 time.tm_hour = to_nonnegative_int(hour(), 24);
1645 time.tm_min = to_nonnegative_int(minute(), 60);
1646 time.tm_sec = to_nonnegative_int(second(), 60);
1647 return time;
1648 }
1649
1650 void write_sign() {
1651 if (negative) {
1652 *out++ = '-';
1653 negative = false;
1654 }
1655 }
1656
1657 void write(Rep value, int width) {
1658 write_sign();
1659 if (isnan(value)) return write_nan();
1661 to_unsigned(to_nonnegative_int(value, max_value<int>()));
1662 int num_digits = detail::count_digits(n);
1663 if (width > num_digits) out = std::fill_n(out, width - num_digits, '0');
1664 out = format_decimal<char_type>(out, n, num_digits).end;
1665 }
1666
1667 template <typename Duration> void write_fractional_seconds(Duration d) {
1668 FMT_ASSERT(!std::is_floating_point<typename Duration::rep>::value, "");
1669 constexpr auto num_fractional_digits =
1670 count_fractional_digits<Duration::period::num,
1671 Duration::period::den>::value;
1672
1673 using subsecond_precision = std::chrono::duration<
1674 typename std::common_type<typename Duration::rep,
1675 std::chrono::seconds::rep>::type,
1676 std::ratio<1, detail::pow10(num_fractional_digits)>>;
1677 if (std::ratio_less<typename subsecond_precision::period,
1678 std::chrono::seconds::period>::value) {
1679 *out++ = '.';
1680 auto fractional =
1681 detail::abs(d) - std::chrono::duration_cast<std::chrono::seconds>(d);
1682 auto subseconds =
1683 std::chrono::treat_as_floating_point<
1684 typename subsecond_precision::rep>::value
1685 ? fractional.count()
1686 : std::chrono::duration_cast<subsecond_precision>(fractional)
1687 .count();
1689 to_unsigned(to_nonnegative_int(subseconds, max_value<long long>()));
1690 int num_digits = detail::count_digits(n);
1691 if (num_fractional_digits > num_digits)
1692 out = std::fill_n(out, num_fractional_digits - num_digits, '0');
1693 out = format_decimal<char_type>(out, n, num_digits).end;
1694 }
1695 }
1696
1697 void write_nan() { std::copy_n("nan", 3, out); }
1698 void write_pinf() { std::copy_n("inf", 3, out); }
1699 void write_ninf() { std::copy_n("-inf", 4, out); }
1700
1701 template <typename Callback, typename... Args>
1702 void format_tm(const tm& time, Callback cb, Args... args) {
1703 if (isnan(val)) return write_nan();
1704 get_locale loc(localized, context.locale());
1705 auto w = tm_writer_type(loc, out, time);
1706 (w.*cb)(args...);
1707 out = w.out();
1708 }
1709
1710 void on_text(const char_type* begin, const char_type* end) {
1711 std::copy(begin, end, out);
1712 }
1713
1714 // These are not implemented because durations don't have date information.
1724 void on_us_date() {}
1725 void on_iso_date() {}
1727 void on_tz_name() {}
1741
1743 if (handle_nan_inf()) return;
1744
1745 if (ns == numeric_system::standard) return write(hour(), 2);
1746 auto time = tm();
1747 time.tm_hour = to_nonnegative_int(hour(), 24);
1749 }
1750
1752 if (handle_nan_inf()) return;
1753
1754 if (ns == numeric_system::standard) return write(hour12(), 2);
1755 auto time = tm();
1756 time.tm_hour = to_nonnegative_int(hour12(), 12);
1758 }
1759
1761 if (handle_nan_inf()) return;
1762
1763 if (ns == numeric_system::standard) return write(minute(), 2);
1764 auto time = tm();
1765 time.tm_min = to_nonnegative_int(minute(), 60);
1767 }
1768
1770 if (handle_nan_inf()) return;
1771
1772 if (ns == numeric_system::standard) {
1773 if (std::is_floating_point<rep>::value) {
1774 constexpr auto num_fractional_digits =
1776 auto buf = memory_buffer();
1777 format_to(std::back_inserter(buf), runtime("{:.{}f}"),
1778 std::fmod(val * static_cast<rep>(Period::num) /
1779 static_cast<rep>(Period::den),
1780 static_cast<rep>(60)),
1781 num_fractional_digits);
1782 if (negative) *out++ = '-';
1783 if (buf.size() < 2 || buf[1] == '.') *out++ = '0';
1784 out = std::copy(buf.begin(), buf.end(), out);
1785 } else {
1786 write(second(), 2);
1787 write_fractional_seconds(std::chrono::duration<rep, Period>(val));
1788 }
1789 return;
1790 }
1791 auto time = tm();
1792 time.tm_sec = to_nonnegative_int(second(), 60);
1794 }
1795
1797 if (handle_nan_inf()) return;
1799 }
1800
1802 if (handle_nan_inf()) {
1803 *out++ = ':';
1805 return;
1806 }
1807
1808 write(hour(), 2);
1809 *out++ = ':';
1810 write(minute(), 2);
1811 }
1812
1815 *out++ = ':';
1816 if (handle_nan_inf()) return;
1818 }
1819
1820 void on_am_pm() {
1821 if (handle_nan_inf()) return;
1823 }
1824
1826 if (handle_nan_inf()) return;
1827 write_sign();
1828 out = format_duration_value<char_type>(out, val, precision);
1829 }
1830
1832 out = format_duration_unit<char_type, Period>(out);
1833 }
1834};
1835
1837
1838#if defined(__cpp_lib_chrono) && __cpp_lib_chrono >= 201907
1839using weekday = std::chrono::weekday;
1840#else
1841// A fallback version of weekday.
1842class weekday {
1843 private:
1844 unsigned char value;
1845
1846 public:
1847 weekday() = default;
1848 explicit constexpr weekday(unsigned wd) noexcept
1849 : value(static_cast<unsigned char>(wd != 7 ? wd : 0)) {}
1850 constexpr unsigned c_encoding() const noexcept { return value; }
1851};
1852
1854#endif
1855
1856// A rudimentary weekday formatter.
1857template <typename Char> struct formatter<weekday, Char> {
1858 private:
1859 bool localized = false;
1860
1861 public:
1863 -> decltype(ctx.begin()) {
1864 auto begin = ctx.begin(), end = ctx.end();
1865 if (begin != end && *begin == 'L') {
1866 ++begin;
1867 localized = true;
1868 }
1869 return begin;
1870 }
1871
1872 template <typename FormatContext>
1873 auto format(weekday wd, FormatContext& ctx) const -> decltype(ctx.out()) {
1874 auto time = std::tm();
1875 time.tm_wday = static_cast<int>(wd.c_encoding());
1876 detail::get_locale loc(localized, ctx.locale());
1877 auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), time);
1878 w.on_abbr_weekday();
1879 return w.out();
1880 }
1881};
1882
1883template <typename Rep, typename Period, typename Char>
1884struct formatter<std::chrono::duration<Rep, Period>, Char> {
1885 private:
1887 int precision = -1;
1888 using arg_ref_type = detail::arg_ref<Char>;
1889 arg_ref_type width_ref;
1890 arg_ref_type precision_ref;
1891 bool localized = false;
1892 basic_string_view<Char> format_str;
1893 using duration = std::chrono::duration<Rep, Period>;
1894
1895 struct spec_handler {
1896 formatter& f;
1898 basic_string_view<Char> format_str;
1899
1900 template <typename Id> FMT_CONSTEXPR arg_ref_type make_arg_ref(Id arg_id) {
1901 context.check_arg_id(arg_id);
1902 return arg_ref_type(arg_id);
1903 }
1904
1905 FMT_CONSTEXPR arg_ref_type make_arg_ref(basic_string_view<Char> arg_id) {
1906 context.check_arg_id(arg_id);
1907 return arg_ref_type(arg_id);
1908 }
1909
1910 FMT_CONSTEXPR arg_ref_type make_arg_ref(detail::auto_id) {
1911 return arg_ref_type(context.next_arg_id());
1912 }
1913
1914 void on_error(const char* msg) { FMT_THROW(format_error(msg)); }
1916 f.specs.fill = fill;
1917 }
1918 FMT_CONSTEXPR void on_align(align_t align) { f.specs.align = align; }
1919 FMT_CONSTEXPR void on_width(int width) { f.specs.width = width; }
1920 FMT_CONSTEXPR void on_precision(int _precision) {
1921 f.precision = _precision;
1922 }
1923 FMT_CONSTEXPR void end_precision() {}
1924
1925 template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {
1926 f.width_ref = make_arg_ref(arg_id);
1927 }
1928
1929 template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {
1930 f.precision_ref = make_arg_ref(arg_id);
1931 }
1932 };
1933
1934 using iterator = typename basic_format_parse_context<Char>::iterator;
1935 struct parse_range {
1936 iterator begin;
1937 iterator end;
1938 };
1939
1940 FMT_CONSTEXPR parse_range do_parse(basic_format_parse_context<Char>& ctx) {
1941 auto begin = ctx.begin(), end = ctx.end();
1942 if (begin == end || *begin == '}') return {begin, begin};
1943 spec_handler handler{*this, ctx, format_str};
1944 begin = detail::parse_align(begin, end, handler);
1945 if (begin == end) return {begin, begin};
1946 begin = detail::parse_width(begin, end, handler);
1947 if (begin == end) return {begin, begin};
1948 if (*begin == '.') {
1949 if (std::is_floating_point<Rep>::value)
1950 begin = detail::parse_precision(begin, end, handler);
1951 else
1952 handler.on_error("precision not allowed for this argument type");
1953 }
1954 if (begin != end && *begin == 'L') {
1955 ++begin;
1956 localized = true;
1957 }
1959 detail::chrono_format_checker());
1960 return {begin, end};
1961 }
1962
1963 public:
1965 -> decltype(ctx.begin()) {
1966 auto range = do_parse(ctx);
1967 format_str = basic_string_view<Char>(
1968 &*range.begin, detail::to_unsigned(range.end - range.begin));
1969 return range.end;
1970 }
1971
1972 template <typename FormatContext>
1973 auto format(const duration& d, FormatContext& ctx) const
1974 -> decltype(ctx.out()) {
1975 auto specs_copy = specs;
1976 auto precision_copy = precision;
1977 auto begin = format_str.begin(), end = format_str.end();
1978 // As a possible future optimization, we could avoid extra copying if width
1979 // is not specified.
1981 auto out = std::back_inserter(buf);
1982 detail::handle_dynamic_spec<detail::width_checker>(specs_copy.width,
1983 width_ref, ctx);
1984 detail::handle_dynamic_spec<detail::precision_checker>(precision_copy,
1985 precision_ref, ctx);
1986 if (begin == end || *begin == '}') {
1987 out = detail::format_duration_value<Char>(out, d.count(), precision_copy);
1988 detail::format_duration_unit<Char, Period>(out);
1989 } else {
1990 detail::chrono_formatter<FormatContext, decltype(out), Rep, Period> f(
1991 ctx, out, d);
1992 f.precision = precision_copy;
1993 f.localized = localized;
1995 }
1996 return detail::write(
1997 ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs_copy);
1998 }
1999};
2000
2001template <typename Char, typename Duration>
2002struct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>,
2003 Char> : formatter<std::tm, Char> {
2005 basic_string_view<Char> default_specs =
2007 this->do_parse(default_specs.begin(), default_specs.end());
2008 }
2009
2010 template <typename FormatContext>
2011 auto format(std::chrono::time_point<std::chrono::system_clock> val,
2012 FormatContext& ctx) const -> decltype(ctx.out()) {
2014 }
2015};
2016
2017template <typename Char> struct formatter<std::tm, Char> {
2018 private:
2019 enum class spec {
2020 unknown,
2022 hh_mm_ss,
2023 };
2024 spec spec_ = spec::unknown;
2026
2027 protected:
2028 template <typename It> FMT_CONSTEXPR auto do_parse(It begin, It end) -> It {
2029 if (begin != end && *begin == ':') ++begin;
2030 end = detail::parse_chrono_format(begin, end, detail::tm_format_checker());
2031 // Replace default spec only if the new spec is not empty.
2032 if (end != begin) specs = {begin, detail::to_unsigned(end - begin)};
2033 return end;
2034 }
2035
2036 public:
2038 -> decltype(ctx.begin()) {
2039 auto end = this->do_parse(ctx.begin(), ctx.end());
2040 // basic_string_view<>::compare isn't constexpr before C++17.
2041 if (specs.size() == 2 && specs[0] == Char('%')) {
2042 if (specs[1] == Char('F'))
2043 spec_ = spec::year_month_day;
2044 else if (specs[1] == Char('T'))
2045 spec_ = spec::hh_mm_ss;
2046 }
2047 return end;
2048 }
2049
2050 template <typename FormatContext>
2051 auto format(const std::tm& tm, FormatContext& ctx) const
2052 -> decltype(ctx.out()) {
2053 const auto loc_ref = ctx.locale();
2054 detail::get_locale loc(static_cast<bool>(loc_ref), loc_ref);
2055 auto w = detail::tm_writer<decltype(ctx.out()), Char>(loc, ctx.out(), tm);
2056 if (spec_ == spec::year_month_day)
2057 w.on_iso_date();
2058 else if (spec_ == spec::hh_mm_ss)
2059 w.on_iso_time();
2060 else
2061 detail::parse_chrono_format(specs.begin(), specs.end(), w);
2062 return w.out();
2063 }
2064};
2065
2068
2069#endif // FMT_CHRONO_H_
and restrictions which apply to each piece of software is included later in this file and or inside of the individual applicable source files The disclaimer of warranty in the WPILib license above applies to all code in and nothing in any of the other licenses gives permission to use the names of FIRST nor the names of the WPILib contributors to endorse or promote products derived from this software The following pieces of software have additional or alternate and or Google Inc All rights reserved Redistribution and use in source and binary with or without are permitted provided that the following conditions are this list of conditions and the following disclaimer *Redistributions in binary form must reproduce the above copyright this list of conditions and the following disclaimer in the documentation and or other materials provided with the distribution *Neither the name of Google Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY OR CONSEQUENTIAL WHETHER IN STRICT OR EVEN IF ADVISED OF THE POSSIBILITY OF SUCH January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the whether in Source or Object that is based or other modifications as a an original work of authorship For the purposes of this Derivative Works shall not include works that remain separable from
Definition: ThirdPartyNotices.txt:128
\rst Parsing context consisting of a format string range being parsed and an argument counter for aut...
Definition: core.h:654
FMT_CONSTEXPR void check_arg_id(int id)
Reports an error if using the automatic argument indexing; otherwise switches to the manual indexing.
Definition: core.h:706
constexpr auto end() const noexcept -> iterator
Returns an iterator past the end of the format string range being parsed.
Definition: core.h:681
typename basic_string_view< Char >::iterator iterator
Definition: core.h:663
FMT_CONSTEXPR auto next_arg_id() -> int
Reports an error if using the manual argument indexing; otherwise returns the next argument index and...
Definition: core.h:692
constexpr auto begin() const noexcept -> iterator
Returns an iterator to the beginning of the format string range being parsed.
Definition: core.h:674
\rst A dynamically growing memory buffer for trivially copyable/constructible types with the first SI...
Definition: format.h:819
constexpr auto end() const noexcept -> iterator
Definition: core.h:478
constexpr auto size() const noexcept -> size_t
Returns the string size.
Definition: core.h:475
constexpr auto begin() const noexcept -> iterator
Definition: core.h:477
Definition: format.h:264
A formatting error such as invalid format string.
Definition: format.h:957
Definition: chrono.h:1551
get_locale(bool localized, locale_ref loc)
Definition: chrono.h:1559
std::locale locale_
Definition: chrono.h:1554
~get_locale()
Definition: chrono.h:1563
Definition: core.h:1710
Definition: chrono.h:960
void on_am_pm()
Definition: chrono.h:1360
void on_duration_value()
Definition: chrono.h:1370
void on_datetime(numeric_system ns)
Definition: chrono.h:1179
void on_abbr_weekday()
Definition: chrono.h:1141
void on_dec1_weekday(numeric_system ns)
Definition: chrono.h:1157
tm_writer(const std::locale &loc, OutputIt out, const std::tm &tm)
Definition: chrono.h:1129
void on_minute(numeric_system ns)
Definition: chrono.h:1327
void on_day_of_month_space(numeric_system ns)
Definition: chrono.h:1307
void on_tz_name()
Definition: chrono.h:1231
void on_year(numeric_system ns)
Definition: chrono.h:1233
FMT_CONSTEXPR void on_text(const Char *begin, const Char *end)
Definition: chrono.h:1137
void on_duration_unit()
Definition: chrono.h:1371
void on_iso_time()
Definition: chrono.h:1353
void on_dec_month(numeric_system ns)
Definition: chrono.h:1266
void on_iso_week_based_year()
Definition: chrono.h:1293
void on_loc_time(numeric_system ns)
Definition: chrono.h:1200
void on_offset_year()
Definition: chrono.h:1243
void on_second(numeric_system ns)
Definition: chrono.h:1331
OutputIt out() const
Definition: chrono.h:1135
void on_iso_week_based_short_year()
Definition: chrono.h:1294
void on_dec1_week_of_year(numeric_system ns)
Definition: chrono.h:1277
void on_abbr_month()
Definition: chrono.h:1166
void on_dec0_weekday(numeric_system ns)
Definition: chrono.h:1153
void on_24_hour(numeric_system ns)
Definition: chrono.h:1318
void on_iso_date()
Definition: chrono.h:1213
void on_day_of_year()
Definition: chrono.h:1298
void on_iso_week_of_year(numeric_system ns)
Definition: chrono.h:1287
void on_24_hour_time()
Definition: chrono.h:1348
void on_full_weekday()
Definition: chrono.h:1147
void on_us_date()
Definition: chrono.h:1206
void on_full_month()
Definition: chrono.h:1172
void on_12_hour_time()
Definition: chrono.h:1336
void on_short_year(numeric_system ns)
Definition: chrono.h:1238
void on_dec0_week_of_year(numeric_system ns)
Definition: chrono.h:1272
void on_loc_date(numeric_system ns)
Definition: chrono.h:1194
void on_utc_offset()
Definition: chrono.h:1230
void on_century(numeric_system ns)
Definition: chrono.h:1248
void on_12_hour(numeric_system ns)
Definition: chrono.h:1322
void on_day_of_month(numeric_system ns)
Definition: chrono.h:1303
Definition: format.h:1282
auto size() const -> size_t
Definition: format.h:1289
auto c_str() const -> const wchar_t *
Definition: format.h:1290
Definition: core.h:1240
Definition: chrono.h:1842
constexpr weekday(unsigned wd) noexcept
Definition: chrono.h:1848
weekday()=default
constexpr unsigned c_encoding() const noexcept
Definition: chrono.h:1850
Definition: chrono.h:1853
constexpr FMT_INLINE auto const_check(T value) -> T
Definition: core.h:356
#define FMT_ASSERT(condition, message)
Definition: core.h:369
basic_string_view< char > string_view
Definition: core.h:520
align::type align_t
Definition: core.h:2084
#define FMT_END_DETAIL_NAMESPACE
Definition: core.h:227
#define FMT_MODULE_EXPORT_BEGIN
Definition: core.h:224
FMT_CONSTEXPR auto parse_precision(const Char *begin, const Char *end, Handler &&handler) -> const Char *
Definition: core.h:2484
constexpr auto count() -> size_t
Definition: core.h:1204
#define FMT_CONSTEXPR
Definition: core.h:106
FMT_CONSTEXPR auto parse_width(const Char *begin, const Char *end, Handler &&handler) -> const Char *
Definition: core.h:2450
type
Definition: core.h:575
#define FMT_BEGIN_NAMESPACE
Definition: core.h:214
#define FMT_BEGIN_DETAIL_NAMESPACE
Definition: core.h:226
FMT_BEGIN_DETAIL_NAMESPACE FMT_CONSTEXPR void ignore_unused(const T &...)
Definition: core.h:343
constexpr auto is_utf8() -> bool
Definition: core.h:415
#define FMT_ENABLE_IF(...)
Definition: core.h:335
void void_t
Definition: core.h:1682
FMT_CONSTEXPR auto to_unsigned(Int value) -> typename std::make_unsigned< Int >::type
Definition: core.h:407
#define FMT_NORETURN
Definition: core.h:163
typename std::conditional< B, T, F >::type conditional_t
Definition: core.h:300
#define FMT_END_NAMESPACE
Definition: core.h:217
#define FMT_MODULE_EXPORT_END
Definition: core.h:225
FMT_CONSTEXPR auto parse_align(const Char *begin, const Char *end, Handler &&handler) -> const Char *
Definition: core.h:2367
constexpr common_return_t< T1, T2 > fmod(const T1 x, const T2 y) noexcept
Compile-time remainder of division function.
Definition: fmod.hpp:64
constexpr long long pow10(std::uint32_t n)
Definition: chrono.h:1483
To fmt_safe_duration_cast(std::chrono::duration< FromRep, FromPeriod > from)
Definition: chrono.h:1435
const char * tm_mon_full_name(int mon)
Definition: chrono.h:924
constexpr std::chrono::duration< Rep, Period > abs(std::chrono::duration< Rep, Period > d)
Definition: chrono.h:1489
FMT_CONSTEXPR const Char * parse_chrono_format(const Char *begin, const Char *end, Handler &&handler)
Definition: chrono.h:604
numeric_system
Definition: chrono.h:596
OutputIt copy_unit(string_view unit, OutputIt out, Char)
Definition: chrono.h:1524
OutputIt format_duration_value(OutputIt out, Rep val, int)
Definition: chrono.h:1509
FMT_MODULE_EXPORT_BEGIN std::tm localtime(std::time_t time)
Converts given time since epoch as std::time_t value into calendar time, expressed in local time.
Definition: chrono.h:451
std::chrono::duration< Rep, std::milli > get_milliseconds(std::chrono::duration< Rep, Period > d)
Definition: chrono.h:1445
OutputIt format_duration_unit(OutputIt out)
Definition: chrono.h:1537
const char * tm_wday_full_name(int wday)
Definition: chrono.h:912
std::tm gmtime(std::time_t time)
Converts given time since epoch as std::time_t value into calendar time, expressed in Coordinated Uni...
Definition: chrono.h:497
bool isfinite(T)
Definition: chrono.h:1392
const char * tm_wday_short_name(int wday)
Definition: chrono.h:918
const char * tm_mon_short_name(int mon)
Definition: chrono.h:930
FMT_CONSTEXPR const char * get_units()
Definition: chrono.h:573
T mod(T x, int y)
Definition: chrono.h:1413
Int to_nonnegative_int(T value, Int upper)
Definition: chrono.h:1398
FMT_BEGIN_DETAIL_NAMESPACE void write_digit2_separated(char *buf, unsigned a, unsigned b, unsigned c, char sep)
Definition: chrono.h:542
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:3433
constexpr bool isnan(T value)
Definition: format.h:2501
FMT_CONSTEXPR20 auto count_digits(uint64_t n) -> int
Definition: format.h:1101
FMT_CONSTEXPR20 FMT_INLINE void copy2(Char *dst, const char *src)
Definition: format.h:1204
std::integral_constant< bool, std::numeric_limits< T >::is_signed||std::is_same< T, int128_opt >::value > is_signed
Definition: format.h:1004
constexpr auto is_negative(T value) -> bool
Definition: format.h:1009
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:1031
constexpr const char * digits2(size_t value)
Definition: format.h:1041
FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n, const fill_t< Char > &fill) -> OutputIt
Definition: format.h:1645
basic_memory_buffer< char > memory_buffer
Definition: format.h:942
#define FMT_THROW(x)
Definition: format.h:95
auto ptr(T p) -> const void *
\rst Converts p to const void* for pointer formatting.
Definition: format.h:3823
constexpr common_t< T1, T2 > max(const T1 x, const T2 y) noexcept
Compile-time pairwise maximum function.
Definition: max.hpp:35
constexpr common_t< T1, T2 > min(const T1 x, const T2 y) noexcept
Compile-time pairwise minimum function.
Definition: min.hpp:35
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bool() isinf(const bfloat16 &a)
Definition: BFloat16.h:476
const Scalar & y
Definition: MathFunctions.h:821
::uint32_t uint32_t
Definition: Meta.h:56
static EIGEN_DEPRECATED const end_t end
Definition: IndexedViewHelper.h:181
Definition: core.h:2080
Definition: format-inl.h:32
null gmtime_s(...)
Definition: chrono.h:308
auto write(OutputIt out, const std::tm &time, const std::locale &loc, char format, char modifier=0) -> OutputIt
Definition: chrono.h:426
auto is_big_endian() -> bool
Definition: format.h:307
auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale &loc) -> OutputIt
Definition: chrono.h:343
void do_write(buffer< Char > &buf, const std::tm &time, const std::locale &loc, char format, char modifier)
Definition: chrono.h:413
null localtime_r FMT_NOMACRO(...)
Definition: chrono.h:305
null gmtime_r(...)
Definition: chrono.h:307
OutputIterator copy(const RangeT &range, OutputIterator out)
Definition: ranges.h:26
FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T &value) -> OutputIt
Definition: format.h:560
const std::locale & get_classic_locale()
Definition: chrono.h:310
null localtime_s(...)
Definition: chrono.h:306
auto write_tm_str(OutputIt out, string_view sv, const std::locale &loc) -> OutputIt
Definition: chrono.h:398
void write_codecvt(codecvt_result< CodeUnit > &out, string_view in_buf, const std::locale &loc)
Definition: chrono.h:324
Definition: format.h:2563
result
Definition: format.h:2564
typename std::common_type< T... >::type common_t
Definition: gcem_options.hpp:80
Definition: chrono.h:51
To safe_duration_cast(std::chrono::duration< FromRep, FromPeriod > from, int &ec)
safe duration cast between integral durations
Definition: chrono.h:173
FMT_CONSTEXPR To safe_float_conversion(const From from, int &ec)
converts From to To if possible, otherwise ec is set.
Definition: chrono.h:139
FMT_CONSTEXPR To lossless_integral_conversion(const From from, int &ec)
converts From to To, without loss.
Definition: chrono.h:57
Definition: BFloat16.h:88
static constexpr const unit_t< compound_unit< energy::joule, time::seconds > > h(6.626070040e-34)
Planck constant.
static constexpr const unit_t< compound_unit< charge::coulomb, inverse< substance::mol > > > F(N_A *e)
Faraday constant.
static constexpr const velocity::meters_per_second_t c(299792458.0)
Speed of light in vacuum.
b
Definition: data.h:44
Definition: core.h:2141
Definition: chrono.h:1374
FMT_CONSTEXPR void on_duration_unit()
Definition: chrono.h:1388
FMT_CONSTEXPR void on_am_pm()
Definition: chrono.h:1386
FMT_CONSTEXPR void on_24_hour_time()
Definition: chrono.h:1384
FMT_CONSTEXPR void on_iso_time()
Definition: chrono.h:1385
FMT_CONSTEXPR void on_duration_value()
Definition: chrono.h:1387
FMT_CONSTEXPR void on_minute(numeric_system)
Definition: chrono.h:1381
FMT_NORETURN void unsupported()
Definition: chrono.h:1375
FMT_CONSTEXPR void on_12_hour(numeric_system)
Definition: chrono.h:1380
FMT_CONSTEXPR void on_24_hour(numeric_system)
Definition: chrono.h:1379
FMT_CONSTEXPR void on_second(numeric_system)
Definition: chrono.h:1382
FMT_CONSTEXPR void on_12_hour_time()
Definition: chrono.h:1383
FMT_CONSTEXPR void on_text(const Char *, const Char *)
Definition: chrono.h:1378
Definition: chrono.h:1573
void on_tz_name()
Definition: chrono.h:1727
void on_full_month()
Definition: chrono.h:1720
void on_us_date()
Definition: chrono.h:1724
tm_writer< OutputIt, char_type > tm_writer_type
Definition: chrono.h:1589
void on_datetime(numeric_system)
Definition: chrono.h:1721
typename FormatContext::char_type char_type
Definition: chrono.h:1588
void on_minute(numeric_system ns)
Definition: chrono.h:1760
void format_tm(const tm &time, Callback cb, Args... args)
Definition: chrono.h:1702
void write_pinf()
Definition: chrono.h:1698
void on_am_pm()
Definition: chrono.h:1820
void on_utc_offset()
Definition: chrono.h:1726
void on_duration_value()
Definition: chrono.h:1825
void on_24_hour_time()
Definition: chrono.h:1801
void on_day_of_month(numeric_system)
Definition: chrono.h:1739
void on_12_hour_time()
Definition: chrono.h:1796
OutputIt out
Definition: chrono.h:1575
void on_second(numeric_system ns)
Definition: chrono.h:1769
void on_iso_week_of_year(numeric_system)
Definition: chrono.h:1737
void on_text(const char_type *begin, const char_type *end)
Definition: chrono.h:1710
void on_abbr_weekday()
Definition: chrono.h:1715
void on_dec0_weekday(numeric_system)
Definition: chrono.h:1717
void on_loc_date(numeric_system)
Definition: chrono.h:1722
void on_12_hour(numeric_system ns)
Definition: chrono.h:1751
bool negative
Definition: chrono.h:1586
Rep second() const
Definition: chrono.h:1640
std::chrono::duration< rep > seconds
Definition: chrono.h:1583
rep val
Definition: chrono.h:1582
void on_abbr_month()
Definition: chrono.h:1719
bool handle_nan_inf()
Definition: chrono.h:1615
void write(Rep value, int width)
Definition: chrono.h:1657
void on_year(numeric_system)
Definition: chrono.h:1728
std::chrono::duration< rep, std::milli > milliseconds
Definition: chrono.h:1585
void on_day_of_year()
Definition: chrono.h:1738
void on_offset_year()
Definition: chrono.h:1730
FormatContext & context
Definition: chrono.h:1574
void write_fractional_seconds(Duration d)
Definition: chrono.h:1667
Rep minute() const
Definition: chrono.h:1639
seconds s
Definition: chrono.h:1584
void on_short_year(numeric_system)
Definition: chrono.h:1729
int precision
Definition: chrono.h:1576
void write_ninf()
Definition: chrono.h:1699
chrono_formatter(FormatContext &ctx, OutputIt o, std::chrono::duration< Rep, Period > d)
Definition: chrono.h:1591
void on_duration_unit()
Definition: chrono.h:1831
std::tm time() const
Definition: chrono.h:1642
bool localized
Definition: chrono.h:1577
Rep hour() const
Definition: chrono.h:1632
void write_sign()
Definition: chrono.h:1650
void on_full_weekday()
Definition: chrono.h:1716
void on_dec_month(numeric_system)
Definition: chrono.h:1734
Rep hour12() const
Definition: chrono.h:1634
void on_loc_time(numeric_system)
Definition: chrono.h:1723
void on_iso_date()
Definition: chrono.h:1725
void on_iso_week_based_year()
Definition: chrono.h:1732
void on_iso_week_based_short_year()
Definition: chrono.h:1733
void on_24_hour(numeric_system ns)
Definition: chrono.h:1742
void on_day_of_month_space(numeric_system)
Definition: chrono.h:1740
conditional_t< std::is_integral< Rep >::value &&sizeof(Rep)< sizeof(int), unsigned, typename make_unsigned_or_unchanged< Rep >::type > rep
Definition: chrono.h:1581
void on_dec1_weekday(numeric_system)
Definition: chrono.h:1718
void on_century(numeric_system)
Definition: chrono.h:1731
void on_dec0_week_of_year(numeric_system)
Definition: chrono.h:1735
void write_nan()
Definition: chrono.h:1697
void on_iso_time()
Definition: chrono.h:1813
void on_dec1_week_of_year(numeric_system)
Definition: chrono.h:1736
Definition: chrono.h:1471
Definition: chrono.h:315
static constexpr const size_t max_size
Definition: chrono.h:316
CodeUnit * end
Definition: chrono.h:318
CodeUnit buf[max_size]
Definition: chrono.h:317
Definition: chrono.h:304
Definition: format.h:252
FMT_CONSTEXPR auto parse(basic_format_parse_context< Char > &ctx) -> decltype(ctx.begin())
Definition: chrono.h:1964
auto format(const duration &d, FormatContext &ctx) const -> decltype(ctx.out())
Definition: chrono.h:1973
auto format(std::chrono::time_point< std::chrono::system_clock > val, FormatContext &ctx) const -> decltype(ctx.out())
Definition: chrono.h:2011
auto format(const std::tm &tm, FormatContext &ctx) const -> decltype(ctx.out())
Definition: chrono.h:2051
FMT_CONSTEXPR auto parse(basic_format_parse_context< Char > &ctx) -> decltype(ctx.begin())
Definition: chrono.h:2037
FMT_CONSTEXPR auto do_parse(It begin, It end) -> It
Definition: chrono.h:2028
FMT_CONSTEXPR auto parse(basic_format_parse_context< Char > &ctx) -> decltype(ctx.begin())
Definition: chrono.h:1862
auto format(weekday wd, FormatContext &ctx) const -> decltype(ctx.out())
Definition: chrono.h:1873
Definition: core.h:791
Definition: chrono.h:939
Definition: chrono.h:945
typename std::make_unsigned< T >::type type
Definition: chrono.h:1429
Definition: chrono.h:1424
T type
Definition: chrono.h:1425
Definition: chrono.h:829
FMT_CONSTEXPR void on_datetime(numeric_system)
Definition: chrono.h:856
FMT_CONSTEXPR void on_offset_year()
Definition: chrono.h:835
FMT_CONSTEXPR void on_full_month()
Definition: chrono.h:844
FMT_CONSTEXPR void on_day_of_month_space(numeric_system)
Definition: chrono.h:851
FMT_CONSTEXPR void on_second(numeric_system)
Definition: chrono.h:855
FMT_CONSTEXPR void on_abbr_month()
Definition: chrono.h:843
FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system)
Definition: chrono.h:847
FMT_CONSTEXPR void on_short_year(numeric_system)
Definition: chrono.h:834
FMT_CONSTEXPR void on_us_date()
Definition: chrono.h:859
FMT_CONSTEXPR void on_am_pm()
Definition: chrono.h:864
FMT_CONSTEXPR void on_dec0_weekday(numeric_system)
Definition: chrono.h:841
FMT_CONSTEXPR void on_abbr_weekday()
Definition: chrono.h:839
FMT_CONSTEXPR void on_utc_offset()
Definition: chrono.h:867
FMT_CONSTEXPR void on_iso_date()
Definition: chrono.h:860
FMT_CONSTEXPR void on_day_of_month(numeric_system)
Definition: chrono.h:850
FMT_CONSTEXPR void on_duration_unit()
Definition: chrono.h:866
FMT_CONSTEXPR void on_24_hour(numeric_system)
Definition: chrono.h:852
FMT_CONSTEXPR void on_dec_month(numeric_system)
Definition: chrono.h:845
FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system)
Definition: chrono.h:846
FMT_CONSTEXPR void on_iso_week_based_year()
Definition: chrono.h:837
FMT_CONSTEXPR void on_12_hour(numeric_system)
Definition: chrono.h:853
FMT_CONSTEXPR void on_full_weekday()
Definition: chrono.h:840
FMT_CONSTEXPR void on_day_of_year()
Definition: chrono.h:849
FMT_CONSTEXPR void unsupported()
Definition: chrono.h:830
FMT_CONSTEXPR void on_duration_value()
Definition: chrono.h:865
FMT_CONSTEXPR void on_12_hour_time()
Definition: chrono.h:861
FMT_CONSTEXPR void on_loc_date(numeric_system)
Definition: chrono.h:857
FMT_CONSTEXPR void on_iso_time()
Definition: chrono.h:863
FMT_CONSTEXPR void on_dec1_weekday(numeric_system)
Definition: chrono.h:842
FMT_CONSTEXPR void on_century(numeric_system)
Definition: chrono.h:836
FMT_CONSTEXPR void on_24_hour_time()
Definition: chrono.h:862
FMT_CONSTEXPR void on_year(numeric_system)
Definition: chrono.h:833
FMT_CONSTEXPR void on_loc_time(numeric_system)
Definition: chrono.h:858
FMT_CONSTEXPR void on_iso_week_based_short_year()
Definition: chrono.h:838
FMT_CONSTEXPR void on_minute(numeric_system)
Definition: chrono.h:854
FMT_CONSTEXPR void on_tz_name()
Definition: chrono.h:868
FMT_CONSTEXPR void on_iso_week_of_year(numeric_system)
Definition: chrono.h:848
Definition: chrono.h:871
FMT_CONSTEXPR void on_12_hour(numeric_system)
Definition: chrono.h:896
FMT_CONSTEXPR void on_abbr_weekday()
Definition: chrono.h:882
FMT_CONSTEXPR void on_12_hour_time()
Definition: chrono.h:904
FMT_CONSTEXPR void on_utc_offset()
Definition: chrono.h:908
FMT_CONSTEXPR void on_offset_year()
Definition: chrono.h:878
FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system)
Definition: chrono.h:890
FMT_CONSTEXPR void on_short_year(numeric_system)
Definition: chrono.h:877
FMT_CONSTEXPR void on_24_hour_time()
Definition: chrono.h:905
FMT_CONSTEXPR void on_24_hour(numeric_system)
Definition: chrono.h:895
FMT_CONSTEXPR void on_minute(numeric_system)
Definition: chrono.h:897
FMT_CONSTEXPR void on_text(const Char *, const Char *)
Definition: chrono.h:875
FMT_CONSTEXPR void on_am_pm()
Definition: chrono.h:907
FMT_CONSTEXPR void on_datetime(numeric_system)
Definition: chrono.h:899
FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system)
Definition: chrono.h:889
FMT_CONSTEXPR void on_us_date()
Definition: chrono.h:902
FMT_CONSTEXPR void on_loc_time(numeric_system)
Definition: chrono.h:901
FMT_CONSTEXPR void on_iso_week_based_year()
Definition: chrono.h:880
FMT_CONSTEXPR void on_abbr_month()
Definition: chrono.h:886
FMT_CONSTEXPR void on_century(numeric_system)
Definition: chrono.h:879
FMT_CONSTEXPR void on_loc_date(numeric_system)
Definition: chrono.h:900
FMT_CONSTEXPR void on_dec_month(numeric_system)
Definition: chrono.h:888
FMT_CONSTEXPR void on_iso_date()
Definition: chrono.h:903
FMT_CONSTEXPR void on_iso_time()
Definition: chrono.h:906
FMT_CONSTEXPR void on_iso_week_of_year(numeric_system)
Definition: chrono.h:891
FMT_CONSTEXPR void on_second(numeric_system)
Definition: chrono.h:898
FMT_CONSTEXPR void on_day_of_month(numeric_system)
Definition: chrono.h:893
FMT_CONSTEXPR void on_iso_week_based_short_year()
Definition: chrono.h:881
FMT_CONSTEXPR void on_day_of_year()
Definition: chrono.h:892
FMT_CONSTEXPR void on_full_weekday()
Definition: chrono.h:883
FMT_CONSTEXPR void on_full_month()
Definition: chrono.h:887
FMT_NORETURN void unsupported()
Definition: chrono.h:872
FMT_CONSTEXPR void on_dec0_weekday(numeric_system)
Definition: chrono.h:884
FMT_CONSTEXPR void on_dec1_weekday(numeric_system)
Definition: chrono.h:885
FMT_CONSTEXPR void on_day_of_month_space(numeric_system)
Definition: chrono.h:894
FMT_CONSTEXPR void on_tz_name()
Definition: chrono.h:909
FMT_CONSTEXPR void on_year(numeric_system)
Definition: chrono.h:876
auto format(wformat_string< T... > fmt, T &&... args) -> std::wstring
Definition: xchar.h:87
auto format_to(OutputIt out, const S &fmt, Args &&... args) -> OutputIt
Definition: xchar.h:136
auto runtime(wstring_view s) -> basic_runtime< wchar_t >
Definition: xchar.h:36