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