Where Online Learning is simpler!
The C and C++ Include Header Files
/usr/include/c++/13/bits/chrono_io.h
$ cat -n /usr/include/c++/13/bits/chrono_io.h 1 //
Formatting -*- C++ -*- 2 3 // Copyright The GNU Toolchain Authors. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 //
. 24 25 /** @file include/bits/chrono_io.h 26 * This is an internal header file, included by other library headers. 27 * Do not attempt to use it directly. @headername{chrono} 28 */ 29 30 #ifndef _GLIBCXX_CHRONO_IO_H 31 #define _GLIBCXX_CHRONO_IO_H 1 32 33 #pragma GCC system_header 34 35 #if __cplusplus >= 202002L 36 37 #include
// ostringstream 38 #include
// setw, setfill 39 #include
40 41 #include
42 43 namespace std _GLIBCXX_VISIBILITY(default) 44 { 45 _GLIBCXX_BEGIN_NAMESPACE_VERSION 46 47 namespace chrono 48 { 49 /// @addtogroup chrono 50 /// @{ 51 52 /// @cond undocumented 53 namespace __detail 54 { 55 // STATICALLY-WIDEN, see C++20 [time.general] 56 // It doesn't matter for format strings (which can only be char or wchar_t) 57 // but this returns the narrow string for anything that isn't wchar_t. This 58 // is done because const char* can be inserted into any ostream type, and 59 // will be widened at runtime if necessary. 60 template
61 consteval auto 62 _Widen(const char* __narrow, const wchar_t* __wide) 63 { 64 if constexpr (is_same_v<_CharT, wchar_t>) 65 return __wide; 66 else 67 return __narrow; 68 } 69 #define _GLIBCXX_WIDEN_(C, S) ::std::chrono::__detail::_Widen
(S, L##S) 70 #define _GLIBCXX_WIDEN(S) _GLIBCXX_WIDEN_(_CharT, S) 71 72 template
73 constexpr basic_string_view<_CharT> 74 __units_suffix() noexcept 75 { 76 // The standard say these are all narrow strings, which would need to 77 // be widened at run-time when inserted into a wide stream. We use 78 // STATICALLY-WIDEN to widen at compile-time. 79 #define _GLIBCXX_UNITS_SUFFIX(period, suffix) \ 80 if constexpr (is_same_v<_Period, period>) \ 81 return _GLIBCXX_WIDEN(suffix); \ 82 else 83 84 _GLIBCXX_UNITS_SUFFIX(atto, "as") 85 _GLIBCXX_UNITS_SUFFIX(femto, "fs") 86 _GLIBCXX_UNITS_SUFFIX(pico, "ps") 87 _GLIBCXX_UNITS_SUFFIX(nano, "ns") 88 _GLIBCXX_UNITS_SUFFIX(milli, "ms") 89 #if _GLIBCXX_USE_ALT_MICROSECONDS_SUFFIX 90 // Deciding this at compile-time is wrong, maybe use nl_langinfo(CODESET) 91 // to check runtime environment and return u8"\u00b5s", "\xb5s", or "us". 92 _GLIBCXX_UNITS_SUFFIX(micro, "\u00b5s") 93 #else 94 _GLIBCXX_UNITS_SUFFIX(micro, "us") 95 #endif 96 _GLIBCXX_UNITS_SUFFIX(centi, "cs") 97 _GLIBCXX_UNITS_SUFFIX(deci, "ds") 98 _GLIBCXX_UNITS_SUFFIX(ratio<1>, "s") 99 _GLIBCXX_UNITS_SUFFIX(deca, "das") 100 _GLIBCXX_UNITS_SUFFIX(hecto, "hs") 101 _GLIBCXX_UNITS_SUFFIX(kilo, "ks") 102 _GLIBCXX_UNITS_SUFFIX(mega, "Ms") 103 _GLIBCXX_UNITS_SUFFIX(giga, "Gs") 104 _GLIBCXX_UNITS_SUFFIX(tera, "Ts") 105 _GLIBCXX_UNITS_SUFFIX(tera, "Ts") 106 _GLIBCXX_UNITS_SUFFIX(peta, "Ps") 107 _GLIBCXX_UNITS_SUFFIX(exa, "Es") 108 _GLIBCXX_UNITS_SUFFIX(ratio<60>, "min") 109 _GLIBCXX_UNITS_SUFFIX(ratio<3600>, "h") 110 _GLIBCXX_UNITS_SUFFIX(ratio<86400>, "d") 111 #undef _GLIBCXX_UNITS_SUFFIX 112 return {}; 113 } 114 115 template
116 inline _Out 117 __fmt_units_suffix(_Out __out) noexcept 118 { 119 if (auto __s = __detail::__units_suffix<_Period, _CharT>(); __s.size()) 120 return __format::__write(std::move(__out), __s); 121 else if constexpr (_Period::den == 1) 122 return std::format_to(std::move(__out), _GLIBCXX_WIDEN("[{}]s"), 123 (uintmax_t)_Period::num); 124 else 125 return std::format_to(std::move(__out), _GLIBCXX_WIDEN("[{}/{}]s"), 126 (uintmax_t)_Period::num, 127 (uintmax_t)_Period::den); 128 } 129 } // namespace __detail 130 /// @endcond 131 132 /** Write a `chrono::duration` to an ostream. 133 * 134 * @since C++20 135 */ 136 template
138 inline basic_ostream<_CharT, _Traits>& 139 operator<<(std::basic_ostream<_CharT, _Traits>& __os, 140 const duration<_Rep, _Period>& __d) 141 { 142 using _Out = ostreambuf_iterator<_CharT, _Traits>; 143 using period = typename _Period::type; 144 std::basic_ostringstream<_CharT, _Traits> __s; 145 __s.flags(__os.flags()); 146 __s.imbue(__os.getloc()); 147 __s.precision(__os.precision()); 148 __s << __d.count(); 149 __detail::__fmt_units_suffix
(_Out(__s)); 150 __os << std::move(__s).str(); 151 return __os; 152 } 153 154 /// @cond undocumented 155 namespace __detail 156 { 157 // An unspecified type returned by `chrono::local_time_format`. 158 template
159 struct __local_time_fmt 160 { 161 local_time<_Duration> _M_time; 162 const string* _M_abbrev; 163 const seconds* _M_offset_sec; 164 }; 165 166 struct __local_fmt_t; 167 } 168 /// @endcond 169 170 /** Return an object that asssociates timezone info with a local time. 171 * 172 * A `chrono::local_time` object has no timezone associated with it. This 173 * function creates an object that allows formatting a `local_time` as 174 * though it refers to a timezone with the given abbreviated name and 175 * offset from UTC. 176 * 177 * @since C++20 178 */ 179 template
180 inline __detail::__local_time_fmt<_Duration> 181 local_time_format(local_time<_Duration> __time, 182 const string* __abbrev = nullptr, 183 const seconds* __offset_sec = nullptr) 184 { return {__time, __abbrev, __offset_sec}; } 185 186 /// @} 187 } // namespace chrono 188 189 /// @cond undocumented 190 namespace __format 191 { 192 [[noreturn,__gnu__::__always_inline__]] 193 inline void 194 __no_timezone_available() 195 { __throw_format_error("format error: no timezone available for %Z or %z"); } 196 197 [[noreturn,__gnu__::__always_inline__]] 198 inline void 199 __not_valid_for_duration() 200 { __throw_format_error("format error: chrono-format-spec not valid for " 201 "chrono::duration"); } 202 203 [[noreturn,__gnu__::__always_inline__]] 204 inline void 205 __invalid_chrono_spec() 206 { __throw_format_error("format error: chrono-format-spec not valid for " 207 "argument type"); } 208 209 template
210 struct _ChronoSpec : _Spec<_CharT> 211 { 212 basic_string_view<_CharT> _M_chrono_specs; 213 }; 214 215 // Represents the information provided by a chrono type. 216 // e.g. month_weekday has month and weekday but no year or time of day, 217 // hh_mm_ss has time of day but no date, sys_time is time_point+timezone. 218 enum _ChronoParts { 219 _Year = 1, _Month = 2, _Day = 4, _Weekday = 8, _TimeOfDay = 16, 220 _TimeZone = 32, 221 _Date = _Year | _Month | _Day | _Weekday, 222 _DateTime = _Date | _TimeOfDay, 223 _ZonedDateTime = _DateTime | _TimeZone, 224 _Duration = 128 // special case 225 }; 226 227 constexpr _ChronoParts 228 operator|(_ChronoParts __x, _ChronoParts __y) 229 { return static_cast<_ChronoParts>((int)__x | (int)__y); } 230 231 // TODO rename this to chrono::__formatter? or chrono::__detail::__formatter? 232 template
233 struct __formatter_chrono 234 { 235 using __string_view = basic_string_view<_CharT>; 236 using __string = basic_string<_CharT>; 237 238 template
239 constexpr typename _ParseContext::iterator 240 _M_parse(_ParseContext& __pc, _ChronoParts __parts) 241 { 242 auto __first = __pc.begin(); 243 auto __last = __pc.end(); 244 245 _ChronoSpec<_CharT> __spec{}; 246 247 auto __finalize = [this, &__spec] { 248 _M_spec = __spec; 249 }; 250 251 auto __finished = [&] { 252 if (__first == __last || *__first == '}') 253 { 254 __finalize(); 255 return true; 256 } 257 return false; 258 }; 259 260 if (__finished()) 261 return __first; 262 263 __first = __spec._M_parse_fill_and_align(__first, __last); 264 if (__finished()) 265 return __first; 266 267 __first = __spec._M_parse_width(__first, __last, __pc); 268 if (__finished()) 269 return __first; 270 271 if (__parts & _ChronoParts::_Duration) 272 { 273 __first = __spec._M_parse_precision(__first, __last, __pc); 274 if (__finished()) 275 return __first; 276 } 277 278 __first = __spec._M_parse_locale(__first, __last); 279 if (__finished()) 280 return __first; 281 282 // Everything up to the end of the string or the first '}' is a 283 // chrono-specs string. Check it is valid. 284 { 285 __string_view __str(__first, __last - __first); 286 auto __end = __str.find('}'); 287 if (__end != __str.npos) 288 { 289 __str.remove_suffix(__str.length() - __end); 290 __last = __first + __end; 291 } 292 if (__str.find('{') != __str.npos) 293 __throw_format_error("chrono format error: '{' in chrono-specs"); 294 } 295 296 // Parse chrono-specs in [first,last), checking each conversion-spec 297 // against __parts (so fail for %Y if no year in parts). 298 // Save range in __spec._M_chrono_specs. 299 300 const auto __chrono_specs = __first++; // Skip leading '%' 301 if (*__chrono_specs != '%') 302 __throw_format_error("chrono format error: no '%' at start of " 303 "chrono-specs"); 304 305 _CharT __mod{}; 306 bool __conv = true; 307 int __needed = 0; 308 309 while (__first != __last) 310 { 311 enum _Mods { _Mod_none, _Mod_E, _Mod_O, _Mod_E_O }; 312 _Mods __allowed_mods = _Mod_none; 313 314 _CharT __c = *__first++; 315 switch (__c) 316 { 317 case 'a': 318 case 'A': 319 __needed = _Weekday; 320 break; 321 case 'b': 322 case 'h': 323 case 'B': 324 __needed = _Month; 325 break; 326 case 'c': 327 __needed = _DateTime; 328 __allowed_mods = _Mod_E; 329 break; 330 case 'C': 331 __needed = _Year; 332 __allowed_mods = _Mod_E; 333 break; 334 case 'd': 335 case 'e': 336 __needed = _Day; 337 __allowed_mods = _Mod_O; 338 break; 339 case 'D': 340 case 'F': 341 __needed = _Date; 342 break; 343 case 'g': 344 case 'G': 345 __needed = _Date; 346 break; 347 case 'H': 348 case 'I': 349 __needed = _TimeOfDay; 350 __allowed_mods = _Mod_O; 351 break; 352 case 'j': 353 if (!(__parts & _Duration)) 354 __needed = _Date; 355 break; 356 case 'm': 357 __needed = _Month; 358 __allowed_mods = _Mod_O; 359 break; 360 case 'M': 361 __needed = _TimeOfDay; 362 __allowed_mods = _Mod_O; 363 break; 364 case 'p': 365 case 'r': 366 case 'R': 367 case 'T': 368 __needed = _TimeOfDay; 369 break; 370 case 'q': 371 case 'Q': 372 __needed = _Duration; 373 break; 374 case 'S': 375 __needed = _TimeOfDay; 376 __allowed_mods = _Mod_O; 377 break; 378 case 'u': 379 case 'w': 380 __needed = _Weekday; 381 __allowed_mods = _Mod_O; 382 break; 383 case 'U': 384 case 'V': 385 case 'W': 386 __needed = _Date; 387 __allowed_mods = _Mod_O; 388 break; 389 case 'x': 390 __needed = _Date; 391 __allowed_mods = _Mod_E; 392 break; 393 case 'X': 394 __needed = _TimeOfDay; 395 __allowed_mods = _Mod_E; 396 break; 397 case 'y': 398 __needed = _Year; 399 __allowed_mods = _Mod_E_O; 400 break; 401 case 'Y': 402 __needed = _Year; 403 __allowed_mods = _Mod_E; 404 break; 405 case 'z': 406 __needed = _TimeZone; 407 __allowed_mods = _Mod_E_O; 408 break; 409 case 'Z': 410 __needed = _TimeZone; 411 break; 412 case 'n': 413 case 't': 414 case '%': 415 break; 416 case 'O': 417 case 'E': 418 if (__mod) [[unlikely]] 419 { 420 __allowed_mods = _Mod_none; 421 break; 422 } 423 __mod = __c; 424 continue; 425 default: 426 __throw_format_error("chrono format error: invalid " 427 " specifier in chrono-specs"); 428 } 429 430 if ((__mod == 'E' && !(__allowed_mods & _Mod_E)) 431 || (__mod == 'O' && !(__allowed_mods & _Mod_O))) 432 __throw_format_error("chrono format error: invalid " 433 " modifier in chrono-specs"); 434 __mod = _CharT(); 435 436 if ((__parts & __needed) != __needed) 437 __throw_format_error("chrono format error: format argument " 438 "does not contain the information " 439 "required by the chrono-specs"); 440 441 // Scan for next '%', ignoring literal-chars before it. 442 size_t __pos = __string_view(__first, __last - __first).find('%'); 443 if (__pos == 0) 444 ++__first; 445 else 446 { 447 if (__pos == __string_view::npos) 448 { 449 __first = __last; 450 __conv = false; 451 } 452 else 453 __first += __pos + 1; 454 } 455 } 456 457 // Check for a '%' conversion-spec without a type. 458 if (__conv || __mod != _CharT()) 459 __throw_format_error("chrono format error: unescaped '%' in " 460 "chrono-specs"); 461 462 _M_spec = __spec; 463 _M_spec._M_chrono_specs 464 = __string_view(__chrono_specs, __first - __chrono_specs); 465 466 return __first; 467 } 468 469 // TODO this function template is instantiated for every different _Tp. 470 // Consider creating a polymorphic interface for calendar types so 471 // that we instantiate fewer different specializations. Similar to 472 // _Sink_iter for std::format. Replace each _S_year, _S_day etc. with 473 // member functions of that type. 474 template
475 typename _FormatContext::iterator 476 _M_format(const _Tp& __t, _FormatContext& __fc, 477 bool __is_neg = false) const 478 { 479 auto __first = _M_spec._M_chrono_specs.begin(); 480 const auto __last = _M_spec._M_chrono_specs.end(); 481 if (__first == __last) 482 return _M_format_to_ostream(__t, __fc, __is_neg); 483 484 _Sink_iter<_CharT> __out; 485 __format::_Str_sink<_CharT> __sink; 486 bool __write_direct = false; 487 if constexpr (is_same_v
>) 489 { 490 if (_M_spec._M_width_kind == __format::_WP_none) 491 { 492 __out = __fc.out(); 493 __write_direct = true; 494 } 495 else 496 __out = __sink.out(); 497 } 498 else 499 __out = __sink.out(); 500 501 // formatter
passes the correct value of __is_neg 502 // for durations but for hh_mm_ss we decide it here. 503 if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>) 504 __is_neg = __t.is_negative(); 505 506 auto __print_sign = [&__is_neg, &__out] { 507 if constexpr (chrono::__is_duration_v<_Tp> 508 || __is_specialization_of<_Tp, chrono::hh_mm_ss>) 509 if (__is_neg) 510 { 511 *__out++ = _S_plus_minus[1]; 512 __is_neg = false; 513 } 514 return std::move(__out); 515 }; 516 517 // Characters to output for "%n", "%t" and "%%" specifiers. 518 constexpr const _CharT* __literals = _GLIBCXX_WIDEN("\n\t%"); 519 520 ++__first; // Skip leading '%' at start of chrono-specs. 521 522 _CharT __mod{}; 523 do 524 { 525 _CharT __c = *__first++; 526 switch (__c) 527 { 528 case 'a': 529 case 'A': 530 __out = _M_a_A(__t, std::move(__out), __fc, __c == 'A'); 531 break; 532 case 'b': 533 case 'h': 534 case 'B': 535 __out = _M_b_B(__t, std::move(__out), __fc, __c == 'B'); 536 break; 537 case 'c': 538 __out = _M_c(__t, std::move(__out), __fc, __mod == 'E'); 539 break; 540 case 'C': 541 case 'y': 542 case 'Y': 543 __out = _M_C_y_Y(__t, std::move(__out), __fc, __c, __mod); 544 break; 545 case 'd': 546 case 'e': 547 __out = _M_d_e(__t, std::move(__out), __fc, __c, __mod == 'O'); 548 break; 549 case 'D': 550 __out = _M_D(__t, std::move(__out), __fc); 551 break; 552 case 'F': 553 __out = _M_F(__t, std::move(__out), __fc); 554 break; 555 case 'g': 556 case 'G': 557 __out = _M_g_G(__t, std::move(__out), __fc, __c == 'G'); 558 break; 559 case 'H': 560 case 'I': 561 __out = _M_H_I(__t, __print_sign(), __fc, __c, __mod == 'O'); 562 break; 563 case 'j': 564 __out = _M_j(__t, __print_sign(), __fc); 565 break; 566 case 'm': 567 __out = _M_m(__t, std::move(__out), __fc, __mod == 'O'); 568 break; 569 case 'M': 570 __out = _M_M(__t, __print_sign(), __fc, __mod == 'O'); 571 break; 572 case 'p': 573 __out = _M_p(__t, std::move(__out), __fc); 574 break; 575 case 'q': 576 __out = _M_q(__t, std::move(__out), __fc); 577 break; 578 case 'Q': 579 // %Q The duration's numeric value. 580 if constexpr (chrono::__is_duration_v<_Tp>) 581 __out = std::format_to(__print_sign(), _S_empty_spec, 582 __t.count()); 583 else 584 __throw_format_error("chrono format error: argument is " 585 "not a duration"); 586 break; 587 case 'r': 588 __out = _M_r(__t, __print_sign(), __fc); 589 break; 590 case 'R': 591 case 'T': 592 __out = _M_R_T(__t, __print_sign(), __fc, __c == 'T'); 593 break; 594 case 'S': 595 __out = _M_S(__t, __print_sign(), __fc, __mod == 'O'); 596 break; 597 case 'u': 598 case 'w': 599 __out = _M_u_w(__t, std::move(__out), __fc, __c, __mod == 'O'); 600 break; 601 case 'U': 602 case 'V': 603 case 'W': 604 __out = _M_U_V_W(__t, std::move(__out), __fc, __c, 605 __mod == 'O'); 606 break; 607 case 'x': 608 __out = _M_x(__t, std::move(__out), __fc, __mod == 'E'); 609 break; 610 case 'X': 611 __out = _M_X(__t, __print_sign(), __fc, __mod == 'E'); 612 break; 613 case 'z': 614 __out = _M_z(__t, std::move(__out), __fc, (bool)__mod); 615 break; 616 case 'Z': 617 __out = _M_Z(__t, std::move(__out), __fc); 618 break; 619 case 'n': 620 *__out++ = __literals[0]; 621 break; 622 case 't': 623 *__out++ = __literals[1]; 624 break; 625 case '%': 626 *__out++ = __literals[2]; 627 break; 628 case 'O': 629 case 'E': 630 __mod = __c; 631 continue; 632 case '}': 633 __first = __last; 634 break; 635 } 636 __mod = _CharT(); 637 // Scan for next '%' and write out everything before it. 638 __string_view __str(__first, __last - __first); 639 size_t __pos = __str.find('%'); 640 if (__pos == 0) 641 ++__first; 642 else 643 { 644 if (__pos == __str.npos) 645 __first = __last; 646 else 647 { 648 __str.remove_suffix(__str.length() - __pos); 649 __first += __pos + 1; 650 } 651 __out = __format::__write(std::move(__out), __str); 652 } 653 } 654 while (__first != __last); 655 656 if constexpr (is_same_v
>) 658 if (__write_direct) 659 return __out; 660 661 auto __str = std::move(__sink).get(); 662 return __format::__write_padded_as_spec(__str, __str.size(), 663 __fc, _M_spec); 664 } 665 666 _ChronoSpec<_CharT> _M_spec; 667 668 private: 669 // Return the formatting locale. 670 template
671 std::locale 672 _M_locale(_FormatContext& __fc) const 673 { 674 if (!_M_spec._M_localized) 675 return std::locale::classic(); 676 else 677 return __fc.locale(); 678 } 679 680 // Format for empty chrono-specs, e.g. "{}" (C++20 [time.format] p6). 681 // TODO: consider moving body of every operator<< into this function 682 // and use std::format("{}", t) to implement those operators. That 683 // would avoid std::format("{}", t) calling operator<< which calls 684 // std::format again. 685 template
686 typename _FormatContext::iterator 687 _M_format_to_ostream(const _Tp& __t, _FormatContext& __fc, 688 bool __is_neg) const 689 { 690 using ::std::chrono::__detail::__utc_leap_second; 691 using ::std::chrono::__detail::__local_time_fmt; 692 693 if constexpr (__is_specialization_of<_Tp, __local_time_fmt>) 694 return _M_format_to_ostream(__t._M_time, __fc, false); 695 else 696 { 697 basic_ostringstream<_CharT> __os; 698 __os.imbue(_M_locale(__fc)); 699 700 if constexpr (__is_specialization_of<_Tp, __utc_leap_second>) 701 __os << __t._M_date << ' ' << __t._M_time; 702 else if constexpr (chrono::__is_time_point_v<_Tp>) 703 { 704 // Need to be careful here because not all specializations 705 // of chrono::sys_time can be written to an ostream. 706 // For the specializations of time_point that can be 707 // formatted with an empty chrono-specs, either it's a 708 // sys_time with period greater or equal to days: 709 if constexpr (is_convertible_v<_Tp, chrono::sys_days>) 710 __os << _S_date(__t); 711 else // Or it's formatted as "{:L%F %T}": 712 { 713 auto __days = chrono::floor
(__t); 714 __os << chrono::year_month_day(__days) << ' ' 715 << chrono::hh_mm_ss(__t - __days); 716 } 717 } 718 else 719 { 720 if constexpr (chrono::__is_duration_v<_Tp>) 721 if (__is_neg) [[unlikely]] 722 __os << _S_plus_minus[1]; 723 __os << __t; 724 } 725 726 auto __str = std::move(__os).str(); 727 return __format::__write_padded_as_spec(__str, __str.size(), 728 __fc, _M_spec); 729 } 730 } 731 732 static constexpr const _CharT* _S_chars 733 = _GLIBCXX_WIDEN("0123456789+-:/ {}"); 734 static constexpr const _CharT* _S_plus_minus = _S_chars + 10; 735 static constexpr _CharT _S_colon = _S_chars[12]; 736 static constexpr _CharT _S_slash = _S_chars[13]; 737 static constexpr _CharT _S_space = _S_chars[14]; 738 static constexpr const _CharT* _S_empty_spec = _S_chars + 15; 739 740 template
741 typename _FormatContext::iterator 742 _M_a_A(const _Tp& __t, typename _FormatContext::iterator __out, 743 _FormatContext& __ctx, bool __full) const 744 { 745 // %a Locale's abbreviated weekday name. 746 // %A Locale's full weekday name. 747 chrono::weekday __wd = _S_weekday(__t); 748 if (!__wd.ok()) 749 __throw_format_error("format error: invalid weekday"); 750 751 locale __loc = _M_locale(__ctx); 752 const auto& __tp = use_facet<__timepunct<_CharT>>(__loc); 753 const _CharT* __days[7]; 754 if (__full) 755 __tp._M_days(__days); 756 else 757 __tp._M_days_abbreviated(__days); 758 __string_view __str(__days[__wd.c_encoding()]); 759 return __format::__write(std::move(__out), __str); 760 } 761 762 template
763 typename _FormatContext::iterator 764 _M_b_B(const _Tp& __t, typename _FormatContext::iterator __out, 765 _FormatContext& __ctx, bool __full) const 766 { 767 // %b Locale's abbreviated month name. 768 // %B Locale's full month name. 769 chrono::month __m = _S_month(__t); 770 if (!__m.ok()) 771 __throw_format_error("format error: invalid month"); 772 locale __loc = _M_locale(__ctx); 773 const auto& __tp = use_facet<__timepunct<_CharT>>(__loc); 774 const _CharT* __months[12]; 775 if (__full) 776 __tp._M_months(__months); 777 else 778 __tp._M_months_abbreviated(__months); 779 __string_view __str(__months[(unsigned)__m - 1]); 780 return __format::__write(std::move(__out), __str); 781 } 782 783 template
784 typename _FormatContext::iterator 785 _M_c(const _Tp& __tt, typename _FormatContext::iterator __out, 786 _FormatContext& __ctx, bool __mod = false) const 787 { 788 // %c Locale's date and time representation. 789 // %Ec Locale's alternate date and time representation. 790 791 auto __t = _S_floor_seconds(__tt); 792 locale __loc = _M_locale(__ctx); 793 const auto& __tp = use_facet<__timepunct<_CharT>>(__loc); 794 const _CharT* __formats[2]; 795 __tp._M_date_time_formats(__formats); 796 const _CharT* __rep = __formats[__mod]; 797 if (!*__rep) 798 __rep = _GLIBCXX_WIDEN("%a %b %e %H:%M:%S %Y"); 799 basic_string<_CharT> __fmt(_S_empty_spec); 800 __fmt.insert(1u, 1u, _S_colon); 801 __fmt.insert(2u, __rep); 802 return std::vformat_to(std::move(__out), __loc, __fmt, 803 std::make_format_args<_FormatContext>(__t)); 804 } 805 806 template
807 typename _FormatContext::iterator 808 _M_C_y_Y(const _Tp& __t, typename _FormatContext::iterator __out, 809 _FormatContext& __ctx, _CharT __conv, _CharT __mod = 0) const 810 { 811 // %C Year divided by 100 using floored division. 812 // %EC Locale's alternative preresentation of the century (era name). 813 // %y Last two decimal digits of the year. 814 // %Oy Locale's alternative representation. 815 // %Ey Locale's alternative representation of offset from %EC. 816 // %Y Year as a decimal number. 817 // %EY Locale's alternative full year representation. 818 819 chrono::year __y = _S_year(__t); 820 821 if (__mod) [[unlikely]] 822 { 823 struct tm __tm{}; 824 __tm.tm_year = (int)__y - 1900; 825 return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm, 826 __conv, __mod); 827 } 828 829 basic_string<_CharT> __s; 830 int __yi = (int)__y; 831 const bool __is_neg = __yi < 0; 832 __yi = __builtin_abs(__yi); 833 834 if (__conv == 'Y' || __conv == 'C') 835 { 836 int __ci = __yi / 100; 837 if (__is_neg) [[unlikely]] 838 { 839 __s.assign(1, _S_plus_minus[1]); 840 // For floored division -123//100 is -2 and -100//100 is -1 841 if (__conv == 'C' && (__ci * 100) != __yi) 842 ++__ci; 843 } 844 if (__ci >= 100) [[unlikely]] 845 { 846 __s += std::format(_S_empty_spec, __ci / 100); 847 __ci %= 100; 848 } 849 __s += _S_two_digits(__ci); 850 } 851 852 if (__conv == 'Y' || __conv == 'y') 853 __s += _S_two_digits(__yi % 100); 854 855 return __format::__write(std::move(__out), __string_view(__s)); 856 } 857 858 template
859 typename _FormatContext::iterator 860 _M_D(const _Tp& __t, typename _FormatContext::iterator __out, 861 _FormatContext&) const 862 { 863 auto __ymd = _S_date(__t); 864 basic_string<_CharT> __s; 865 #if ! _GLIBCXX_USE_CXX11_ABI 866 __s.reserve(8); 867 #endif 868 __s = _S_two_digits((unsigned)__ymd.month()); 869 __s += _S_slash; 870 __s += _S_two_digits((unsigned)__ymd.day()); 871 __s += _S_slash; 872 __s += _S_two_digits(__builtin_abs((int)__ymd.year()) % 100); 873 return __format::__write(std::move(__out), __string_view(__s)); 874 } 875 876 template
877 typename _FormatContext::iterator 878 _M_d_e(const _Tp& __t, typename _FormatContext::iterator __out, 879 _FormatContext& __ctx, _CharT __conv, bool __mod = false) const 880 { 881 // %d The day of month as a decimal number. 882 // %Od Locale's alternative representation. 883 // %e Day of month as decimal number, padded with space. 884 // %Oe Locale's alternative digits. 885 886 chrono::day __d = _S_day(__t); 887 unsigned __i = (unsigned)__d; 888 889 if (__mod) [[unlikely]] 890 { 891 struct tm __tm{}; 892 __tm.tm_mday = __i; 893 return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm, 894 (char)__conv, 'O'); 895 } 896 897 auto __sv = _S_two_digits(__i); 898 _CharT __buf[2]; 899 if (__conv == _CharT('e') && __i < 10) 900 { 901 __buf[0] = _S_space; 902 __buf[1] = __sv[1]; 903 __sv = {__buf, 2}; 904 } 905 return __format::__write(std::move(__out), __sv); 906 } 907 908 template
909 typename _FormatContext::iterator 910 _M_F(const _Tp& __t, typename _FormatContext::iterator __out, 911 _FormatContext&) const 912 { 913 auto __ymd = _S_date(__t); 914 basic_string<_CharT> __s; 915 #if ! _GLIBCXX_USE_CXX11_ABI 916 __s.reserve(11); 917 #endif 918 __s += std::format(_GLIBCXX_WIDEN("{:04d}- - "), (int)__ymd.year()); 919 auto __sv = _S_two_digits((unsigned)__ymd.month()); 920 __s[__s.size() - 5] = __sv[0]; 921 __s[__s.size() - 4] = __sv[1]; 922 __sv = _S_two_digits((unsigned)__ymd.day()); 923 __s[__s.size() - 2] = __sv[0]; 924 __s[__s.size() - 1] = __sv[1]; 925 __sv = __s; 926 return __format::__write(std::move(__out), __sv); 927 } 928 929 template
930 typename _FormatContext::iterator 931 _M_g_G(const _Tp& __t, typename _FormatContext::iterator __out, 932 _FormatContext& __ctx, bool __full) const 933 { 934 // %g last two decimal digits of the ISO week-based year. 935 // %G ISO week-based year. 936 using namespace chrono; 937 auto __d = _S_days(__t); 938 // Move to nearest Thursday: 939 __d -= (weekday(__d) - Monday) - days(3); 940 // ISO week-based year is the year that contains that Thursday: 941 year __y = year_month_day(__d).year(); 942 return _M_C_y_Y(__y, std::move(__out), __ctx, "yY"[__full]); 943 } 944 945 template
946 typename _FormatContext::iterator 947 _M_H_I(const _Tp& __t, typename _FormatContext::iterator __out, 948 _FormatContext& __ctx, _CharT __conv, bool __mod = false) const 949 { 950 // %H The hour (24-hour clock) as a decimal number. 951 // %OH Locale's alternative representation. 952 // %I The hour (12-hour clock) as a decimal number. 953 // %OI Locale's alternative representation. 954 955 const auto __hms = _S_hms(__t); 956 int __i = __hms.hours().count(); 957 958 if (__mod) [[unlikely]] 959 { 960 struct tm __tm{}; 961 __tm.tm_hour = __i; 962 return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm, 963 (char)__conv, 'O'); 964 } 965 966 if (__conv == _CharT('I')) 967 { 968 if (__i == 0) 969 __i = 12; 970 else if (__i > 12) 971 __i -= 12; 972 } 973 return __format::__write(std::move(__out), _S_two_digits(__i)); 974 } 975 976 template
977 typename _FormatContext::iterator 978 _M_j(const _Tp& __t, typename _FormatContext::iterator __out, 979 _FormatContext&) const 980 { 981 if constexpr (chrono::__is_duration_v<_Tp>) 982 { 983 // Decimal number of days, without padding. 984 unsigned __d = chrono::duration_cast
(__t).count(); 985 return std::format_to(std::move(__out), _S_empty_spec, __d); 986 } 987 else 988 { 989 // Day of the year as a decimal number, padding with zero. 990 using namespace chrono; 991 auto __day = _S_days(__t); 992 auto __ymd = _S_date(__t); 993 days __d; 994 // See "Calculating Ordinal Dates" at 995 // https://github.com/HowardHinnant/date/wiki/Examples-and-Recipes 996 if constexpr (is_same_v
) 997 __d = __day - local_days(__ymd.year()/January/0); 998 else 999 __d = __day - sys_days(__ymd.year()/January/0); 1000 return std::format_to(std::move(__out), _GLIBCXX_WIDEN("{:03d}"), 1001 __d.count()); 1002 } 1003 } 1004 1005 template
1006 typename _FormatContext::iterator 1007 _M_m(const _Tp& __t, typename _FormatContext::iterator __out, 1008 _FormatContext& __ctx, bool __mod) const 1009 { 1010 // %m month as a decimal number. 1011 // %Om Locale's alternative representation. 1012 1013 auto __m = _S_month(__t); 1014 auto __i = (unsigned)__m; 1015 1016 if (__mod) [[unlikely]] // %Om 1017 { 1018 struct tm __tm{}; 1019 __tm.tm_mon = __i - 1; 1020 return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm, 1021 'm', 'O'); 1022 } 1023 1024 return __format::__write(std::move(__out), _S_two_digits(__i)); 1025 } 1026 1027 template
1028 typename _FormatContext::iterator 1029 _M_M(const _Tp& __t, typename _FormatContext::iterator __out, 1030 _FormatContext& __ctx, bool __mod) const 1031 { 1032 // %M The minute as a decimal number. 1033 // %OM Locale's alternative representation. 1034 1035 auto __m = _S_hms(__t).minutes(); 1036 auto __i = __m.count(); 1037 1038 if (__mod) [[unlikely]] // %OM 1039 { 1040 struct tm __tm{}; 1041 __tm.tm_min = __i; 1042 return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm, 1043 'M', 'O'); 1044 } 1045 1046 return __format::__write(std::move(__out), _S_two_digits(__i)); 1047 } 1048 1049 template
1050 typename _FormatContext::iterator 1051 _M_p(const _Tp& __t, typename _FormatContext::iterator __out, 1052 _FormatContext& __ctx) const 1053 { 1054 // %p The locale's equivalent of the AM/PM designations. 1055 auto __hms = _S_hms(__t); 1056 locale __loc = _M_locale(__ctx); 1057 const auto& __tp = use_facet<__timepunct<_CharT>>(__loc); 1058 const _CharT* __ampm[2]; 1059 __tp._M_am_pm(__ampm); 1060 return std::format_to(std::move(__out), _S_empty_spec, 1061 __ampm[__hms.hours().count() >= 12]); 1062 } 1063 1064 template
1065 typename _FormatContext::iterator 1066 _M_q(const _Tp&, typename _FormatContext::iterator __out, 1067 _FormatContext&) const 1068 { 1069 // %q The duration's unit suffix 1070 if constexpr (!chrono::__is_duration_v<_Tp>) 1071 __throw_format_error("format error: argument is not a duration"); 1072 else 1073 { 1074 namespace __d = chrono::__detail; 1075 using period = typename _Tp::period; 1076 return __d::__fmt_units_suffix
(std::move(__out)); 1077 } 1078 } 1079 1080 // %Q handled in _M_format 1081 1082 template
1083 typename _FormatContext::iterator 1084 _M_r(const _Tp& __tt, typename _FormatContext::iterator __out, 1085 _FormatContext& __ctx) const 1086 { 1087 // %r locale's 12-hour clock time. 1088 auto __t = _S_floor_seconds(__tt); 1089 locale __loc = _M_locale(__ctx); 1090 const auto& __tp = use_facet<__timepunct<_CharT>>(__loc); 1091 const _CharT* __ampm_fmt; 1092 __tp._M_am_pm_format(&__ampm_fmt); 1093 basic_string<_CharT> __fmt(_S_empty_spec); 1094 __fmt.insert(1u, 1u, _S_colon); 1095 __fmt.insert(2u, __ampm_fmt); 1096 return std::vformat_to(std::move(__out), __fmt, 1097 std::make_format_args<_FormatContext>(__t)); 1098 } 1099 1100 template
1101 typename _FormatContext::iterator 1102 _M_R_T(const _Tp& __t, typename _FormatContext::iterator __out, 1103 _FormatContext& __ctx, bool __secs) const 1104 { 1105 // %R Equivalent to %H:%M 1106 // %T Equivalent to %H:%M:%S 1107 auto __hms = _S_hms(__t); 1108 1109 basic_string<_CharT> __s; 1110 #if ! _GLIBCXX_USE_CXX11_ABI 1111 __s.reserve(11); 1112 #endif 1113 __s = std::format(_GLIBCXX_WIDEN("{:02d}:00"), __hms.hours().count()); 1114 auto __sv = _S_two_digits(__hms.minutes().count()); 1115 __s[__s.size() - 2] = __sv[0]; 1116 __s[__s.size() - 1] = __sv[1]; 1117 __sv = __s; 1118 __out = __format::__write(std::move(__out), __sv); 1119 if (__secs) 1120 { 1121 *__out++ = _S_colon; 1122 __out = _M_S(__hms, std::move(__out), __ctx); 1123 } 1124 return __out; 1125 } 1126 1127 template
1128 typename _FormatContext::iterator 1129 _M_S(const _Tp& __t, typename _FormatContext::iterator __out, 1130 _FormatContext& __ctx, bool __mod = false) const 1131 { 1132 // %S Seconds as a decimal number. 1133 // %OS The locale's alternative representation. 1134 auto __hms = _S_hms(__t); 1135 1136 if (__mod) [[unlikely]] // %OS 1137 { 1138 struct tm __tm{}; 1139 __tm.tm_sec = (int)__hms.seconds().count(); 1140 return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm, 1141 'S', 'O'); 1142 } 1143 1144 if constexpr (__hms.fractional_width == 0) 1145 __out = __format::__write(std::move(__out), 1146 _S_two_digits(__hms.seconds().count())); 1147 else 1148 { 1149 locale __loc = _M_locale(__ctx); 1150 auto __s = __hms.seconds(); 1151 auto __ss = __hms.subseconds(); 1152 using rep = typename decltype(__ss)::rep; 1153 if constexpr (is_floating_point_v
) 1154 { 1155 chrono::duration
__fs = __s + __ss; 1156 __out = std::format_to(std::move(__out), __loc, 1157 _GLIBCXX_WIDEN("{:#0{}.{}Lf}"), 1158 __fs.count(), 1159 3 + __hms.fractional_width, 1160 __hms.fractional_width); 1161 } 1162 else 1163 { 1164 const auto& __np 1165 = use_facet
>(__loc); 1166 __out = __format::__write(std::move(__out), 1167 _S_two_digits(__s.count())); 1168 *__out++ = __np.decimal_point(); 1169 if constexpr (is_integral_v
) 1170 __out = std::format_to(std::move(__out), 1171 _GLIBCXX_WIDEN("{:0{}}"), 1172 __ss.count(), 1173 __hms.fractional_width); 1174 else 1175 { 1176 auto __str = std::format(_S_empty_spec, __ss.count()); 1177 __out = std::format_to(_GLIBCXX_WIDEN("{:0>{}s}"), 1178 __str, 1179 __hms.fractional_width); 1180 } 1181 } 1182 } 1183 return __out; 1184 } 1185 1186 // %t handled in _M_format 1187 1188 template
1189 typename _FormatContext::iterator 1190 _M_u_w(const _Tp& __t, typename _FormatContext::iterator __out, 1191 _FormatContext& __ctx, _CharT __conv, bool __mod = false) const 1192 { 1193 // %u ISO weekday as a decimal number (1-7), where Monday is 1. 1194 // %Ou Locale's alternative numeric rep. 1195 // %w Weekday as a decimal number (0-6), where Sunday is 0. 1196 // %Ow Locale's alternative numeric rep. 1197 1198 chrono::weekday __wd = _S_weekday(__t); 1199 1200 if (__mod) [[unlikely]] 1201 { 1202 struct tm __tm{}; 1203 __tm.tm_wday = __wd.c_encoding(); 1204 return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm, 1205 (char)__conv, 'O'); 1206 } 1207 1208 unsigned __wdi = __conv == 'u' ? __wd.iso_encoding() 1209 : __wd.c_encoding(); 1210 const _CharT __d = _S_digit(__wdi); 1211 return __format::__write(std::move(__out), __string_view(&__d, 1)); 1212 } 1213 1214 template
1215 typename _FormatContext::iterator 1216 _M_U_V_W(const _Tp& __t, typename _FormatContext::iterator __out, 1217 _FormatContext& __ctx, _CharT __conv, bool __mod = false) const 1218 { 1219 // %U Week number of the year as a decimal number, from first Sunday. 1220 // %OU Locale's alternative numeric rep. 1221 // %V ISO week-based week number as a decimal number. 1222 // %OV Locale's alternative numeric rep. 1223 // %W Week number of the year as a decimal number, from first Monday. 1224 // %OW Locale's alternative numeric rep. 1225 using namespace chrono; 1226 auto __d = _S_days(__t); 1227 using _TDays = decltype(__d); // Either sys_days or local_days. 1228 1229 if (__mod) [[unlikely]] 1230 { 1231 const year_month_day __ymd(__d); 1232 const year __y = __ymd.year(); 1233 struct tm __tm{}; 1234 __tm.tm_year = (int)__y - 1900; 1235 __tm.tm_yday = (__d - _TDays(__y/January/1)).count(); 1236 __tm.tm_wday = weekday(__d).c_encoding(); 1237 return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm, 1238 (char)__conv, 'O'); 1239 } 1240 1241 _TDays __first; // First day of week 1. 1242 if (__conv == 'V') // W01 begins on Monday before first Thursday. 1243 { 1244 // Move to nearest Thursday: 1245 __d -= (weekday(__d) - Monday) - days(3); 1246 // ISO week of __t is number of weeks since January 1 of the 1247 // same year as that nearest Thursday. 1248 __first = _TDays(year_month_day(__d).year()/January/1); 1249 } 1250 else 1251 { 1252 year __y; 1253 if constexpr (requires { __t.year(); }) 1254 __y = __t.year(); 1255 else 1256 __y = year_month_day(__d).year(); 1257 const weekday __weekstart = __conv == 'U' ? Sunday : Monday; 1258 __first = _TDays(__y/January/__weekstart[1]); 1259 } 1260 auto __weeks = chrono::floor
(__d - __first); 1261 __string_view __sv = _S_two_digits(__weeks.count() + 1); 1262 return __format::__write(std::move(__out), __sv); 1263 } 1264 1265 template
1266 typename _FormatContext::iterator 1267 _M_x(const _Tp& __t, typename _FormatContext::iterator __out, 1268 _FormatContext& __ctx, bool __mod = false) const 1269 { 1270 // %x Locale's date rep 1271 // %Ex Locale's alternative date representation. 1272 locale __loc = _M_locale(__ctx); 1273 const auto& __tp = use_facet<__timepunct<_CharT>>(__loc); 1274 const _CharT* __date_reps[2]; 1275 __tp._M_date_formats(__date_reps); 1276 const _CharT* __rep = __date_reps[__mod]; 1277 if (!*__rep) 1278 return _M_D(__t, std::move(__out), __ctx); 1279 1280 basic_string<_CharT> __fmt(_S_empty_spec); 1281 __fmt.insert(1u, 1u, _S_colon); 1282 __fmt.insert(2u, __rep); 1283 return std::vformat_to(std::move(__out), __fmt, 1284 std::make_format_args<_FormatContext>(__t)); 1285 } 1286 1287 template
1288 typename _FormatContext::iterator 1289 _M_X(const _Tp& __tt, typename _FormatContext::iterator __out, 1290 _FormatContext& __ctx, bool __mod = false) const 1291 { 1292 // %X Locale's time rep 1293 // %EX Locale's alternative time representation. 1294 auto __t = _S_floor_seconds(__tt); 1295 locale __loc = _M_locale(__ctx); 1296 const auto& __tp = use_facet<__timepunct<_CharT>>(__loc); 1297 const _CharT* __time_reps[2]; 1298 __tp._M_time_formats(__time_reps); 1299 const _CharT* __rep = __time_reps[__mod]; 1300 if (!*__rep) 1301 return _M_R_T(__t, std::move(__out), __ctx, true); 1302 1303 basic_string<_CharT> __fmt(_S_empty_spec); 1304 __fmt.insert(1u, 1u, _S_colon); 1305 __fmt.insert(2u, __rep); 1306 return std::vformat_to(std::move(__out), __fmt, 1307 std::make_format_args<_FormatContext>(__t)); 1308 } 1309 1310 template
1311 typename _FormatContext::iterator 1312 _M_z(const _Tp& __t, typename _FormatContext::iterator __out, 1313 _FormatContext&, bool __mod = false) const 1314 { 1315 using ::std::chrono::__detail::__utc_leap_second; 1316 using ::std::chrono::__detail::__local_time_fmt; 1317 1318 auto __utc = __mod ? __string_view(_GLIBCXX_WIDEN("+00:00"), 6) 1319 : __string_view(_GLIBCXX_WIDEN("+0000"), 5); 1320 1321 if constexpr (chrono::__is_time_point_v<_Tp>) 1322 { 1323 if constexpr (is_same_v
) 1325 return __format::__write(std::move(__out), __utc); 1326 } 1327 else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>) 1328 { 1329 if (__t._M_offset_sec) 1330 { 1331 auto __sv = __utc; 1332 basic_string<_CharT> __s; 1333 if (*__t._M_offset_sec != 0s) 1334 { 1335 chrono:: hh_mm_ss __hms(*__t._M_offset_sec); 1336 __s = _S_plus_minus[__hms.is_negative()]; 1337 __s += _S_two_digits(__hms.hours().count()); 1338 if (__mod) 1339 __s += _S_colon; 1340 __s += _S_two_digits(__hms.minutes().count()); 1341 __sv = __s; 1342 } 1343 return __format::__write(std::move(__out), __sv); 1344 } 1345 } 1346 else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>) 1347 return __format::__write(std::move(__out), __utc); 1348 1349 __no_timezone_available(); 1350 } 1351 1352 template
1353 typename _FormatContext::iterator 1354 _M_Z(const _Tp& __t, typename _FormatContext::iterator __out, 1355 _FormatContext& __ctx) const 1356 { 1357 using ::std::chrono::__detail::__utc_leap_second; 1358 using ::std::chrono::__detail::__local_time_fmt; 1359 1360 __string_view __utc(_GLIBCXX_WIDEN("UTC"), 3); 1361 if constexpr (chrono::__is_time_point_v<_Tp>) 1362 { 1363 if constexpr (is_same_v
) 1365 return __format::__write(std::move(__out), __utc); 1366 } 1367 else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>) 1368 { 1369 if (__t._M_abbrev) 1370 { 1371 string_view __sv = *__t._M_abbrev; 1372 if constexpr (is_same_v<_CharT, char>) 1373 return __format::__write(std::move(__out), __sv); 1374 else 1375 { 1376 // TODO use resize_and_overwrite 1377 basic_string<_CharT> __ws(__sv.size(), _CharT()); 1378 auto& __ct = use_facet
>(_M_locale(__ctx)); 1379 __ct.widen(__sv.begin(), __sv.end(), __ws.data()); 1380 __string_view __wsv = __ws; 1381 return __format::__write(std::move(__out), __wsv); 1382 } 1383 } 1384 } 1385 else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>) 1386 return __format::__write(std::move(__out), __utc); 1387 1388 __no_timezone_available(); 1389 } 1390 1391 // %% handled in _M_format 1392 1393 // A single digit character in the range '0'..'9'. 1394 static _CharT 1395 _S_digit(int __n) noexcept 1396 { 1397 // Extra 9s avoid past-the-end read on bad input. 1398 return _GLIBCXX_WIDEN("0123456789999999")[__n & 0xf]; 1399 } 1400 1401 // A string view of two digit characters, "00".."99". 1402 static basic_string_view<_CharT> 1403 _S_two_digits(int __n) noexcept 1404 { 1405 return { 1406 _GLIBCXX_WIDEN("0001020304050607080910111213141516171819" 1407 "2021222324252627282930313233343536373839" 1408 "4041424344454647484950515253545556575859" 1409 "6061626364656667686970717273747576777879" 1410 "8081828384858687888990919293949596979899" 1411 "9999999999999999999999999999999999999999" 1412 "9999999999999999") + 2 * (__n & 0x7f), 1413 2 1414 }; 1415 } 1416 1417 // Accessors for the components of chrono types: 1418 1419 // Returns a hh_mm_ss. 1420 template
1421 static decltype(auto) 1422 _S_hms(const _Tp& __t) 1423 { 1424 using ::std::chrono::__detail::__utc_leap_second; 1425 using ::std::chrono::__detail::__local_time_fmt; 1426 1427 if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>) 1428 return __t; 1429 else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>) 1430 return __t._M_time; 1431 else if constexpr (chrono::__is_duration_v<_Tp>) 1432 return chrono::hh_mm_ss<_Tp>(__t); 1433 else if constexpr (chrono::__is_time_point_v<_Tp>) 1434 return chrono::hh_mm_ss(__t - chrono::floor
(__t)); 1435 else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>) 1436 return _S_hms(__t._M_time); 1437 else 1438 { 1439 __invalid_chrono_spec(); 1440 return chrono::hh_mm_ss
(); 1441 } 1442 } 1443 1444 // Returns a sys_days or local_days. 1445 template
1446 static auto 1447 _S_days(const _Tp& __t) 1448 { 1449 using namespace chrono; 1450 using ::std::chrono::__detail::__utc_leap_second; 1451 using ::std::chrono::__detail::__local_time_fmt; 1452 1453 if constexpr (__is_time_point_v<_Tp>) 1454 return chrono::floor
(__t); 1455 else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>) 1456 return __t._M_date; 1457 else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>) 1458 return chrono::floor
(__t._M_time); 1459 else if constexpr (is_same_v<_Tp, year_month_day> 1460 || is_same_v<_Tp, year_month_day_last> 1461 || is_same_v<_Tp, year_month_weekday> 1462 || is_same_v<_Tp, year_month_weekday_last>) 1463 return sys_days(__t); 1464 else 1465 { 1466 if constexpr (__is_duration_v<_Tp>) 1467 __not_valid_for_duration(); 1468 else 1469 __invalid_chrono_spec(); 1470 return chrono::sys_days(); 1471 } 1472 } 1473 1474 // Returns a year_month_day. 1475 template
1476 static chrono::year_month_day 1477 _S_date(const _Tp& __t) 1478 { 1479 if constexpr (is_same_v<_Tp, chrono::year_month_day>) 1480 return __t; 1481 else 1482 return chrono::year_month_day(_S_days(__t)); 1483 } 1484 1485 template
1486 static chrono::day 1487 _S_day(const _Tp& __t) 1488 { 1489 using namespace chrono; 1490 1491 if constexpr (is_same_v<_Tp, day>) 1492 return __t; 1493 else if constexpr (requires { __t.day(); }) 1494 return __t.day(); 1495 else 1496 return _S_date(__t).day(); 1497 } 1498 1499 template
1500 static chrono::month 1501 _S_month(const _Tp& __t) 1502 { 1503 using namespace chrono; 1504 1505 if constexpr (is_same_v<_Tp, month>) 1506 return __t; 1507 else if constexpr (requires { __t.month(); }) 1508 return __t.month(); 1509 else 1510 return _S_date(__t).month(); 1511 } 1512 1513 template
1514 static chrono::year 1515 _S_year(const _Tp& __t) 1516 { 1517 using namespace chrono; 1518 1519 if constexpr (is_same_v<_Tp, year>) 1520 return __t; 1521 else if constexpr (requires { __t.year(); }) 1522 return __t.year(); 1523 else 1524 return _S_date(__t).year(); 1525 } 1526 1527 template
1528 static chrono::weekday 1529 _S_weekday(const _Tp& __t) 1530 { 1531 using namespace ::std::chrono; 1532 using ::std::chrono::__detail::__local_time_fmt; 1533 1534 if constexpr (is_same_v<_Tp, weekday>) 1535 return __t; 1536 else if constexpr (requires { __t.weekday(); }) 1537 return __t.weekday(); 1538 else if constexpr (is_same_v<_Tp, month_weekday>) 1539 return __t.weekday_indexed().weekday(); 1540 else if constexpr (is_same_v<_Tp, month_weekday_last>) 1541 return __t.weekday_last().weekday(); 1542 else 1543 return weekday(_S_days(__t)); 1544 } 1545 1546 // Remove subsecond precision from a time_point. 1547 template
1548 static auto 1549 _S_floor_seconds(const _Tp& __t) 1550 { 1551 using chrono::__detail::__local_time_fmt; 1552 if constexpr (chrono::__is_time_point_v<_Tp> 1553 || chrono::__is_duration_v<_Tp>) 1554 { 1555 if constexpr (_Tp::period::den != 1) 1556 return chrono::floor
(__t); 1557 else 1558 return __t; 1559 } 1560 else if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>) 1561 { 1562 if constexpr (_Tp::fractional_width != 0) 1563 return chrono::floor
(__t.to_duration()); 1564 else 1565 return __t; 1566 } 1567 else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>) 1568 return _S_floor_seconds(__t._M_time); 1569 else 1570 return __t; 1571 } 1572 1573 // Use the formatting locale's std::time_put facet to produce 1574 // a locale-specific representation. 1575 template
1576 _Iter 1577 _M_locale_fmt(_Iter __out, const locale& __loc, const struct tm& __tm, 1578 char __fmt, char __mod) const 1579 { 1580 basic_ostringstream<_CharT> __os; 1581 const auto& __tp = use_facet
>(__loc); 1582 __tp.put(__os, __os, _S_space, &__tm, __fmt, __mod); 1583 if (__os) 1584 __out = __format::__write(std::move(__out), __os.view()); 1585 return __out; 1586 } 1587 }; 1588 1589 } // namespace __format 1590 /// @endcond 1591 1592 template
1593 struct formatter
, _CharT> 1594 { 1595 constexpr typename basic_format_parse_context<_CharT>::iterator 1596 parse(basic_format_parse_context<_CharT>& __pc) 1597 { 1598 using namespace __format; 1599 auto __it = _M_f._M_parse(__pc, _Duration|_TimeOfDay); 1600 if constexpr (!is_floating_point_v<_Rep>) 1601 if (_M_f._M_spec._M_prec_kind != __format::_WP_none) 1602 __throw_format_error("format error: invalid precision for duration"); 1603 return __it; 1604 } 1605 1606 template
1607 typename basic_format_context<_Out, _CharT>::iterator 1608 format(const chrono::duration<_Rep, _Period>& __d, 1609 basic_format_context<_Out, _CharT>& __fc) const 1610 { 1611 if constexpr (numeric_limits<_Rep>::is_signed) 1612 if (__d < __d.zero()) 1613 return _M_f._M_format(-__d, __fc, true); 1614 return _M_f._M_format(__d, __fc, false); 1615 } 1616 1617 private: 1618 __format::__formatter_chrono<_CharT> _M_f; 1619 }; 1620 1621 template
1622 struct formatter
1623 { 1624 template
1625 constexpr typename _ParseContext::iterator 1626 parse(_ParseContext& __pc) 1627 { return _M_f._M_parse(__pc, __format::_Day); } 1628 1629 template
1630 typename _FormatContext::iterator 1631 format(const chrono::day& __t, _FormatContext& __fc) const 1632 { return _M_f._M_format(__t, __fc); } 1633 1634 private: 1635 __format::__formatter_chrono<_CharT> _M_f; 1636 }; 1637 1638 template
1639 struct formatter
1640 { 1641 template
1642 constexpr typename _ParseContext::iterator 1643 parse(_ParseContext& __pc) 1644 { return _M_f._M_parse(__pc, __format::_Month); } 1645 1646 template
1647 typename _FormatContext::iterator 1648 format(const chrono::month& __t, _FormatContext& __fc) const 1649 { return _M_f._M_format(__t, __fc); } 1650 1651 private: 1652 __format::__formatter_chrono<_CharT> _M_f; 1653 }; 1654 1655 template
1656 struct formatter
1657 { 1658 template
1659 constexpr typename _ParseContext::iterator 1660 parse(_ParseContext& __pc) 1661 { return _M_f._M_parse(__pc, __format::_Year); } 1662 1663 template
1664 typename _FormatContext::iterator 1665 format(const chrono::year& __t, _FormatContext& __fc) const 1666 { return _M_f._M_format(__t, __fc); } 1667 1668 private: 1669 __format::__formatter_chrono<_CharT> _M_f; 1670 }; 1671 1672 template
1673 struct formatter
1674 { 1675 template
1676 constexpr typename _ParseContext::iterator 1677 parse(_ParseContext& __pc) 1678 { return _M_f._M_parse(__pc, __format::_Weekday); } 1679 1680 template
1681 typename _FormatContext::iterator 1682 format(const chrono::weekday& __t, _FormatContext& __fc) const 1683 { return _M_f._M_format(__t, __fc); } 1684 1685 private: 1686 __format::__formatter_chrono<_CharT> _M_f; 1687 }; 1688 1689 template
1690 struct formatter
1691 { 1692 template
1693 constexpr typename _ParseContext::iterator 1694 parse(_ParseContext& __pc) 1695 { return _M_f._M_parse(__pc, __format::_Weekday); } 1696 1697 template
1698 typename _FormatContext::iterator 1699 format(const chrono::weekday_indexed& __t, _FormatContext& __fc) const 1700 { return _M_f._M_format(__t, __fc); } 1701 1702 private: 1703 __format::__formatter_chrono<_CharT> _M_f; 1704 }; 1705 1706 template
1707 struct formatter
1708 { 1709 template
1710 constexpr typename _ParseContext::iterator 1711 parse(_ParseContext& __pc) 1712 { return _M_f._M_parse(__pc, __format::_Weekday); } 1713 1714 template
1715 typename _FormatContext::iterator 1716 format(const chrono::weekday_last& __t, _FormatContext& __fc) const 1717 { return _M_f._M_format(__t, __fc); } 1718 1719 private: 1720 __format::__formatter_chrono<_CharT> _M_f; 1721 }; 1722 1723 template
1724 struct formatter
1725 { 1726 template
1727 constexpr typename _ParseContext::iterator 1728 parse(_ParseContext& __pc) 1729 { return _M_f._M_parse(__pc, __format::_Month|__format::_Day); } 1730 1731 template
1732 typename _FormatContext::iterator 1733 format(const chrono::month_day& __t, _FormatContext& __fc) const 1734 { return _M_f._M_format(__t, __fc); } 1735 1736 private: 1737 __format::__formatter_chrono<_CharT> _M_f; 1738 }; 1739 1740 template
1741 struct formatter
1742 { 1743 template
1744 constexpr typename _ParseContext::iterator 1745 parse(_ParseContext& __pc) 1746 { return _M_f._M_parse(__pc, __format::_Month|__format::_Day); } 1747 1748 template
1749 typename _FormatContext::iterator 1750 format(const chrono::month_day_last& __t, _FormatContext& __fc) const 1751 { return _M_f._M_format(__t, __fc); } 1752 1753 private: 1754 __format::__formatter_chrono<_CharT> _M_f; 1755 }; 1756 1757 template
1758 struct formatter
1759 { 1760 template
1761 constexpr typename _ParseContext::iterator 1762 parse(_ParseContext& __pc) 1763 { return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday); } 1764 1765 template
1766 typename _FormatContext::iterator 1767 format(const chrono::month_weekday& __t, _FormatContext& __fc) const 1768 { return _M_f._M_format(__t, __fc); } 1769 1770 private: 1771 __format::__formatter_chrono<_CharT> _M_f; 1772 }; 1773 1774 template
1775 struct formatter
1776 { 1777 template
1778 constexpr typename _ParseContext::iterator 1779 parse(_ParseContext& __pc) 1780 { return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday); } 1781 1782 template
1783 typename _FormatContext::iterator 1784 format(const chrono::month_weekday_last& __t, 1785 _FormatContext& __fc) const 1786 { return _M_f._M_format(__t, __fc); } 1787 1788 private: 1789 __format::__formatter_chrono<_CharT> _M_f; 1790 }; 1791 1792 template
1793 struct formatter
1794 { 1795 template
1796 constexpr typename _ParseContext::iterator 1797 parse(_ParseContext& __pc) 1798 { return _M_f._M_parse(__pc, __format::_Year|__format::_Month); } 1799 1800 template
1801 typename _FormatContext::iterator 1802 format(const chrono::year_month& __t, _FormatContext& __fc) const 1803 { return _M_f._M_format(__t, __fc); } 1804 1805 private: 1806 __format::__formatter_chrono<_CharT> _M_f; 1807 }; 1808 1809 template
1810 struct formatter
1811 { 1812 template
1813 constexpr typename _ParseContext::iterator 1814 parse(_ParseContext& __pc) 1815 { return _M_f._M_parse(__pc, __format::_Date); } 1816 1817 template
1818 typename _FormatContext::iterator 1819 format(const chrono::year_month_day& __t, _FormatContext& __fc) const 1820 { return _M_f._M_format(__t, __fc); } 1821 1822 private: 1823 __format::__formatter_chrono<_CharT> _M_f; 1824 }; 1825 1826 template
1827 struct formatter
1828 { 1829 template
1830 constexpr typename _ParseContext::iterator 1831 parse(_ParseContext& __pc) 1832 { return _M_f._M_parse(__pc, __format::_Date); } 1833 1834 template
1835 typename _FormatContext::iterator 1836 format(const chrono::year_month_day_last& __t, 1837 _FormatContext& __fc) const 1838 { return _M_f._M_format(__t, __fc); } 1839 1840 private: 1841 __format::__formatter_chrono<_CharT> _M_f; 1842 }; 1843 1844 template
1845 struct formatter
1846 { 1847 template
1848 constexpr typename _ParseContext::iterator 1849 parse(_ParseContext& __pc) 1850 { return _M_f._M_parse(__pc, __format::_Date); } 1851 1852 template
1853 typename _FormatContext::iterator 1854 format(const chrono::year_month_weekday& __t, 1855 _FormatContext& __fc) const 1856 { return _M_f._M_format(__t, __fc); } 1857 1858 private: 1859 __format::__formatter_chrono<_CharT> _M_f; 1860 }; 1861 1862 template
1863 struct formatter
1864 { 1865 template
1866 constexpr typename _ParseContext::iterator 1867 parse(_ParseContext& __pc) 1868 { return _M_f._M_parse(__pc, __format::_Date); } 1869 1870 template
1871 typename _FormatContext::iterator 1872 format(const chrono::year_month_weekday_last& __t, 1873 _FormatContext& __fc) const 1874 { return _M_f._M_format(__t, __fc); } 1875 1876 private: 1877 __format::__formatter_chrono<_CharT> _M_f; 1878 }; 1879 1880 template
1881 struct formatter
>, _CharT> 1882 { 1883 template
1884 constexpr typename _ParseContext::iterator 1885 parse(_ParseContext& __pc) 1886 { return _M_f._M_parse(__pc, __format::_TimeOfDay); } 1887 1888 template
1889 typename _FormatContext::iterator 1890 format(const chrono::hh_mm_ss
>& __t, 1891 _FormatContext& __fc) const 1892 { return _M_f._M_format(__t, __fc); } 1893 1894 private: 1895 __format::__formatter_chrono<_CharT> _M_f; 1896 }; 1897 1898 #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI 1899 template
1900 struct formatter
1901 { 1902 template
1903 constexpr typename _ParseContext::iterator 1904 parse(_ParseContext& __pc) 1905 { return _M_f._M_parse(__pc, __format::_ChronoParts{}); } 1906 1907 template
1908 typename _FormatContext::iterator 1909 format(const chrono::sys_info& __i, _FormatContext& __fc) const 1910 { return _M_f._M_format(__i, __fc); } 1911 1912 private: 1913 __format::__formatter_chrono<_CharT> _M_f; 1914 }; 1915 1916 template
1917 struct formatter
1918 { 1919 template
1920 constexpr typename _ParseContext::iterator 1921 parse(_ParseContext& __pc) 1922 { return _M_f._M_parse(__pc, __format::_ChronoParts{}); } 1923 1924 template
1925 typename _FormatContext::iterator 1926 format(const chrono::local_info& __i, _FormatContext& __fc) const 1927 { return _M_f._M_format(__i, __fc); } 1928 1929 private: 1930 __format::__formatter_chrono<_CharT> _M_f; 1931 }; 1932 #endif 1933 1934 template
1935 struct formatter
, _CharT> 1936 { 1937 template
1938 constexpr typename _ParseContext::iterator 1939 parse(_ParseContext& __pc) 1940 { 1941 auto __next = _M_f._M_parse(__pc, __format::_ZonedDateTime); 1942 if constexpr (!__stream_insertable) 1943 if (_M_f._M_spec._M_chrono_specs.empty()) 1944 __format::__invalid_chrono_spec(); // chrono-specs can't be empty 1945 return __next; 1946 } 1947 1948 template
1949 typename _FormatContext::iterator 1950 format(const chrono::sys_time<_Duration>& __t, 1951 _FormatContext& __fc) const 1952 { return _M_f._M_format(__t, __fc); } 1953 1954 private: 1955 static constexpr bool __stream_insertable 1956 = requires (basic_ostream<_CharT>& __os, 1957 chrono::sys_time<_Duration> __t) { __os << __t; }; 1958 1959 __format::__formatter_chrono<_CharT> _M_f; 1960 }; 1961 1962 template
1963 struct formatter
, _CharT> 1964 : __format::__formatter_chrono<_CharT> 1965 { 1966 template
1967 constexpr typename _ParseContext::iterator 1968 parse(_ParseContext& __pc) 1969 { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } 1970 1971 template
1972 typename _FormatContext::iterator 1973 format(const chrono::utc_time<_Duration>& __t, 1974 _FormatContext& __fc) const 1975 { 1976 // Adjust by removing leap seconds to get equivalent sys_time. 1977 // We can't just use clock_cast because we want to know if the time 1978 // falls within a leap second insertion, and format seconds as "60". 1979 using chrono::__detail::__utc_leap_second; 1980 using chrono::seconds; 1981 using chrono::sys_time; 1982 using _CDur = common_type_t<_Duration, seconds>; 1983 const auto __li = chrono::get_leap_second_info(__t); 1984 sys_time<_CDur> __s{__t.time_since_epoch() - __li.elapsed}; 1985 if (!__li.is_leap_second) [[likely]] 1986 return _M_f._M_format(__s, __fc); 1987 else 1988 return _M_f._M_format(__utc_leap_second(__s), __fc); 1989 } 1990 1991 private: 1992 friend formatter
, _CharT>; 1993 1994 __format::__formatter_chrono<_CharT> _M_f; 1995 }; 1996 1997 template
1998 struct formatter
, _CharT> 1999 : __format::__formatter_chrono<_CharT> 2000 { 2001 template
2002 constexpr typename _ParseContext::iterator 2003 parse(_ParseContext& __pc) 2004 { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } 2005 2006 template
2007 typename _FormatContext::iterator 2008 format(const chrono::tai_time<_Duration>& __t, 2009 _FormatContext& __fc) const 2010 { 2011 // Convert to __local_time_fmt with abbrev "TAI" and offset 0s. 2012 2013 // Offset is 1970y/January/1 - 1958y/January/1 2014 constexpr chrono::days __tai_offset = chrono::days(4383); 2015 using _CDur = common_type_t<_Duration, chrono::days>; 2016 chrono::local_time<_CDur> __lt(__t.time_since_epoch() - __tai_offset); 2017 const string __abbrev("TAI", 3); 2018 const chrono::seconds __off = 0s; 2019 const auto __lf = chrono::local_time_format(__lt, &__abbrev, &__off); 2020 return _M_f._M_format(__lf, __fc); 2021 } 2022 2023 private: 2024 __format::__formatter_chrono<_CharT> _M_f; 2025 }; 2026 2027 template
2028 struct formatter
, _CharT> 2029 : __format::__formatter_chrono<_CharT> 2030 { 2031 template
2032 constexpr typename _ParseContext::iterator 2033 parse(_ParseContext& __pc) 2034 { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } 2035 2036 template
2037 typename _FormatContext::iterator 2038 format(const chrono::gps_time<_Duration>& __t, 2039 _FormatContext& __fc) const 2040 { 2041 // Convert to __local_time_fmt with abbrev "GPS" and offset 0s. 2042 2043 // Offset is 1980y/January/Sunday[1] - 1970y/January/1 2044 constexpr chrono::days __gps_offset = chrono::days(3657); 2045 using _CDur = common_type_t<_Duration, chrono::days>; 2046 chrono::local_time<_CDur> __lt(__t.time_since_epoch() + __gps_offset); 2047 const string __abbrev("GPS", 3); 2048 const chrono::seconds __off = 0s; 2049 const auto __lf = chrono::local_time_format(__lt, &__abbrev, &__off); 2050 return _M_f._M_format(__lf, __fc); 2051 } 2052 2053 private: 2054 __format::__formatter_chrono<_CharT> _M_f; 2055 }; 2056 2057 template
2058 struct formatter
, _CharT> 2059 { 2060 template
2061 constexpr typename _ParseContext::iterator 2062 parse(_ParseContext& __pc) 2063 { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } 2064 2065 template
2066 typename _FormatContext::iterator 2067 format(const chrono::file_time<_Duration>& __t, 2068 _FormatContext& __ctx) const 2069 { 2070 using namespace chrono; 2071 return _M_f._M_format(chrono::clock_cast
(__t), __ctx); 2072 } 2073 2074 private: 2075 __format::__formatter_chrono<_CharT> _M_f; 2076 }; 2077 2078 template
2079 struct formatter
, _CharT> 2080 { 2081 template
2082 constexpr typename _ParseContext::iterator 2083 parse(_ParseContext& __pc) 2084 { return _M_f._M_parse(__pc, __format::_DateTime); } 2085 2086 template
2087 typename _FormatContext::iterator 2088 format(const chrono::local_time<_Duration>& __t, 2089 _FormatContext& __ctx) const 2090 { return _M_f._M_format(__t, __ctx); } 2091 2092 private: 2093 __format::__formatter_chrono<_CharT> _M_f; 2094 }; 2095 2096 template
2097 struct formatter
, _CharT> 2098 { 2099 template
2100 constexpr typename _ParseContext::iterator 2101 parse(_ParseContext& __pc) 2102 { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } 2103 2104 template
2105 typename _FormatContext::iterator 2106 format(const chrono::__detail::__local_time_fmt<_Duration>& __t, 2107 _FormatContext& __ctx) const 2108 { return _M_f._M_format(__t, __ctx); } 2109 2110 private: 2111 __format::__formatter_chrono<_CharT> _M_f; 2112 }; 2113 2114 #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI 2115 template
2116 struct formatter
, _CharT> 2117 : formatter
, _CharT> 2118 { 2119 template
2120 typename _FormatContext::iterator 2121 format(const chrono::zoned_time<_Duration, _TimeZonePtr>& __tp, 2122 _FormatContext& __ctx) const 2123 { 2124 using chrono::__detail::__local_time_fmt; 2125 using _Base = formatter<__local_time_fmt<_Duration>, _CharT>; 2126 const chrono::sys_info __info = __tp.get_info(); 2127 const auto __lf = chrono::local_time_format(__tp.get_local_time(), 2128 &__info.abbrev, 2129 &__info.offset); 2130 return _Base::format(__lf, __ctx); 2131 } 2132 }; 2133 #endif 2134 2135 // Partial specialization needed for %c formatting of __utc_leap_second. 2136 template
2137 struct formatter
, _CharT> 2138 : formatter
, _CharT> 2139 { 2140 template
2141 typename _FormatContext::iterator 2142 format(const chrono::__detail::__utc_leap_second<_Duration>& __t, 2143 _FormatContext& __fc) const 2144 { return this->_M_f._M_format(__t, __fc); } 2145 }; 2146 2147 namespace chrono 2148 { 2149 /// @addtogroup chrono 2150 /// @{ 2151 2152 // TODO: from_stream for duration 2153 #if 0 2154 template
> 2156 basic_istream<_CharT, _Traits>& 2157 from_stream(basic_istream<_CharT, _Traits>& __is, const _CharT* __fmt, 2158 duration<_Rep, _Period>& __d, 2159 basic_string<_CharT, _Traits, _Alloc>* __abbrev = nullptr, 2160 minutes* __offset = nullptr) 2161 { 2162 } 2163 #endif 2164 2165 template
2166 inline basic_ostream<_CharT, _Traits>& 2167 operator<<(basic_ostream<_CharT, _Traits>& __os, const day& __d) 2168 { 2169 using _Ctx = __conditional_t
, 2170 format_context, wformat_context>; 2171 using _Str = basic_string_view<_CharT>; 2172 _Str __s = _GLIBCXX_WIDEN("{:02d} is not a valid day"); 2173 if (__d.ok()) 2174 __s = __s.substr(0, 6); 2175 auto __u = (unsigned)__d; 2176 __os << std::vformat(__s, make_format_args<_Ctx>(__u)); 2177 return __os; 2178 } 2179 2180 // TODO from_stream for day 2181 2182 template
2183 inline basic_ostream<_CharT, _Traits>& 2184 operator<<(basic_ostream<_CharT, _Traits>& __os, const month& __m) 2185 { 2186 using _Ctx = __conditional_t
, 2187 format_context, wformat_context>; 2188 using _Str = basic_string_view<_CharT>; 2189 _Str __s = _GLIBCXX_WIDEN("{:L%b}{} is not a valid month"); 2190 if (__m.ok()) 2191 __os << std::vformat(__os.getloc(), __s.substr(0, 6), 2192 make_format_args<_Ctx>(__m)); 2193 else 2194 { 2195 auto __u = (unsigned)__m; 2196 __os << std::vformat(__s.substr(6), make_format_args<_Ctx>(__u)); 2197 } 2198 return __os; 2199 } 2200 2201 // TODO from_stream for month 2202 2203 template
2204 inline basic_ostream<_CharT, _Traits>& 2205 operator<<(basic_ostream<_CharT, _Traits>& __os, const year& __y) 2206 { 2207 using _Ctx = __conditional_t
, 2208 format_context, wformat_context>; 2209 using _Str = basic_string_view<_CharT>; 2210 _Str __s = _GLIBCXX_WIDEN("-{:04d} is not a valid year"); 2211 if (__y.ok()) 2212 __s = __s.substr(0, 7); 2213 int __i = (int)__y; 2214 if (__i >= 0) [[likely]] 2215 __s.remove_prefix(1); 2216 else 2217 __i = -__i; 2218 __os << std::vformat(__s, make_format_args<_Ctx>(__i)); 2219 return __os; 2220 } 2221 2222 // TODO from_stream for year 2223 2224 template
2225 inline basic_ostream<_CharT, _Traits>& 2226 operator<<(basic_ostream<_CharT, _Traits>& __os, const weekday& __wd) 2227 { 2228 using _Ctx = __conditional_t
, 2229 format_context, wformat_context>; 2230 using _Str = basic_string_view<_CharT>; 2231 _Str __s = _GLIBCXX_WIDEN("{:L%a}{} is not a valid weekday"); 2232 if (__wd.ok()) 2233 __os << std::vformat(__os.getloc(), __s.substr(0, 6), 2234 make_format_args<_Ctx>(__wd)); 2235 else 2236 { 2237 auto __c = __wd.c_encoding(); 2238 __os << std::vformat(__s.substr(6), make_format_args<_Ctx>(__c)); 2239 } 2240 return __os; 2241 } 2242 2243 // TODO from_stream for weekday 2244 2245 template
2246 inline basic_ostream<_CharT, _Traits>& 2247 operator<<(basic_ostream<_CharT, _Traits>& __os, 2248 const weekday_indexed& __wdi) 2249 { 2250 // The standard says to format wdi.weekday() and wdi.index() using 2251 // either "{:L}[{}]" or "{:L}[{} is not a valid index]". The {:L} spec 2252 // means to format the weekday using ostringstream, so just do that. 2253 basic_stringstream<_CharT> __os2; 2254 __os2.imbue(__os.getloc()); 2255 __os2 << __wdi.weekday(); 2256 const auto __i = __wdi.index(); 2257 if constexpr (is_same_v<_CharT, char>) 2258 __os2 << std::format("[{}", __i); 2259 else 2260 __os2 << std::format(L"[{}", __i); 2261 basic_string_view<_CharT> __s = _GLIBCXX_WIDEN(" is not a valid index]"); 2262 if (__i >= 1 && __i <= 5) 2263 __os2 << __s.back(); 2264 else 2265 __os2 << __s; 2266 __os << __os2.view(); 2267 return __os; 2268 } 2269 2270 template
2271 inline basic_ostream<_CharT, _Traits>& 2272 operator<<(basic_ostream<_CharT, _Traits>& __os, 2273 const weekday_last& __wdl) 2274 { 2275 // As above, just write straight to a stringstream, as if by "{:L}[last]" 2276 basic_stringstream<_CharT> __os2; 2277 __os2.imbue(__os.getloc()); 2278 __os2 << __wdl.weekday() << _GLIBCXX_WIDEN("[last]"); 2279 __os << __os2.view(); 2280 return __os; 2281 } 2282 2283 template
2284 inline basic_ostream<_CharT, _Traits>& 2285 operator<<(basic_ostream<_CharT, _Traits>& __os, const month_day& __md) 2286 { 2287 // As above, just write straight to a stringstream, as if by "{:L}/{}" 2288 basic_stringstream<_CharT> __os2; 2289 __os2.imbue(__os.getloc()); 2290 __os2 << __md.month(); 2291 if constexpr (is_same_v<_CharT, char>) 2292 __os2 << '/'; 2293 else 2294 __os2 << L'/'; 2295 __os2 << __md.day(); 2296 __os << __os2.view(); 2297 return __os; 2298 } 2299 2300 // TODO from_stream for month_day 2301 2302 template
2303 inline basic_ostream<_CharT, _Traits>& 2304 operator<<(basic_ostream<_CharT, _Traits>& __os, 2305 const month_day_last& __mdl) 2306 { 2307 // As above, just write straight to a stringstream, as if by "{:L}/last" 2308 basic_stringstream<_CharT> __os2; 2309 __os2.imbue(__os.getloc()); 2310 __os2 << __mdl.month(); 2311 if constexpr (is_same_v<_CharT, char>) 2312 __os2 << "/last"; 2313 else 2314 __os2 << L"/last"; 2315 __os << __os2.view(); 2316 return __os; 2317 } 2318 2319 template
2320 inline basic_ostream<_CharT, _Traits>& 2321 operator<<(basic_ostream<_CharT, _Traits>& __os, 2322 const month_weekday& __mwd) 2323 { 2324 // As above, just write straight to a stringstream, as if by "{:L}/{:L}" 2325 basic_stringstream<_CharT> __os2; 2326 __os2.imbue(__os.getloc()); 2327 __os2 << __mwd.month(); 2328 if constexpr (is_same_v<_CharT, char>) 2329 __os2 << '/'; 2330 else 2331 __os2 << L'/'; 2332 __os2 << __mwd.weekday_indexed(); 2333 __os << __os2.view(); 2334 return __os; 2335 } 2336 2337 template
2338 inline basic_ostream<_CharT, _Traits>& 2339 operator<<(basic_ostream<_CharT, _Traits>& __os, 2340 const month_weekday_last& __mwdl) 2341 { 2342 // As above, just write straight to a stringstream, as if by "{:L}/{:L}" 2343 basic_stringstream<_CharT> __os2; 2344 __os2.imbue(__os.getloc()); 2345 __os2 << __mwdl.month(); 2346 if constexpr (is_same_v<_CharT, char>) 2347 __os2 << '/'; 2348 else 2349 __os2 << L'/'; 2350 __os2 << __mwdl.weekday_last(); 2351 __os << __os2.view(); 2352 return __os; 2353 } 2354 2355 template
2356 inline basic_ostream<_CharT, _Traits>& 2357 operator<<(basic_ostream<_CharT, _Traits>& __os, const year_month& __ym) 2358 { 2359 // As above, just write straight to a stringstream, as if by "{}/{:L}" 2360 basic_stringstream<_CharT> __os2; 2361 __os2.imbue(__os.getloc()); 2362 __os2 << __ym.year(); 2363 if constexpr (is_same_v<_CharT, char>) 2364 __os2 << '/'; 2365 else 2366 __os2 << L'/'; 2367 __os2 << __ym.month(); 2368 __os << __os2.view(); 2369 return __os; 2370 } 2371 2372 // TODO from_stream for year_month 2373 2374 template
2375 inline basic_ostream<_CharT, _Traits>& 2376 operator<<(basic_ostream<_CharT, _Traits>& __os, 2377 const year_month_day& __ymd) 2378 { 2379 using _Ctx = __conditional_t
, 2380 format_context, wformat_context>; 2381 using _Str = basic_string_view<_CharT>; 2382 _Str __s = _GLIBCXX_WIDEN("{:%F} is not a valid date"); 2383 __os << std::vformat(__ymd.ok() ? __s.substr(0, 5) : __s, 2384 make_format_args<_Ctx>(__ymd)); 2385 return __os; 2386 } 2387 2388 // TODO from_stream for year_month_day 2389 2390 template
2391 inline basic_ostream<_CharT, _Traits>& 2392 operator<<(basic_ostream<_CharT, _Traits>& __os, 2393 const year_month_day_last& __ymdl) 2394 { 2395 // As above, just write straight to a stringstream, as if by "{}/{:L}" 2396 basic_stringstream<_CharT> __os2; 2397 __os2.imbue(__os.getloc()); 2398 __os2 << __ymdl.year(); 2399 if constexpr (is_same_v<_CharT, char>) 2400 __os2 << '/'; 2401 else 2402 __os2 << L'/'; 2403 __os2 << __ymdl.month_day_last(); 2404 __os << __os2.view(); 2405 return __os; 2406 } 2407 2408 template
2409 inline basic_ostream<_CharT, _Traits>& 2410 operator<<(basic_ostream<_CharT, _Traits>& __os, 2411 const year_month_weekday& __ymwd) 2412 { 2413 // As above, just write straight to a stringstream, as if by 2414 // "{}/{:L}/{:L}" 2415 basic_stringstream<_CharT> __os2; 2416 __os2.imbue(__os.getloc()); 2417 _CharT __slash; 2418 if constexpr (is_same_v<_CharT, char>) 2419 __slash = '/'; 2420 else 2421 __slash = L'/'; 2422 __os2 << __ymwd.year() << __slash << __ymwd.month() << __slash 2423 << __ymwd.weekday_indexed(); 2424 __os << __os2.view(); 2425 return __os; 2426 } 2427 2428 template
2429 inline basic_ostream<_CharT, _Traits>& 2430 operator<<(basic_ostream<_CharT, _Traits>& __os, 2431 const year_month_weekday_last& __ymwdl) 2432 { 2433 // As above, just write straight to a stringstream, as if by 2434 // "{}/{:L}/{:L}" 2435 basic_stringstream<_CharT> __os2; 2436 __os2.imbue(__os.getloc()); 2437 _CharT __slash; 2438 if constexpr (is_same_v<_CharT, char>) 2439 __slash = '/'; 2440 else 2441 __slash = L'/'; 2442 __os2 << __ymwdl.year() << __slash << __ymwdl.month() << __slash 2443 << __ymwdl.weekday_last(); 2444 __os << __os2.view(); 2445 return __os; 2446 } 2447 2448 template
2449 inline basic_ostream<_CharT, _Traits>& 2450 operator<<(basic_ostream<_CharT, _Traits>& __os, 2451 const hh_mm_ss<_Duration>& __hms) 2452 { 2453 return __os << format(__os.getloc(), _GLIBCXX_WIDEN("{:L%T}"), __hms); 2454 } 2455 2456 #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI 2457 /// Writes a sys_info object to an ostream in an unspecified format. 2458 template
2459 basic_ostream<_CharT, _Traits>& 2460 operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_info& __i) 2461 { 2462 __os << '[' << __i.begin << ',' << __i.end 2463 << ',' << hh_mm_ss(__i.offset) << ',' << __i.save 2464 << ',' << __i.abbrev << ']'; 2465 return __os; 2466 } 2467 2468 /// Writes a local_info object to an ostream in an unspecified format. 2469 template
2470 basic_ostream<_CharT, _Traits>& 2471 operator<<(basic_ostream<_CharT, _Traits>& __os, const local_info& __li) 2472 { 2473 __os << '['; 2474 if (__li.result == local_info::unique) 2475 __os << __li.first; 2476 else 2477 { 2478 if (__li.result == local_info::nonexistent) 2479 __os << "nonexistent"; 2480 else 2481 __os << "ambiguous"; 2482 __os << " local time between " << __li.first; 2483 __os << " and " << __li.second; 2484 } 2485 __os << ']'; 2486 return __os; 2487 } 2488 2489 template
2491 inline basic_ostream<_CharT, _Traits>& 2492 operator<<(basic_ostream<_CharT, _Traits>& __os, 2493 const zoned_time<_Duration, _TimeZonePtr>& __t) 2494 { 2495 __os << format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T %Z}"), __t); 2496 return __os; 2497 } 2498 #endif 2499 2500 template
2501 requires (!treat_as_floating_point_v
) 2502 && ratio_less_v
2503 inline basic_ostream<_CharT, _Traits>& 2504 operator<<(basic_ostream<_CharT, _Traits>& __os, 2505 const sys_time<_Duration>& __tp) 2506 { 2507 __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __tp); 2508 return __os; 2509 } 2510 2511 template
2512 inline basic_ostream<_CharT, _Traits>& 2513 operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_days& __dp) 2514 { 2515 __os << year_month_day{__dp}; 2516 return __os; 2517 } 2518 2519 // TODO: from_stream for sys_time 2520 2521 template
2522 inline basic_ostream<_CharT, _Traits>& 2523 operator<<(basic_ostream<_CharT, _Traits>& __os, 2524 const utc_time<_Duration>& __t) 2525 { 2526 __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __t); 2527 return __os; 2528 } 2529 2530 // TODO: from_stream for utc_time 2531 2532 template
2533 inline basic_ostream<_CharT, _Traits>& 2534 operator<<(basic_ostream<_CharT, _Traits>& __os, 2535 const tai_time<_Duration>& __t) 2536 { 2537 __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __t); 2538 return __os; 2539 } 2540 2541 // TODO: from_stream for tai_time 2542 2543 template
2544 inline basic_ostream<_CharT, _Traits>& 2545 operator<<(basic_ostream<_CharT, _Traits>& __os, 2546 const gps_time<_Duration>& __t) 2547 { 2548 __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __t); 2549 return __os; 2550 } 2551 2552 // TODO: from_stream for gps_time 2553 2554 2555 template
2556 inline basic_ostream<_CharT, _Traits>& 2557 operator<<(basic_ostream<_CharT, _Traits>& __os, 2558 const file_time<_Duration>& __t) 2559 { 2560 __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{:L%F %T}"), __t); 2561 return __os; 2562 } 2563 2564 // TODO: from_stream for file_time 2565 2566 template
2567 inline basic_ostream<_CharT, _Traits>& 2568 operator<<(basic_ostream<_CharT, _Traits>& __os, 2569 const local_time<_Duration>& __lt) 2570 { 2571 __os << sys_time<_Duration>{__lt.time_since_epoch()}; 2572 return __os; 2573 } 2574 2575 // TODO: from_stream for local_time 2576 #undef _GLIBCXX_WIDEN 2577 2578 /// @} group chrono 2579 } // namespace chrono 2580 2581 _GLIBCXX_END_NAMESPACE_VERSION 2582 } // namespace std 2583 2584 #endif // C++20 2585 2586 #endif //_GLIBCXX_CHRONO_IO_H
Contact us
|
About us
|
Term of use
|
Copyright © 2000-2025 MyWebUniversity.com ™