1 // <chrono> -*- C++ -*- 2 3 // Copyright (C) 2008-2024 Free Software Foundation, Inc. 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 // <http://www.gnu.org/licenses/>. 24 25 /** @file include/chrono 26 * This is a Standard C++ Library header. 27 * @ingroup chrono 28 */ 29 30 #ifndef _GLIBCXX_CHRONO 31 #define _GLIBCXX_CHRONO 1 32 33 #pragma GCC system_header 34 35 #include <bits/requires_hosted.h> // for <ctime> and clocks 36 37 #if __cplusplus < 201103L 38 # include <bits/c++0x_warning.h> 39 #else 40 41 #include <bits/chrono.h> 42 43 #if __cplusplus >= 202002L 44 # include <bit> 45 # include <sstream> 46 # include <string> 47 # include <vector> 48 # include <bits/stl_algo.h> // upper_bound 49 # include <bits/shared_ptr.h> 50 # include <bits/unique_ptr.h> 51 #endif 52 53 #define __glibcxx_want_chrono 54 #define __glibcxx_want_chrono_udls 55 #include <bits/version.h> 56 57 namespace std _GLIBCXX_VISIBILITY(default) 58 { 59 _GLIBCXX_BEGIN_NAMESPACE_VERSION 60 61 /** 62 * @defgroup chrono Time 63 * @ingroup utilities 64 * 65 * Classes and functions for time. 66 * 67 * @since C++11 68 */ 69 70 /** @namespace std::chrono 71 * @brief ISO C++ 2011 namespace for date and time utilities 72 * @ingroup chrono 73 */ 74 namespace chrono 75 { 76 #if __cplusplus >= 202002L 77 /// @addtogroup chrono 78 /// @{ 79 struct local_t { }; 80 template<typename _Duration> 81 using local_time = time_point<local_t, _Duration>; 82 using local_seconds = local_time<seconds>; 83 using local_days = local_time<days>; 84 85 class utc_clock; 86 class tai_clock; 87 class gps_clock; 88 89 template<typename _Duration> 90 using utc_time = time_point<utc_clock, _Duration>; 91 using utc_seconds = utc_time<seconds>; 92 93 template<typename _Duration> 94 using tai_time = time_point<tai_clock, _Duration>; 95 using tai_seconds = tai_time<seconds>; 96 97 template<typename _Duration> 98 using gps_time = time_point<gps_clock, _Duration>; 99 using gps_seconds = gps_time<seconds>; 100 101 template<> struct is_clock<utc_clock> : true_type { }; 102 template<> struct is_clock<tai_clock> : true_type { }; 103 template<> struct is_clock<gps_clock> : true_type { }; 104 105 template<> inline constexpr bool is_clock_v<utc_clock> = true; 106 template<> inline constexpr bool is_clock_v<tai_clock> = true; 107 template<> inline constexpr bool is_clock_v<gps_clock> = true; 108 109 struct leap_second_info 110 { 111 bool is_leap_second; 112 seconds elapsed; 113 }; 114 115 template<typename _Duration> 116 leap_second_info 117 get_leap_second_info(const utc_time<_Duration>& __ut); 118 119 /** A clock that measures Universal Coordinated Time (UTC). 120 * 121 * The epoch is 1970-01-01 00:00:00. 122 * 123 * @since C++20 124 */ 125 class utc_clock 126 { 127 public: 128 using rep = system_clock::rep; 129 using period = system_clock::period; 130 using duration = chrono::duration<rep, period>; 131 using time_point = chrono::time_point<utc_clock>; 132 static constexpr bool is_steady = false; 133 134 [[nodiscard]] 135 static time_point 136 now() 137 { return from_sys(system_clock::now()); } 138 139 template<typename _Duration> 140 [[nodiscard]] 141 static sys_time<common_type_t<_Duration, seconds>> 142 to_sys(const utc_time<_Duration>& __t) 143 { 144 using _CDur = common_type_t<_Duration, seconds>; 145 const auto __li = chrono::get_leap_second_info(__t); 146 sys_time<_CDur> __s{__t.time_since_epoch() - __li.elapsed}; 147 if (__li.is_leap_second) 148 __s = chrono::floor<seconds>(__s) + seconds{1} - _CDur{1}; 149 return __s; 150 } 151 152 template<typename _Duration> 153 [[nodiscard]] 154 static utc_time<common_type_t<_Duration, seconds>> 155 from_sys(const sys_time<_Duration>& __t); 156 }; 157 158 /** A clock that measures International Atomic Time. 159 * 160 * The epoch is 1958-01-01 00:00:00. 161 * 162 * @since C++20 163 */ 164 class tai_clock 165 { 166 public: 167 using rep = system_clock::rep; 168 using period = system_clock::period; 169 using duration = chrono::duration<rep, period>; 170 using time_point = chrono::time_point<tai_clock>; 171 static constexpr bool is_steady = false; // XXX true for CLOCK_TAI? 172 173 // TODO move into lib, use CLOCK_TAI on linux, add extension point. 174 [[nodiscard]] 175 static time_point 176 now() 177 { return from_utc(utc_clock::now()); } 178 179 template<typename _Duration> 180 [[nodiscard]] 181 static utc_time<common_type_t<_Duration, seconds>> 182 to_utc(const tai_time<_Duration>& __t) 183 { 184 using _CDur = common_type_t<_Duration, seconds>; 185 return utc_time<_CDur>{__t.time_since_epoch()} - 378691210s; 186 } 187 188 template<typename _Duration> 189 [[nodiscard]] 190 static tai_time<common_type_t<_Duration, seconds>> 191 from_utc(const utc_time<_Duration>& __t) 192 { 193 using _CDur = common_type_t<_Duration, seconds>; 194 return tai_time<_CDur>{__t.time_since_epoch()} + 378691210s; 195 } 196 }; 197 198 /** A clock that measures GPS time. 199 * 200 * The epoch is 1980-01-06 00:00:00. 201 * 202 * @since C++20 203 */ 204 class gps_clock 205 { 206 public: 207 using rep = system_clock::rep; 208 using period = system_clock::period; 209 using duration = chrono::duration<rep, period>; 210 using time_point = chrono::time_point<gps_clock>; 211 static constexpr bool is_steady = false; // XXX 212 213 // TODO move into lib, add extension point. 214 [[nodiscard]] 215 static time_point 216 now() 217 { return from_utc(utc_clock::now()); } 218 219 template<typename _Duration> 220 [[nodiscard]] 221 static utc_time<common_type_t<_Duration, seconds>> 222 to_utc(const gps_time<_Duration>& __t) 223 { 224 using _CDur = common_type_t<_Duration, seconds>; 225 return utc_time<_CDur>{__t.time_since_epoch()} + 315964809s; 226 } 227 228 template<typename _Duration> 229 [[nodiscard]] 230 static gps_time<common_type_t<_Duration, seconds>> 231 from_utc(const utc_time<_Duration>& __t) 232 { 233 using _CDur = common_type_t<_Duration, seconds>; 234 return gps_time<_CDur>{__t.time_since_epoch()} - 315964809s; 235 } 236 }; 237 238 239 template<typename _DestClock, typename _SourceClock> 240 struct clock_time_conversion 241 { }; 242 243 // Identity conversions 244 245 template<typename _Clock> 246 struct clock_time_conversion<_Clock, _Clock> 247 { 248 template<typename _Duration> 249 time_point<_Clock, _Duration> 250 operator()(const time_point<_Clock, _Duration>& __t) const 251 { return __t; } 252 }; 253 254 template<> 255 struct clock_time_conversion<system_clock, system_clock> 256 { 257 template<typename _Duration> 258 sys_time<_Duration> 259 operator()(const sys_time<_Duration>& __t) const 260 { return __t; } 261 }; 262 263 template<> 264 struct clock_time_conversion<utc_clock, utc_clock> 265 { 266 template<typename _Duration> 267 utc_time<_Duration> 268 operator()(const utc_time<_Duration>& __t) const 269 { return __t; } 270 }; 271 272 // Conversions between system_clock and utc_clock 273 274 template<> 275 struct clock_time_conversion<utc_clock, system_clock> 276 { 277 template<typename _Duration> 278 utc_time<common_type_t<_Duration, seconds>> 279 operator()(const sys_time<_Duration>& __t) const 280 { return utc_clock::from_sys(__t); } 281 }; 282 283 template<> 284 struct clock_time_conversion<system_clock, utc_clock> 285 { 286 template<typename _Duration> 287 sys_time<common_type_t<_Duration, seconds>> 288 operator()(const utc_time<_Duration>& __t) const 289 { return utc_clock::to_sys(__t); } 290 }; 291 292 template<typename _Tp, typename _Clock> 293 inline constexpr bool __is_time_point_for_v = false; 294 295 template<typename _Clock, typename _Duration> 296 inline constexpr bool 297 __is_time_point_for_v<time_point<_Clock, _Duration>, _Clock> = true; 298 299 // Conversions between system_clock and other clocks 300 301 template<typename _SourceClock> 302 struct clock_time_conversion<system_clock, _SourceClock> 303 { 304 template<typename _Duration, typename _Src = _SourceClock> 305 auto 306 operator()(const time_point<_SourceClock, _Duration>& __t) const 307 -> decltype(_Src::to_sys(__t)) 308 { 309 using _Ret = decltype(_SourceClock::to_sys(__t)); 310 static_assert(__is_time_point_for_v<_Ret, system_clock>); 311 return _SourceClock::to_sys(__t); 312 } 313 }; 314 315 template<typename _DestClock> 316 struct clock_time_conversion<_DestClock, system_clock> 317 { 318 template<typename _Duration, typename _Dest = _DestClock> 319 auto 320 operator()(const sys_time<_Duration>& __t) const 321 -> decltype(_Dest::from_sys(__t)) 322 { 323 using _Ret = decltype(_DestClock::from_sys(__t)); 324 static_assert(__is_time_point_for_v<_Ret, _DestClock>); 325 return _DestClock::from_sys(__t); 326 } 327 }; 328 329 // Conversions between utc_clock and other clocks 330 331 template<typename _SourceClock> 332 struct clock_time_conversion<utc_clock, _SourceClock> 333 { 334 template<typename _Duration, typename _Src = _SourceClock> 335 auto 336 operator()(const time_point<_SourceClock, _Duration>& __t) const 337 -> decltype(_Src::to_utc(__t)) 338 { 339 using _Ret = decltype(_SourceClock::to_utc(__t)); 340 static_assert(__is_time_point_for_v<_Ret, utc_clock>); 341 return _SourceClock::to_utc(__t); 342 } 343 }; 344 345 template<typename _DestClock> 346 struct clock_time_conversion<_DestClock, utc_clock> 347 { 348 template<typename _Duration, typename _Dest = _DestClock> 349 auto 350 operator()(const utc_time<_Duration>& __t) const 351 -> decltype(_Dest::from_utc(__t)) 352 { 353 using _Ret = decltype(_DestClock::from_utc(__t)); 354 static_assert(__is_time_point_for_v<_Ret, _DestClock>); 355 return _DestClock::from_utc(__t); 356 } 357 }; 358 359 /// @cond undocumented 360 namespace __detail 361 { 362 template<typename _DestClock, typename _SourceClock, typename _Duration> 363 concept __clock_convs 364 = requires (const time_point<_SourceClock, _Duration>& __t) { 365 clock_time_conversion<_DestClock, _SourceClock>{}(__t); 366 }; 367 368 template<typename _DestClock, typename _SourceClock, typename _Duration> 369 concept __clock_convs_sys 370 = requires (const time_point<_SourceClock, _Duration>& __t) { 371 clock_time_conversion<_DestClock, system_clock>{}( 372 clock_time_conversion<system_clock, _SourceClock>{}(__t)); 373 }; 374 375 template<typename _DestClock, typename _SourceClock, typename _Duration> 376 concept __clock_convs_utc 377 = requires (const time_point<_SourceClock, _Duration>& __t) { 378 clock_time_conversion<_DestClock, utc_clock>{}( 379 clock_time_conversion<utc_clock, _SourceClock>{}(__t)); 380 }; 381 382 template<typename _DestClock, typename _SourceClock, typename _Duration> 383 concept __clock_convs_sys_utc 384 = requires (const time_point<_SourceClock, _Duration>& __t) { 385 clock_time_conversion<_DestClock, utc_clock>{}( 386 clock_time_conversion<utc_clock, system_clock>{}( 387 clock_time_conversion<system_clock, _SourceClock>{}(__t))); 388 }; 389 390 template<typename _DestClock, typename _SourceClock, typename _Duration> 391 concept __clock_convs_utc_sys 392 = requires (const time_point<_SourceClock, _Duration>& __t) { 393 clock_time_conversion<_DestClock, system_clock>{}( 394 clock_time_conversion<system_clock, utc_clock>{}( 395 clock_time_conversion<utc_clock, _SourceClock>{}(__t))); 396 }; 397 398 } // namespace __detail 399 /// @endcond 400 401 /// Convert a time point to a different clock. 402 template<typename _DestClock, typename _SourceClock, typename _Duration> 403 [[nodiscard]] 404 inline auto 405 clock_cast(const time_point<_SourceClock, _Duration>& __t) 406 requires __detail::__clock_convs<_DestClock, _SourceClock, _Duration> 407 || __detail::__clock_convs_sys<_DestClock, _SourceClock, _Duration> 408 || __detail::__clock_convs_utc<_DestClock, _SourceClock, _Duration> 409 || __detail::__clock_convs_sys_utc<_DestClock, _SourceClock, _Duration> 410 || __detail::__clock_convs_utc_sys<_DestClock, _SourceClock, _Duration> 411 { 412 constexpr bool __direct 413 = __detail::__clock_convs<_DestClock, _SourceClock, _Duration>; 414 if constexpr (__direct) 415 { 416 return clock_time_conversion<_DestClock, _SourceClock>{}(__t); 417 } 418 else 419 { 420 constexpr bool __convert_via_sys_clock 421 = __detail::__clock_convs_sys<_DestClock, _SourceClock, _Duration>; 422 constexpr bool __convert_via_utc_clock 423 = __detail::__clock_convs_utc<_DestClock, _SourceClock, _Duration>; 424 if constexpr (__convert_via_sys_clock) 425 { 426 static_assert(!__convert_via_utc_clock, 427 "clock_cast requires a unique best conversion, but " 428 "conversion is possible via system_clock and also via" 429 "utc_clock"); 430 return clock_time_conversion<_DestClock, system_clock>{}( 431 clock_time_conversion<system_clock, _SourceClock>{}(__t)); 432 } 433 else if constexpr (__convert_via_utc_clock) 434 { 435 return clock_time_conversion<_DestClock, utc_clock>{}( 436 clock_time_conversion<utc_clock, _SourceClock>{}(__t)); 437 } 438 else 439 { 440 constexpr bool __convert_via_sys_and_utc_clocks 441 = __detail::__clock_convs_sys_utc<_DestClock, 442 _SourceClock, 443 _Duration>; 444 445 if constexpr (__convert_via_sys_and_utc_clocks) 446 { 447 constexpr bool __convert_via_utc_and_sys_clocks 448 = __detail::__clock_convs_utc_sys<_DestClock, 449 _SourceClock, 450 _Duration>; 451 static_assert(!__convert_via_utc_and_sys_clocks, 452 "clock_cast requires a unique best conversion, but " 453 "conversion is possible via system_clock followed by " 454 "utc_clock, and also via utc_clock followed by " 455 "system_clock"); 456 return clock_time_conversion<_DestClock, utc_clock>{}( 457 clock_time_conversion<utc_clock, system_clock>{}( 458 clock_time_conversion<system_clock, _SourceClock>{}(__t))); 459 } 460 else 461 { 462 return clock_time_conversion<_DestClock, system_clock>{}( 463 clock_time_conversion<system_clock, utc_clock>{}( 464 clock_time_conversion<utc_clock, _SourceClock>{}(__t))); 465 } 466 } 467 } 468 } 469 470 // CALENDRICAL TYPES 471 472 // CLASS DECLARATIONS 473 class day; 474 class month; 475 class year; 476 class weekday; 477 class weekday_indexed; 478 class weekday_last; 479 class month_day; 480 class month_day_last; 481 class month_weekday; 482 class month_weekday_last; 483 class year_month; 484 class year_month_day; 485 class year_month_day_last; 486 class year_month_weekday; 487 class year_month_weekday_last; 488 489 struct last_spec 490 { 491 explicit last_spec() = default; 492 493 friend constexpr month_day_last 494 operator/(int __m, last_spec) noexcept; 495 496 friend constexpr month_day_last 497 operator/(last_spec, int __m) noexcept; 498 }; 499 500 inline constexpr last_spec last{}; 501 502 namespace __detail 503 { 504 // Helper to __add_modulo and __sub_modulo. 505 template <unsigned __d, typename _Tp> 506 consteval auto 507 __modulo_offset() 508 { 509 using _Up = make_unsigned_t<_Tp>; 510 auto constexpr __a = _Up(-1) - _Up(255 + __d - 2); 511 auto constexpr __b = _Up(__d * (__a / __d) - 1); 512 // Notice: b <= a - 1 <= _Up(-1) - (255 + d - 1) and b % d = d - 1. 513 return _Up(-1) - __b; // >= 255 + d - 1 514 } 515 516 // Compute the remainder of the Euclidean division of __x + __y divided by 517 // __d without overflowing. Typically, __x <= 255 + d - 1 is sum of 518 // weekday/month with a shift in [0, d - 1] and __y is a duration count. 519 template <unsigned __d, typename _Tp> 520 constexpr unsigned 521 __add_modulo(unsigned __x, _Tp __y) 522 { 523 using _Up = make_unsigned_t<_Tp>; 524 // For __y >= 0, _Up(__y) has the same mathematical value as __y and 525 // this function simply returns (__x + _Up(__y)) % d. Typically, this 526 // doesn't overflow since the range of _Up contains many more positive 527 // values than _Tp's. For __y < 0, _Up(__y) has a mathematical value in 528 // the upper-half range of _Up so that adding a positive value to it 529 // might overflow. Moreover, most likely, _Up(__y) != __y mod d. To 530 // fix both issues we subtract from _Up(__y) an __offset >= 531 // 255 + d - 1 to make room for the addition to __x and shift the modulo 532 // to the correct value. 533 auto const __offset = __y >= 0 ? _Up(0) : __modulo_offset<__d, _Tp>(); 534 return (__x + _Up(__y) - __offset) % __d; 535 } 536 537 // Similar to __add_modulo but for __x - __y. 538 template <unsigned __d, typename _Tp> 539 constexpr unsigned 540 __sub_modulo(unsigned __x, _Tp __y) 541 { 542 using _Up = make_unsigned_t<_Tp>; 543 auto const __offset = __y <= 0 ? _Up(0) : __modulo_offset<__d, _Tp>(); 544 return (__x - _Up(__y) - __offset) % __d; 545 } 546 547 inline constexpr unsigned __days_per_month[12] 548 = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 549 } 550 551 // DAY 552 553 class day 554 { 555 private: 556 unsigned char _M_d; 557 558 public: 559 day() = default; 560 561 explicit constexpr 562 day(unsigned __d) noexcept 563 : _M_d(__d) 564 { } 565 566 constexpr day& 567 operator++() noexcept 568 { 569 ++_M_d; 570 return *this; 571 } 572 573 constexpr day 574 operator++(int) noexcept 575 { 576 auto __ret = *this; 577 ++(*this); 578 return __ret; 579 } 580 581 constexpr day& 582 operator--() noexcept 583 { 584 --_M_d; 585 return *this; 586 } 587 588 constexpr day 589 operator--(int) noexcept 590 { 591 auto __ret = *this; 592 --(*this); 593 return __ret; 594 } 595 596 constexpr day& 597 operator+=(const days& __d) noexcept 598 { 599 *this = *this + __d; 600 return *this; 601 } 602 603 constexpr day& 604 operator-=(const days& __d) noexcept 605 { 606 *this = *this - __d; 607 return *this; 608 } 609 610 constexpr explicit 611 operator unsigned() const noexcept 612 { return _M_d; } 613 614 constexpr bool 615 ok() const noexcept 616 { return 1 <= _M_d && _M_d <= 31; } 617 618 friend constexpr bool 619 operator==(const day& __x, const day& __y) noexcept 620 { return unsigned{__x} == unsigned{__y}; } 621 622 friend constexpr strong_ordering 623 operator<=>(const day& __x, const day& __y) noexcept 624 { return unsigned{__x} <=> unsigned{__y}; } 625 626 friend constexpr day 627 operator+(const day& __x, const days& __y) noexcept 628 { return day(unsigned{__x} + __y.count()); } 629 630 friend constexpr day 631 operator+(const days& __x, const day& __y) noexcept 632 { return __y + __x; } 633 634 friend constexpr day 635 operator-(const day& __x, const days& __y) noexcept 636 { return __x + -__y; } 637 638 friend constexpr days 639 operator-(const day& __x, const day& __y) noexcept 640 { return days{int(unsigned{__x}) - int(unsigned{__y})}; } 641 642 friend constexpr month_day 643 operator/(const month& __m, const day& __d) noexcept; 644 645 friend constexpr month_day 646 operator/(int __m, const day& __d) noexcept; 647 648 friend constexpr month_day 649 operator/(const day& __d, const month& __m) noexcept; 650 651 friend constexpr month_day 652 operator/(const day& __d, int __m) noexcept; 653 654 friend constexpr year_month_day 655 operator/(const year_month& __ym, const day& __d) noexcept; 656 }; 657 658 // MONTH 659 660 class month 661 { 662 private: 663 unsigned char _M_m; 664 665 public: 666 month() = default; 667 668 explicit constexpr 669 month(unsigned __m) noexcept 670 : _M_m(__m) 671 { } 672 673 constexpr month& 674 operator++() noexcept 675 { 676 *this += months{1}; 677 return *this; 678 } 679 680 constexpr month 681 operator++(int) noexcept 682 { 683 auto __ret = *this; 684 ++(*this); 685 return __ret; 686 } 687 688 constexpr month& 689 operator--() noexcept 690 { 691 *this -= months{1}; 692 return *this; 693 } 694 695 constexpr month 696 operator--(int) noexcept 697 { 698 auto __ret = *this; 699 --(*this); 700 return __ret; 701 } 702 703 constexpr month& 704 operator+=(const months& __m) noexcept 705 { 706 *this = *this + __m; 707 return *this; 708 } 709 710 constexpr month& 711 operator-=(const months& __m) noexcept 712 { 713 *this = *this - __m; 714 return *this; 715 } 716 717 explicit constexpr 718 operator unsigned() const noexcept 719 { return _M_m; } 720 721 constexpr bool 722 ok() const noexcept 723 { return 1 <= _M_m && _M_m <= 12; } 724 725 friend constexpr bool 726 operator==(const month& __x, const month& __y) noexcept 727 { return unsigned{__x} == unsigned{__y}; } 728 729 friend constexpr strong_ordering 730 operator<=>(const month& __x, const month& __y) noexcept 731 { return unsigned{__x} <=> unsigned{__y}; } 732 733 friend constexpr month 734 operator+(const month& __x, const months& __y) noexcept 735 { 736 // modulo(x + (y - 1), 12) = modulo(x + (y - 1) + 12, 12) 737 // = modulo((x + 11) + y , 12) 738 return month{1 + __detail::__add_modulo<12>( 739 unsigned{__x} + 11, __y.count())}; 740 } 741 742 friend constexpr month 743 operator+(const months& __x, const month& __y) noexcept 744 { return __y + __x; } 745 746 friend constexpr month 747 operator-(const month& __x, const months& __y) noexcept 748 { 749 // modulo(x + (-y - 1), 12) = modulo(x + (-y - 1) + 12, 12) 750 // = modulo((x + 11) - y , 12) 751 return month{1 + __detail::__sub_modulo<12>( 752 unsigned{__x} + 11, __y.count())}; 753 } 754 755 friend constexpr months 756 operator-(const month& __x, const month& __y) noexcept 757 { 758 const auto __dm = int(unsigned(__x)) - int(unsigned(__y)); 759 return months{__dm < 0 ? 12 + __dm : __dm}; 760 } 761 762 friend constexpr year_month 763 operator/(const year& __y, const month& __m) noexcept; 764 765 friend constexpr month_day 766 operator/(const month& __m, int __d) noexcept; 767 768 friend constexpr month_day_last 769 operator/(const month& __m, last_spec) noexcept; 770 771 friend constexpr month_day_last 772 operator/(last_spec, const month& __m) noexcept; 773 774 friend constexpr month_weekday 775 operator/(const month& __m, const weekday_indexed& __wdi) noexcept; 776 777 friend constexpr month_weekday 778 operator/(const weekday_indexed& __wdi, const month& __m) noexcept; 779 780 friend constexpr month_weekday_last 781 operator/(const month& __m, const weekday_last& __wdl) noexcept; 782 783 friend constexpr month_weekday_last 784 operator/(const weekday_last& __wdl, const month& __m) noexcept; 785 }; 786 787 inline constexpr month January{1}; 788 inline constexpr month February{2}; 789 inline constexpr month March{3}; 790 inline constexpr month April{4}; 791 inline constexpr month May{5}; 792 inline constexpr month June{6}; 793 inline constexpr month July{7}; 794 inline constexpr month August{8}; 795 inline constexpr month September{9}; 796 inline constexpr month October{10}; 797 inline constexpr month November{11}; 798 inline constexpr month December{12}; 799 800 // YEAR 801 802 class year 803 { 804 private: 805 short _M_y; 806 807 public: 808 year() = default; 809 810 explicit constexpr 811 year(int __y) noexcept 812 : _M_y{static_cast<short>(__y)} 813 { } 814 815 static constexpr year 816 min() noexcept 817 { return year{-32767}; } 818 819 static constexpr year 820 max() noexcept 821 { return year{32767}; } 822 823 constexpr year& 824 operator++() noexcept 825 { 826 ++_M_y; 827 return *this; 828 } 829 830 constexpr year 831 operator++(int) noexcept 832 { 833 auto __ret = *this; 834 ++(*this); 835 return __ret; 836 } 837 838 constexpr year& 839 operator--() noexcept 840 { 841 --_M_y; 842 return *this; 843 } 844 845 constexpr year 846 operator--(int) noexcept 847 { 848 auto __ret = *this; 849 --(*this); 850 return __ret; 851 } 852 853 constexpr year& 854 operator+=(const years& __y) noexcept 855 { 856 *this = *this + __y; 857 return *this; 858 } 859 860 constexpr year& 861 operator-=(const years& __y) noexcept 862 { 863 *this = *this - __y; 864 return *this; 865 } 866 867 constexpr year 868 operator+() const noexcept 869 { return *this; } 870 871 constexpr year 872 operator-() const noexcept 873 { return year{-_M_y}; } 874 875 constexpr bool 876 is_leap() const noexcept 877 { 878 // Testing divisibility by 100 first gives better performance [1], i.e., 879 // return _M_y % 100 == 0 ? _M_y % 400 == 0 : _M_y % 16 == 0; 880 // Furthermore, if _M_y % 100 == 0, then _M_y % 400 == 0 is equivalent 881 // to _M_y % 16 == 0, so we can simplify it to 882 // return _M_y % 100 == 0 ? _M_y % 16 == 0 : _M_y % 4 == 0. // #1 883 // Similarly, we can replace 100 with 25 (which is good since 884 // _M_y % 25 == 0 requires one fewer instruction than _M_y % 100 == 0 885 // [2]): 886 // return _M_y % 25 == 0 ? _M_y % 16 == 0 : _M_y % 4 == 0. // #2 887 // Indeed, first assume _M_y % 4 != 0. Then _M_y % 16 != 0 and hence, 888 // _M_y % 4 == 0 and _M_y % 16 == 0 are both false. Therefore, #2 889 // returns false as it should (regardless of _M_y % 25.) Now assume 890 // _M_y % 4 == 0. In this case, _M_y % 25 == 0 if, and only if, 891 // _M_y % 100 == 0, that is, #1 and #2 are equivalent. Finally, #2 is 892 // equivalent to 893 // return (_M_y & (_M_y % 25 == 0 ? 15 : 3)) == 0. 894 895 // References: 896 // [1] https://github.com/cassioneri/calendar 897 // [2] https://godbolt.org/z/55G8rn77e 898 // [3] https://gcc.gnu.org/pipermail/libstdc++/2021-June/052815.html 899 900 return (_M_y & (_M_y % 25 == 0 ? 15 : 3)) == 0; 901 } 902 903 explicit constexpr 904 operator int() const noexcept 905 { return _M_y; } 906 907 constexpr bool 908 ok() const noexcept 909 { return min()._M_y <= _M_y && _M_y <= max()._M_y; } 910 911 friend constexpr bool 912 operator==(const year& __x, const year& __y) noexcept 913 { return int{__x} == int{__y}; } 914 915 friend constexpr strong_ordering 916 operator<=>(const year& __x, const year& __y) noexcept 917 { return int{__x} <=> int{__y}; } 918 919 friend constexpr year 920 operator+(const year& __x, const years& __y) noexcept 921 { return year{int{__x} + static_cast<int>(__y.count())}; } 922 923 friend constexpr year 924 operator+(const years& __x, const year& __y) noexcept 925 { return __y + __x; } 926 927 friend constexpr year 928 operator-(const year& __x, const years& __y) noexcept 929 { return __x + -__y; } 930 931 friend constexpr years 932 operator-(const year& __x, const year& __y) noexcept 933 { return years{int{__x} - int{__y}}; } 934 935 friend constexpr year_month 936 operator/(const year& __y, int __m) noexcept; 937 938 friend constexpr year_month_day 939 operator/(const year& __y, const month_day& __md) noexcept; 940 941 friend constexpr year_month_day 942 operator/(const month_day& __md, const year& __y) noexcept; 943 944 friend constexpr year_month_day_last 945 operator/(const year& __y, const month_day_last& __mdl) noexcept; 946 947 friend constexpr year_month_day_last 948 operator/(const month_day_last& __mdl, const year& __y) noexcept; 949 950 friend constexpr year_month_weekday 951 operator/(const year& __y, const month_weekday& __mwd) noexcept; 952 953 friend constexpr year_month_weekday 954 operator/(const month_weekday& __mwd, const year& __y) noexcept; 955 956 friend constexpr year_month_weekday_last 957 operator/(const year& __y, const month_weekday_last& __mwdl) noexcept; 958 959 friend constexpr year_month_weekday_last 960 operator/(const month_weekday_last& __mwdl, const year& __y) noexcept; 961 }; 962 963 // WEEKDAY 964 965 class weekday 966 { 967 private: 968 unsigned char _M_wd; 969 970 static constexpr weekday 971 _S_from_days(const days& __d) 972 { 973 return weekday{__detail::__add_modulo<7>(4, __d.count())}; 974 } 975 976 public: 977 weekday() = default; 978 979 explicit constexpr 980 weekday(unsigned __wd) noexcept 981 : _M_wd(__wd == 7 ? 0 : __wd) // __wd % 7 ? 982 { } 983 984 constexpr 985 weekday(const sys_days& __dp) noexcept 986 : weekday{_S_from_days(__dp.time_since_epoch())} 987 { } 988 989 explicit constexpr 990 weekday(const local_days& __dp) noexcept 991 : weekday{sys_days{__dp.time_since_epoch()}} 992 { } 993 994 constexpr weekday& 995 operator++() noexcept 996 { 997 *this += days{1}; 998 return *this; 999 } 1000 1001 constexpr weekday 1002 operator++(int) noexcept 1003 { 1004 auto __ret = *this; 1005 ++(*this); 1006 return __ret; 1007 } 1008 1009 constexpr weekday& 1010 operator--() noexcept 1011 { 1012 *this -= days{1}; 1013 return *this; 1014 } 1015 1016 constexpr weekday 1017 operator--(int) noexcept 1018 { 1019 auto __ret = *this; 1020 --(*this); 1021 return __ret; 1022 } 1023 1024 constexpr weekday& 1025 operator+=(const days& __d) noexcept 1026 { 1027 *this = *this + __d; 1028 return *this; 1029 } 1030 1031 constexpr weekday& 1032 operator-=(const days& __d) noexcept 1033 { 1034 *this = *this - __d; 1035 return *this; 1036 } 1037 1038 constexpr unsigned 1039 c_encoding() const noexcept 1040 { return _M_wd; } 1041 1042 constexpr unsigned 1043 iso_encoding() const noexcept 1044 { return _M_wd == 0u ? 7u : _M_wd; } 1045 1046 constexpr bool 1047 ok() const noexcept 1048 { return _M_wd <= 6; } 1049 1050 constexpr weekday_indexed 1051 operator[](unsigned __index) const noexcept; 1052 1053 constexpr weekday_last 1054 operator[](last_spec) const noexcept; 1055 1056 friend constexpr bool 1057 operator==(const weekday& __x, const weekday& __y) noexcept 1058 { return __x._M_wd == __y._M_wd; } 1059 1060 friend constexpr weekday 1061 operator+(const weekday& __x, const days& __y) noexcept 1062 { 1063 return weekday{__detail::__add_modulo<7>(__x._M_wd, __y.count())}; 1064 } 1065 1066 friend constexpr weekday 1067 operator+(const days& __x, const weekday& __y) noexcept 1068 { return __y + __x; } 1069 1070 friend constexpr weekday 1071 operator-(const weekday& __x, const days& __y) noexcept 1072 { 1073 return weekday{__detail::__sub_modulo<7>(__x._M_wd, __y.count())}; 1074 } 1075 1076 friend constexpr days 1077 operator-(const weekday& __x, const weekday& __y) noexcept 1078 { 1079 const auto __n = __x.c_encoding() - __y.c_encoding(); 1080 return static_cast<int>(__n) >= 0 ? days{__n} : days{__n + 7}; 1081 } 1082 }; 1083 1084 inline constexpr weekday Sunday{0}; 1085 inline constexpr weekday Monday{1}; 1086 inline constexpr weekday Tuesday{2}; 1087 inline constexpr weekday Wednesday{3}; 1088 inline constexpr weekday Thursday{4}; 1089 inline constexpr weekday Friday{5}; 1090 inline constexpr weekday Saturday{6}; 1091 1092 // WEEKDAY_INDEXED 1093 1094 class weekday_indexed 1095 { 1096 private: 1097 chrono::weekday _M_wd; 1098 unsigned char _M_index; 1099 1100 public: 1101 weekday_indexed() = default; 1102 1103 constexpr 1104 weekday_indexed(const chrono::weekday& __wd, unsigned __index) noexcept 1105 : _M_wd(__wd), _M_index(__index) 1106 { } 1107 1108 constexpr chrono::weekday 1109 weekday() const noexcept 1110 { return _M_wd; } 1111 1112 constexpr unsigned 1113 index() const noexcept 1114 { return _M_index; }; 1115 1116 constexpr bool 1117 ok() const noexcept 1118 { return _M_wd.ok() && 1 <= _M_index && _M_index <= 5; } 1119 1120 friend constexpr bool 1121 operator==(const weekday_indexed& __x, const weekday_indexed& __y) noexcept 1122 { return __x.weekday() == __y.weekday() && __x.index() == __y.index(); } 1123 1124 friend constexpr month_weekday 1125 operator/(const month& __m, const weekday_indexed& __wdi) noexcept; 1126 1127 friend constexpr month_weekday 1128 operator/(int __m, const weekday_indexed& __wdi) noexcept; 1129 1130 friend constexpr month_weekday 1131 operator/(const weekday_indexed& __wdi, const month& __m) noexcept; 1132 1133 friend constexpr month_weekday 1134 operator/(const weekday_indexed& __wdi, int __m) noexcept; 1135 1136 friend constexpr year_month_weekday 1137 operator/(const year_month& __ym, const weekday_indexed& __wdi) noexcept; 1138 }; 1139 1140 constexpr weekday_indexed 1141 weekday::operator[](unsigned __index) const noexcept 1142 { return {*this, __index}; } 1143 1144 // WEEKDAY_LAST 1145 1146 class weekday_last 1147 { 1148 private: 1149 chrono::weekday _M_wd; 1150 1151 public: 1152 explicit constexpr 1153 weekday_last(const chrono::weekday& __wd) noexcept 1154 : _M_wd{__wd} 1155 { } 1156 1157 constexpr chrono::weekday 1158 weekday() const noexcept 1159 { return _M_wd; } 1160 1161 constexpr bool 1162 ok() const noexcept 1163 { return _M_wd.ok(); } 1164 1165 friend constexpr bool 1166 operator==(const weekday_last& __x, const weekday_last& __y) noexcept 1167 { return __x.weekday() == __y.weekday(); } 1168 1169 friend constexpr month_weekday_last 1170 operator/(int __m, const weekday_last& __wdl) noexcept; 1171 1172 friend constexpr month_weekday_last 1173 operator/(const weekday_last& __wdl, int __m) noexcept; 1174 1175 friend constexpr year_month_weekday_last 1176 operator/(const year_month& __ym, const weekday_last& __wdl) noexcept; 1177 }; 1178 1179 constexpr weekday_last 1180 weekday::operator[](last_spec) const noexcept 1181 { return weekday_last{*this}; } 1182 1183 // MONTH_DAY 1184 1185 class month_day 1186 { 1187 private: 1188 chrono::month _M_m; 1189 chrono::day _M_d; 1190 1191 public: 1192 month_day() = default; 1193 1194 constexpr 1195 month_day(const chrono::month& __m, const chrono::day& __d) noexcept 1196 : _M_m{__m}, _M_d{__d} 1197 { } 1198 1199 constexpr chrono::month 1200 month() const noexcept 1201 { return _M_m; } 1202 1203 constexpr chrono::day 1204 day() const noexcept 1205 { return _M_d; } 1206 1207 constexpr bool 1208 ok() const noexcept 1209 { 1210 return _M_m.ok() 1211 && 1u <= unsigned(_M_d) 1212 && unsigned(_M_d) <= __detail::__days_per_month[unsigned(_M_m) - 1]; 1213 } 1214 1215 friend constexpr bool 1216 operator==(const month_day& __x, const month_day& __y) noexcept 1217 { return __x.month() == __y.month() && __x.day() == __y.day(); } 1218 1219 friend constexpr strong_ordering 1220 operator<=>(const month_day& __x, const month_day& __y) noexcept 1221 = default; 1222 1223 friend constexpr month_day 1224 operator/(const chrono::month& __m, const chrono::day& __d) noexcept 1225 { return {__m, __d}; } 1226 1227 friend constexpr month_day 1228 operator/(const chrono::month& __m, int __d) noexcept 1229 { return {__m, chrono::day(unsigned(__d))}; } 1230 1231 friend constexpr month_day 1232 operator/(int __m, const chrono::day& __d) noexcept 1233 { return {chrono::month(unsigned(__m)), __d}; } 1234 1235 friend constexpr month_day 1236 operator/(const chrono::day& __d, const chrono::month& __m) noexcept 1237 { return {__m, __d}; } 1238 1239 friend constexpr month_day 1240 operator/(const chrono::day& __d, int __m) noexcept 1241 { return {chrono::month(unsigned(__m)), __d}; } 1242 1243 friend constexpr year_month_day 1244 operator/(int __y, const month_day& __md) noexcept; 1245 1246 friend constexpr year_month_day 1247 operator/(const month_day& __md, int __y) noexcept; 1248 }; 1249 1250 // MONTH_DAY_LAST 1251 1252 class month_day_last 1253 { 1254 private: 1255 chrono::month _M_m; 1256 1257 public: 1258 explicit constexpr 1259 month_day_last(const chrono::month& __m) noexcept 1260 : _M_m{__m} 1261 { } 1262 1263 constexpr chrono::month 1264 month() const noexcept 1265 { return _M_m; } 1266 1267 constexpr bool 1268 ok() const noexcept 1269 { return _M_m.ok(); } 1270 1271 friend constexpr bool 1272 operator==(const month_day_last& __x, const month_day_last& __y) noexcept 1273 { return __x.month() == __y.month(); } 1274 1275 friend constexpr strong_ordering 1276 operator<=>(const month_day_last& __x, const month_day_last& __y) noexcept 1277 = default; 1278 1279 friend constexpr month_day_last 1280 operator/(const chrono::month& __m, last_spec) noexcept 1281 { return month_day_last{__m}; } 1282 1283 friend constexpr month_day_last 1284 operator/(int __m, last_spec) noexcept 1285 { return chrono::month(unsigned(__m)) / last; } 1286 1287 friend constexpr month_day_last 1288 operator/(last_spec, const chrono::month& __m) noexcept 1289 { return __m / last; } 1290 1291 friend constexpr month_day_last 1292 operator/(last_spec, int __m) noexcept 1293 { return __m / last; } 1294 1295 friend constexpr year_month_day_last 1296 operator/(int __y, const month_day_last& __mdl) noexcept; 1297 1298 friend constexpr year_month_day_last 1299 operator/(const month_day_last& __mdl, int __y) noexcept; 1300 }; 1301 1302 // MONTH_WEEKDAY 1303 1304 class month_weekday 1305 { 1306 private: 1307 chrono::month _M_m; 1308 chrono::weekday_indexed _M_wdi; 1309 1310 public: 1311 constexpr 1312 month_weekday(const chrono::month& __m, 1313 const chrono::weekday_indexed& __wdi) noexcept 1314 : _M_m{__m}, _M_wdi{__wdi} 1315 { } 1316 1317 constexpr chrono::month 1318 month() const noexcept 1319 { return _M_m; } 1320 1321 constexpr chrono::weekday_indexed 1322 weekday_indexed() const noexcept 1323 { return _M_wdi; } 1324 1325 constexpr bool 1326 ok() const noexcept 1327 { return _M_m.ok() && _M_wdi.ok(); } 1328 1329 friend constexpr bool 1330 operator==(const month_weekday& __x, const month_weekday& __y) noexcept 1331 { 1332 return __x.month() == __y.month() 1333 && __x.weekday_indexed() == __y.weekday_indexed(); 1334 } 1335 1336 friend constexpr month_weekday 1337 operator/(const chrono::month& __m, 1338 const chrono::weekday_indexed& __wdi) noexcept 1339 { return {__m, __wdi}; } 1340 1341 friend constexpr month_weekday 1342 operator/(int __m, const chrono::weekday_indexed& __wdi) noexcept 1343 { return chrono::month(unsigned(__m)) / __wdi; } 1344 1345 friend constexpr month_weekday 1346 operator/(const chrono::weekday_indexed& __wdi, 1347 const chrono::month& __m) noexcept 1348 { return __m / __wdi; } 1349 1350 friend constexpr month_weekday 1351 operator/(const chrono::weekday_indexed& __wdi, int __m) noexcept 1352 { return __m / __wdi; } 1353 1354 friend constexpr year_month_weekday 1355 operator/(int __y, const month_weekday& __mwd) noexcept; 1356 1357 friend constexpr year_month_weekday 1358 operator/(const month_weekday& __mwd, int __y) noexcept; 1359 }; 1360 1361 // MONTH_WEEKDAY_LAST 1362 1363 class month_weekday_last 1364 { 1365 private: 1366 chrono::month _M_m; 1367 chrono::weekday_last _M_wdl; 1368 1369 public: 1370 constexpr 1371 month_weekday_last(const chrono::month& __m, 1372 const chrono::weekday_last& __wdl) noexcept 1373 :_M_m{__m}, _M_wdl{__wdl} 1374 { } 1375 1376 constexpr chrono::month 1377 month() const noexcept 1378 { return _M_m; } 1379 1380 constexpr chrono::weekday_last 1381 weekday_last() const noexcept 1382 { return _M_wdl; } 1383 1384 constexpr bool 1385 ok() const noexcept 1386 { return _M_m.ok() && _M_wdl.ok(); } 1387 1388 friend constexpr bool 1389 operator==(const month_weekday_last& __x, 1390 const month_weekday_last& __y) noexcept 1391 { 1392 return __x.month() == __y.month() 1393 && __x.weekday_last() == __y.weekday_last(); 1394 } 1395 1396 friend constexpr month_weekday_last 1397 operator/(const chrono::month& __m, 1398 const chrono::weekday_last& __wdl) noexcept 1399 { return {__m, __wdl}; } 1400 1401 friend constexpr month_weekday_last 1402 operator/(int __m, const chrono::weekday_last& __wdl) noexcept 1403 { return chrono::month(unsigned(__m)) / __wdl; } 1404 1405 friend constexpr month_weekday_last 1406 operator/(const chrono::weekday_last& __wdl, 1407 const chrono::month& __m) noexcept 1408 { return __m / __wdl; } 1409 1410 friend constexpr month_weekday_last 1411 operator/(const chrono::weekday_last& __wdl, int __m) noexcept 1412 { return chrono::month(unsigned(__m)) / __wdl; } 1413 1414 friend constexpr year_month_weekday_last 1415 operator/(int __y, const month_weekday_last& __mwdl) noexcept; 1416 1417 friend constexpr year_month_weekday_last 1418 operator/(const month_weekday_last& __mwdl, int __y) noexcept; 1419 }; 1420 1421 // YEAR_MONTH 1422 1423 namespace __detail 1424 { 1425 // [time.cal.ym], [time.cal.ymd], etc constrain the 'months'-based 1426 // addition/subtraction operator overloads like so: 1427 // 1428 // Constraints: if the argument supplied by the caller for the months 1429 // parameter is convertible to years, its implicit conversion sequence 1430 // to years is worse than its implicit conversion sequence to months. 1431 // 1432 // We realize this constraint by templatizing the 'months'-based 1433 // overloads (using a dummy defaulted template parameter), so that 1434 // overload resolution doesn't select the 'months'-based overload unless 1435 // the implicit conversion sequence to 'months' is better than that to 1436 // 'years'. 1437 using __months_years_conversion_disambiguator = void; 1438 } 1439 1440 class year_month 1441 { 1442 private: 1443 chrono::year _M_y; 1444 chrono::month _M_m; 1445 1446 public: 1447 year_month() = default; 1448 1449 constexpr 1450 year_month(const chrono::year& __y, const chrono::month& __m) noexcept 1451 : _M_y{__y}, _M_m{__m} 1452 { } 1453 1454 constexpr chrono::year 1455 year() const noexcept 1456 { return _M_y; } 1457 1458 constexpr chrono::month 1459 month() const noexcept 1460 { return _M_m; } 1461 1462 template<typename = __detail::__months_years_conversion_disambiguator> 1463 constexpr year_month& 1464 operator+=(const months& __dm) noexcept 1465 { 1466 *this = *this + __dm; 1467 return *this; 1468 } 1469 1470 template<typename = __detail::__months_years_conversion_disambiguator> 1471 constexpr year_month& 1472 operator-=(const months& __dm) noexcept 1473 { 1474 *this = *this - __dm; 1475 return *this; 1476 } 1477 1478 constexpr year_month& 1479 operator+=(const years& __dy) noexcept 1480 { 1481 *this = *this + __dy; 1482 return *this; 1483 } 1484 1485 constexpr year_month& 1486 operator-=(const years& __dy) noexcept 1487 { 1488 *this = *this - __dy; 1489 return *this; 1490 } 1491 1492 constexpr bool 1493 ok() const noexcept 1494 { return _M_y.ok() && _M_m.ok(); } 1495 1496 friend constexpr bool 1497 operator==(const year_month& __x, const year_month& __y) noexcept 1498 { return __x.year() == __y.year() && __x.month() == __y.month(); } 1499 1500 friend constexpr strong_ordering 1501 operator<=>(const year_month& __x, const year_month& __y) noexcept 1502 = default; 1503 1504 template<typename = __detail::__months_years_conversion_disambiguator> 1505 friend constexpr year_month 1506 operator+(const year_month& __ym, const months& __dm) noexcept 1507 { 1508 // TODO: Optimize? 1509 auto __m = __ym.month() + __dm; 1510 auto __i = int(unsigned(__ym.month())) - 1 + __dm.count(); 1511 auto __y = (__i < 0 1512 ? __ym.year() + years{(__i - 11) / 12} 1513 : __ym.year() + years{__i / 12}); 1514 return __y / __m; 1515 } 1516 1517 template<typename = __detail::__months_years_conversion_disambiguator> 1518 friend constexpr year_month 1519 operator+(const months& __dm, const year_month& __ym) noexcept 1520 { return __ym + __dm; } 1521 1522 template<typename = __detail::__months_years_conversion_disambiguator> 1523 friend constexpr year_month 1524 operator-(const year_month& __ym, const months& __dm) noexcept 1525 { return __ym + -__dm; } 1526 1527 friend constexpr months 1528 operator-(const year_month& __x, const year_month& __y) noexcept 1529 { 1530 return (__x.year() - __y.year() 1531 + months{static_cast<int>(unsigned{__x.month()}) 1532 - static_cast<int>(unsigned{__y.month()})}); 1533 } 1534 1535 friend constexpr year_month 1536 operator+(const year_month& __ym, const years& __dy) noexcept 1537 { return (__ym.year() + __dy) / __ym.month(); } 1538 1539 friend constexpr year_month 1540 operator+(const years& __dy, const year_month& __ym) noexcept 1541 { return __ym + __dy; } 1542 1543 friend constexpr year_month 1544 operator-(const year_month& __ym, const years& __dy) noexcept 1545 { return __ym + -__dy; } 1546 1547 friend constexpr year_month 1548 operator/(const chrono::year& __y, const chrono::month& __m) noexcept 1549 { return {__y, __m}; } 1550 1551 friend constexpr year_month 1552 operator/(const chrono::year& __y, int __m) noexcept 1553 { return {__y, chrono::month(unsigned(__m))}; } 1554 1555 friend constexpr year_month_day 1556 operator/(const year_month& __ym, int __d) noexcept; 1557 1558 friend constexpr year_month_day_last 1559 operator/(const year_month& __ym, last_spec) noexcept; 1560 }; 1561 1562 // YEAR_MONTH_DAY 1563 1564 class year_month_day 1565 { 1566 private: 1567 chrono::year _M_y; 1568 chrono::month _M_m; 1569 chrono::day _M_d; 1570 1571 static constexpr year_month_day _S_from_days(const days& __dp) noexcept; 1572 1573 constexpr days _M_days_since_epoch() const noexcept; 1574 1575 public: 1576 year_month_day() = default; 1577 1578 constexpr 1579 year_month_day(const chrono::year& __y, const chrono::month& __m, 1580 const chrono::day& __d) noexcept 1581 : _M_y{__y}, _M_m{__m}, _M_d{__d} 1582 { } 1583 1584 constexpr 1585 year_month_day(const year_month_day_last& __ymdl) noexcept; 1586 1587 constexpr 1588 year_month_day(const sys_days& __dp) noexcept 1589 : year_month_day(_S_from_days(__dp.time_since_epoch())) 1590 { } 1591 1592 explicit constexpr 1593 year_month_day(const local_days& __dp) noexcept 1594 : year_month_day(sys_days{__dp.time_since_epoch()}) 1595 { } 1596 1597 template<typename = __detail::__months_years_conversion_disambiguator> 1598 constexpr year_month_day& 1599 operator+=(const months& __m) noexcept 1600 { 1601 *this = *this + __m; 1602 return *this; 1603 } 1604 1605 template<typename = __detail::__months_years_conversion_disambiguator> 1606 constexpr year_month_day& 1607 operator-=(const months& __m) noexcept 1608 { 1609 *this = *this - __m; 1610 return *this; 1611 } 1612 1613 constexpr year_month_day& 1614 operator+=(const years& __y) noexcept 1615 { 1616 *this = *this + __y; 1617 return *this; 1618 } 1619 1620 constexpr year_month_day& 1621 operator-=(const years& __y) noexcept 1622 { 1623 *this = *this - __y; 1624 return *this; 1625 } 1626 1627 constexpr chrono::year 1628 year() const noexcept 1629 { return _M_y; } 1630 1631 constexpr chrono::month 1632 month() const noexcept 1633 { return _M_m; } 1634 1635 constexpr chrono::day 1636 day() const noexcept 1637 { return _M_d; } 1638 1639 constexpr 1640 operator sys_days() const noexcept 1641 { return sys_days{_M_days_since_epoch()}; } 1642 1643 explicit constexpr 1644 operator local_days() const noexcept 1645 { return local_days{sys_days{*this}.time_since_epoch()}; } 1646 1647 constexpr bool ok() const noexcept; 1648 1649 friend constexpr bool 1650 operator==(const year_month_day& __x, const year_month_day& __y) noexcept 1651 { 1652 return __x.year() == __y.year() 1653 && __x.month() == __y.month() 1654 && __x.day() == __y.day(); 1655 } 1656 1657 friend constexpr strong_ordering 1658 operator<=>(const year_month_day& __x, const year_month_day& __y) noexcept 1659 = default; 1660 1661 template<typename = __detail::__months_years_conversion_disambiguator> 1662 friend constexpr year_month_day 1663 operator+(const year_month_day& __ymd, const months& __dm) noexcept 1664 { return (__ymd.year() / __ymd.month() + __dm) / __ymd.day(); } 1665 1666 template<typename = __detail::__months_years_conversion_disambiguator> 1667 friend constexpr year_month_day 1668 operator+(const months& __dm, const year_month_day& __ymd) noexcept 1669 { return __ymd + __dm; } 1670 1671 friend constexpr year_month_day 1672 operator+(const year_month_day& __ymd, const years& __dy) noexcept 1673 { return (__ymd.year() + __dy) / __ymd.month() / __ymd.day(); } 1674 1675 friend constexpr year_month_day 1676 operator+(const years& __dy, const year_month_day& __ymd) noexcept 1677 { return __ymd + __dy; } 1678 1679 template<typename = __detail::__months_years_conversion_disambiguator> 1680 friend constexpr year_month_day 1681 operator-(const year_month_day& __ymd, const months& __dm) noexcept 1682 { return __ymd + -__dm; } 1683 1684 friend constexpr year_month_day 1685 operator-(const year_month_day& __ymd, const years& __dy) noexcept 1686 { return __ymd + -__dy; } 1687 1688 friend constexpr year_month_day 1689 operator/(const year_month& __ym, const chrono::day& __d) noexcept 1690 { return {__ym.year(), __ym.month(), __d}; } 1691 1692 friend constexpr year_month_day 1693 operator/(const year_month& __ym, int __d) noexcept 1694 { return __ym / chrono::day{unsigned(__d)}; } 1695 1696 friend constexpr year_month_day 1697 operator/(const chrono::year& __y, const month_day& __md) noexcept 1698 { return __y / __md.month() / __md.day(); } 1699 1700 friend constexpr year_month_day 1701 operator/(int __y, const month_day& __md) noexcept 1702 { return chrono::year{__y} / __md; } 1703 1704 friend constexpr year_month_day 1705 operator/(const month_day& __md, const chrono::year& __y) noexcept 1706 { return __y / __md; } 1707 1708 friend constexpr year_month_day 1709 operator/(const month_day& __md, int __y) noexcept 1710 { return chrono::year(__y) / __md; } 1711 }; 1712 1713 // Construct from days since 1970/01/01. 1714 // Proposition 6.3 of Neri and Schneider, 1715 // "Euclidean Affine Functions and Applications to Calendar Algorithms". 1716 // https://arxiv.org/abs/2102.06959 1717 constexpr year_month_day 1718 year_month_day::_S_from_days(const days& __dp) noexcept 1719 { 1720 constexpr auto __z2 = static_cast<uint32_t>(-1468000); 1721 constexpr auto __r2_e3 = static_cast<uint32_t>(536895458); 1722 1723 const auto __r0 = static_cast<uint32_t>(__dp.count()) + __r2_e3; 1724 1725 const auto __n1 = 4 * __r0 + 3; 1726 const auto __q1 = __n1 / 146097; 1727 const auto __r1 = __n1 % 146097 / 4; 1728 1729 constexpr auto __p32 = static_cast<uint64_t>(1) << 32; 1730 const auto __n2 = 4 * __r1 + 3; 1731 const auto __u2 = static_cast<uint64_t>(2939745) * __n2; 1732 const auto __q2 = static_cast<uint32_t>(__u2 / __p32); 1733 const auto __r2 = static_cast<uint32_t>(__u2 % __p32) / 2939745 / 4; 1734 1735 constexpr auto __p16 = static_cast<uint32_t>(1) << 16; 1736 const auto __n3 = 2141 * __r2 + 197913; 1737 const auto __q3 = __n3 / __p16; 1738 const auto __r3 = __n3 % __p16 / 2141; 1739 1740 const auto __y0 = 100 * __q1 + __q2; 1741 const auto __m0 = __q3; 1742 const auto __d0 = __r3; 1743 1744 const auto __j = __r2 >= 306; 1745 const auto __y1 = __y0 + __j; 1746 const auto __m1 = __j ? __m0 - 12 : __m0; 1747 const auto __d1 = __d0 + 1; 1748 1749 return year_month_day{chrono::year{static_cast<int>(__y1 + __z2)}, 1750 chrono::month{__m1}, chrono::day{__d1}}; 1751 } 1752 1753 // Days since 1970/01/01. 1754 // Proposition 6.2 of Neri and Schneider, 1755 // "Euclidean Affine Functions and Applications to Calendar Algorithms". 1756 // https://arxiv.org/abs/2102.06959 1757 constexpr days 1758 year_month_day::_M_days_since_epoch() const noexcept 1759 { 1760 auto constexpr __z2 = static_cast<uint32_t>(-1468000); 1761 auto constexpr __r2_e3 = static_cast<uint32_t>(536895458); 1762 1763 const auto __y1 = static_cast<uint32_t>(static_cast<int>(_M_y)) - __z2; 1764 const auto __m1 = static_cast<uint32_t>(static_cast<unsigned>(_M_m)); 1765 const auto __d1 = static_cast<uint32_t>(static_cast<unsigned>(_M_d)); 1766 1767 const auto __j = static_cast<uint32_t>(__m1 < 3); 1768 const auto __y0 = __y1 - __j; 1769 const auto __m0 = __j ? __m1 + 12 : __m1; 1770 const auto __d0 = __d1 - 1; 1771 1772 const auto __q1 = __y0 / 100; 1773 const auto __yc = 1461 * __y0 / 4 - __q1 + __q1 / 4; 1774 const auto __mc = (979 *__m0 - 2919) / 32; 1775 const auto __dc = __d0; 1776 1777 return days{static_cast<int32_t>(__yc + __mc + __dc - __r2_e3)}; 1778 } 1779 1780 // YEAR_MONTH_DAY_LAST 1781 1782 class year_month_day_last 1783 { 1784 private: 1785 chrono::year _M_y; 1786 chrono::month_day_last _M_mdl; 1787 1788 public: 1789 constexpr 1790 year_month_day_last(const chrono::year& __y, 1791 const chrono::month_day_last& __mdl) noexcept 1792 : _M_y{__y}, _M_mdl{__mdl} 1793 { } 1794 1795 template<typename = __detail::__months_years_conversion_disambiguator> 1796 constexpr year_month_day_last& 1797 operator+=(const months& __m) noexcept 1798 { 1799 *this = *this + __m; 1800 return *this; 1801 } 1802 1803 template<typename = __detail::__months_years_conversion_disambiguator> 1804 constexpr year_month_day_last& 1805 operator-=(const months& __m) noexcept 1806 { 1807 *this = *this - __m; 1808 return *this; 1809 } 1810 1811 constexpr year_month_day_last& 1812 operator+=(const years& __y) noexcept 1813 { 1814 *this = *this + __y; 1815 return *this; 1816 } 1817 1818 constexpr year_month_day_last& 1819 operator-=(const years& __y) noexcept 1820 { 1821 *this = *this - __y; 1822 return *this; 1823 } 1824 1825 constexpr chrono::year 1826 year() const noexcept 1827 { return _M_y; } 1828 1829 constexpr chrono::month 1830 month() const noexcept 1831 { return _M_mdl.month(); } 1832 1833 constexpr chrono::month_day_last 1834 month_day_last() const noexcept 1835 { return _M_mdl; } 1836 1837 // Return A day representing the last day of this year, month pair. 1838 constexpr chrono::day 1839 day() const noexcept 1840 { 1841 const auto __m = static_cast<unsigned>(month()); 1842 1843 // The result is unspecified if __m < 1 or __m > 12. Hence, assume 1844 // 1 <= __m <= 12. For __m != 2, day() == 30 or day() == 31 or, in 1845 // other words, day () == 30 | b, where b is in {0, 1}. 1846 1847 // If __m in {1, 3, 4, 5, 6, 7}, then b is 1 if, and only if, __m is 1848 // odd. Hence, b = __m & 1 = (__m ^ 0) & 1. 1849 1850 // If __m in {8, 9, 10, 11, 12}, then b is 1 if, and only if, __m is 1851 // even. Hence, b = (__m ^ 1) & 1. 1852 1853 // Therefore, b = (__m ^ c) & 1, where c = 0, if __m < 8, or c = 1 if 1854 // __m >= 8, that is, c = __m >> 3. 1855 1856 // Since 30 = (11110)_2 and __m <= 31 = (11111)_2, the "& 1" in b's 1857 // calculation is unnecessary. 1858 1859 // The performance of this implementation does not depend on look-up 1860 // tables being on the L1 cache. 1861 return chrono::day{__m != 2 ? (__m ^ (__m >> 3)) | 30 1862 : _M_y.is_leap() ? 29 : 28}; 1863 } 1864 1865 constexpr 1866 operator sys_days() const noexcept 1867 { return sys_days{year() / month() / day()}; } 1868 1869 explicit constexpr 1870 operator local_days() const noexcept 1871 { return local_days{sys_days{*this}.time_since_epoch()}; } 1872 1873 constexpr bool 1874 ok() const noexcept 1875 { return _M_y.ok() && _M_mdl.ok(); } 1876 1877 friend constexpr bool 1878 operator==(const year_month_day_last& __x, 1879 const year_month_day_last& __y) noexcept 1880 { 1881 return __x.year() == __y.year() 1882 && __x.month_day_last() == __y.month_day_last(); 1883 } 1884 1885 friend constexpr strong_ordering 1886 operator<=>(const year_month_day_last& __x, 1887 const year_month_day_last& __y) noexcept 1888 = default; 1889 1890 template<typename = __detail::__months_years_conversion_disambiguator> 1891 friend constexpr year_month_day_last 1892 operator+(const year_month_day_last& __ymdl, 1893 const months& __dm) noexcept 1894 { return (__ymdl.year() / __ymdl.month() + __dm) / last; } 1895 1896 template<typename = __detail::__months_years_conversion_disambiguator> 1897 friend constexpr year_month_day_last 1898 operator+(const months& __dm, 1899 const year_month_day_last& __ymdl) noexcept 1900 { return __ymdl + __dm; } 1901 1902 template<typename = __detail::__months_years_conversion_disambiguator> 1903 friend constexpr year_month_day_last 1904 operator-(const year_month_day_last& __ymdl, 1905 const months& __dm) noexcept 1906 { return __ymdl + -__dm; } 1907 1908 friend constexpr year_month_day_last 1909 operator+(const year_month_day_last& __ymdl, 1910 const years& __dy) noexcept 1911 { return {__ymdl.year() + __dy, __ymdl.month_day_last()}; } 1912 1913 friend constexpr year_month_day_last 1914 operator+(const years& __dy, 1915 const year_month_day_last& __ymdl) noexcept 1916 { return __ymdl + __dy; } 1917 1918 friend constexpr year_month_day_last 1919 operator-(const year_month_day_last& __ymdl, 1920 const years& __dy) noexcept 1921 { return __ymdl + -__dy; } 1922 1923 friend constexpr year_month_day_last 1924 operator/(const year_month& __ym, last_spec) noexcept 1925 { return {__ym.year(), chrono::month_day_last{__ym.month()}}; } 1926 1927 friend constexpr year_month_day_last 1928 operator/(const chrono::year& __y, 1929 const chrono::month_day_last& __mdl) noexcept 1930 { return {__y, __mdl}; } 1931 1932 friend constexpr year_month_day_last 1933 operator/(int __y, const chrono::month_day_last& __mdl) noexcept 1934 { return chrono::year(__y) / __mdl; } 1935 1936 friend constexpr year_month_day_last 1937 operator/(const chrono::month_day_last& __mdl, 1938 const chrono::year& __y) noexcept 1939 { return __y / __mdl; } 1940 1941 friend constexpr year_month_day_last 1942 operator/(const chrono::month_day_last& __mdl, int __y) noexcept 1943 { return chrono::year(__y) / __mdl; } 1944 }; 1945 1946 // year_month_day ctor from year_month_day_last 1947 constexpr 1948 year_month_day::year_month_day(const year_month_day_last& __ymdl) noexcept 1949 : _M_y{__ymdl.year()}, _M_m{__ymdl.month()}, _M_d{__ymdl.day()} 1950 { } 1951 1952 constexpr bool 1953 year_month_day::ok() const noexcept 1954 { 1955 if (!_M_y.ok() || !_M_m.ok()) 1956 return false; 1957 return chrono::day{1} <= _M_d && _M_d <= (_M_y / _M_m / last).day(); 1958 } 1959 1960 // YEAR_MONTH_WEEKDAY 1961 1962 class year_month_weekday 1963 { 1964 private: 1965 chrono::year _M_y; 1966 chrono::month _M_m; 1967 chrono::weekday_indexed _M_wdi; 1968 1969 static constexpr year_month_weekday 1970 _S_from_sys_days(const sys_days& __dp) 1971 { 1972 year_month_day __ymd{__dp}; 1973 chrono::weekday __wd{__dp}; 1974 auto __index = __wd[(unsigned{__ymd.day()} - 1) / 7 + 1]; 1975 return {__ymd.year(), __ymd.month(), __index}; 1976 } 1977 1978 public: 1979 year_month_weekday() = default; 1980 1981 constexpr 1982 year_month_weekday(const chrono::year& __y, const chrono::month& __m, 1983 const chrono::weekday_indexed& __wdi) noexcept 1984 : _M_y{__y}, _M_m{__m}, _M_wdi{__wdi} 1985 { } 1986 1987 constexpr 1988 year_month_weekday(const sys_days& __dp) noexcept 1989 : year_month_weekday{_S_from_sys_days(__dp)} 1990 { } 1991 1992 explicit constexpr 1993 year_month_weekday(const local_days& __dp) noexcept 1994 : year_month_weekday{sys_days{__dp.time_since_epoch()}} 1995 { } 1996 1997 template<typename = __detail::__months_years_conversion_disambiguator> 1998 constexpr year_month_weekday& 1999 operator+=(const months& __m) noexcept 2000 { 2001 *this = *this + __m; 2002 return *this; 2003 } 2004 2005 template<typename = __detail::__months_years_conversion_disambiguator> 2006 constexpr year_month_weekday& 2007 operator-=(const months& __m) noexcept 2008 { 2009 *this = *this - __m; 2010 return *this; 2011 } 2012 2013 constexpr year_month_weekday& 2014 operator+=(const years& __y) noexcept 2015 { 2016 *this = *this + __y; 2017 return *this; 2018 } 2019 2020 constexpr year_month_weekday& 2021 operator-=(const years& __y) noexcept 2022 { 2023 *this = *this - __y; 2024 return *this; 2025 } 2026 2027 constexpr chrono::year 2028 year() const noexcept 2029 { return _M_y; } 2030 2031 constexpr chrono::month 2032 month() const noexcept 2033 { return _M_m; } 2034 2035 constexpr chrono::weekday 2036 weekday() const noexcept 2037 { return _M_wdi.weekday(); } 2038 2039 constexpr unsigned 2040 index() const noexcept 2041 { return _M_wdi.index(); } 2042 2043 constexpr chrono::weekday_indexed 2044 weekday_indexed() const noexcept 2045 { return _M_wdi; } 2046 2047 constexpr 2048 operator sys_days() const noexcept 2049 { 2050 auto __d = sys_days{year() / month() / 1}; 2051 return __d + (weekday() - chrono::weekday(__d) 2052 + days{(static_cast<int>(index())-1)*7}); 2053 } 2054 2055 explicit constexpr 2056 operator local_days() const noexcept 2057 { return local_days{sys_days{*this}.time_since_epoch()}; } 2058 2059 constexpr bool 2060 ok() const noexcept 2061 { 2062 if (!_M_y.ok() || !_M_m.ok() || !_M_wdi.ok()) 2063 return false; 2064 if (_M_wdi.index() <= 4) 2065 return true; 2066 days __d = (_M_wdi.weekday() 2067 - chrono::weekday{sys_days{_M_y / _M_m / 1}} 2068 + days((_M_wdi.index()-1)*7 + 1)); 2069 __glibcxx_assert(__d.count() >= 1); 2070 return (unsigned)__d.count() <= (unsigned)(_M_y / _M_m / last).day(); 2071 } 2072 2073 friend constexpr bool 2074 operator==(const year_month_weekday& __x, 2075 const year_month_weekday& __y) noexcept 2076 { 2077 return __x.year() == __y.year() 2078 && __x.month() == __y.month() 2079 && __x.weekday_indexed() == __y.weekday_indexed(); 2080 } 2081 2082 template<typename = __detail::__months_years_conversion_disambiguator> 2083 friend constexpr year_month_weekday 2084 operator+(const year_month_weekday& __ymwd, const months& __dm) noexcept 2085 { 2086 return ((__ymwd.year() / __ymwd.month() + __dm) 2087 / __ymwd.weekday_indexed()); 2088 } 2089 2090 template<typename = __detail::__months_years_conversion_disambiguator> 2091 friend constexpr year_month_weekday 2092 operator+(const months& __dm, const year_month_weekday& __ymwd) noexcept 2093 { return __ymwd + __dm; } 2094 2095 friend constexpr year_month_weekday 2096 operator+(const year_month_weekday& __ymwd, const years& __dy) noexcept 2097 { return {__ymwd.year() + __dy, __ymwd.month(), __ymwd.weekday_indexed()}; } 2098 2099 friend constexpr year_month_weekday 2100 operator+(const years& __dy, const year_month_weekday& __ymwd) noexcept 2101 { return __ymwd + __dy; } 2102 2103 template<typename = __detail::__months_years_conversion_disambiguator> 2104 friend constexpr year_month_weekday 2105 operator-(const year_month_weekday& __ymwd, const months& __dm) noexcept 2106 { return __ymwd + -__dm; } 2107 2108 friend constexpr year_month_weekday 2109 operator-(const year_month_weekday& __ymwd, const years& __dy) noexcept 2110 { return __ymwd + -__dy; } 2111 2112 friend constexpr year_month_weekday 2113 operator/(const year_month& __ym, 2114 const chrono::weekday_indexed& __wdi) noexcept 2115 { return {__ym.year(), __ym.month(), __wdi}; } 2116 2117 friend constexpr year_month_weekday 2118 operator/(const chrono::year& __y, const month_weekday& __mwd) noexcept 2119 { return {__y, __mwd.month(), __mwd.weekday_indexed()}; } 2120 2121 friend constexpr year_month_weekday 2122 operator/(int __y, const month_weekday& __mwd) noexcept 2123 { return chrono::year(__y) / __mwd; } 2124 2125 friend constexpr year_month_weekday 2126 operator/(const month_weekday& __mwd, const chrono::year& __y) noexcept 2127 { return __y / __mwd; } 2128 2129 friend constexpr year_month_weekday 2130 operator/(const month_weekday& __mwd, int __y) noexcept 2131 { return chrono::year(__y) / __mwd; } 2132 }; 2133 2134 // YEAR_MONTH_WEEKDAY_LAST 2135 2136 class year_month_weekday_last 2137 { 2138 private: 2139 chrono::year _M_y; 2140 chrono::month _M_m; 2141 chrono::weekday_last _M_wdl; 2142 2143 public: 2144 constexpr 2145 year_month_weekday_last(const chrono::year& __y, const chrono::month& __m, 2146 const chrono::weekday_last& __wdl) noexcept 2147 : _M_y{__y}, _M_m{__m}, _M_wdl{__wdl} 2148 { } 2149 2150 template<typename = __detail::__months_years_conversion_disambiguator> 2151 constexpr year_month_weekday_last& 2152 operator+=(const months& __m) noexcept 2153 { 2154 *this = *this + __m; 2155 return *this; 2156 } 2157 2158 template<typename = __detail::__months_years_conversion_disambiguator> 2159 constexpr year_month_weekday_last& 2160 operator-=(const months& __m) noexcept 2161 { 2162 *this = *this - __m; 2163 return *this; 2164 } 2165 2166 constexpr year_month_weekday_last& 2167 operator+=(const years& __y) noexcept 2168 { 2169 *this = *this + __y; 2170 return *this; 2171 } 2172 2173 constexpr year_month_weekday_last& 2174 operator-=(const years& __y) noexcept 2175 { 2176 *this = *this - __y; 2177 return *this; 2178 } 2179 2180 constexpr chrono::year 2181 year() const noexcept 2182 { return _M_y; } 2183 2184 constexpr chrono::month 2185 month() const noexcept 2186 { return _M_m; } 2187 2188 constexpr chrono::weekday 2189 weekday() const noexcept 2190 { return _M_wdl.weekday(); } 2191 2192 constexpr chrono::weekday_last 2193 weekday_last() const noexcept 2194 { return _M_wdl; } 2195 2196 constexpr 2197 operator sys_days() const noexcept 2198 { 2199 const auto __d = sys_days{_M_y / _M_m / last}; 2200 return sys_days{(__d - (chrono::weekday{__d} 2201 - _M_wdl.weekday())).time_since_epoch()}; 2202 } 2203 2204 explicit constexpr 2205 operator local_days() const noexcept 2206 { return local_days{sys_days{*this}.time_since_epoch()}; } 2207 2208 constexpr bool 2209 ok() const noexcept 2210 { return _M_y.ok() && _M_m.ok() && _M_wdl.ok(); } 2211 2212 friend constexpr bool 2213 operator==(const year_month_weekday_last& __x, 2214 const year_month_weekday_last& __y) noexcept 2215 { 2216 return __x.year() == __y.year() 2217 && __x.month() == __y.month() 2218 && __x.weekday_last() == __y.weekday_last(); 2219 } 2220 2221 template<typename = __detail::__months_years_conversion_disambiguator> 2222 friend constexpr year_month_weekday_last 2223 operator+(const year_month_weekday_last& __ymwdl, 2224 const months& __dm) noexcept 2225 { 2226 return ((__ymwdl.year() / __ymwdl.month() + __dm) 2227 / __ymwdl.weekday_last()); 2228 } 2229 2230 template<typename = __detail::__months_years_conversion_disambiguator> 2231 friend constexpr year_month_weekday_last 2232 operator+(const months& __dm, 2233 const year_month_weekday_last& __ymwdl) noexcept 2234 { return __ymwdl + __dm; } 2235 2236 friend constexpr year_month_weekday_last 2237 operator+(const year_month_weekday_last& __ymwdl, 2238 const years& __dy) noexcept 2239 { return {__ymwdl.year() + __dy, __ymwdl.month(), __ymwdl.weekday_last()}; } 2240 2241 friend constexpr year_month_weekday_last 2242 operator+(const years& __dy, 2243 const year_month_weekday_last& __ymwdl) noexcept 2244 { return __ymwdl + __dy; } 2245 2246 template<typename = __detail::__months_years_conversion_disambiguator> 2247 friend constexpr year_month_weekday_last 2248 operator-(const year_month_weekday_last& __ymwdl, 2249 const months& __dm) noexcept 2250 { return __ymwdl + -__dm; } 2251 2252 friend constexpr year_month_weekday_last 2253 operator-(const year_month_weekday_last& __ymwdl, 2254 const years& __dy) noexcept 2255 { return __ymwdl + -__dy; } 2256 2257 friend constexpr year_month_weekday_last 2258 operator/(const year_month& __ym, 2259 const chrono::weekday_last& __wdl) noexcept 2260 { return {__ym.year(), __ym.month(), __wdl}; } 2261 2262 friend constexpr year_month_weekday_last 2263 operator/(const chrono::year& __y, 2264 const chrono::month_weekday_last& __mwdl) noexcept 2265 { return {__y, __mwdl.month(), __mwdl.weekday_last()}; } 2266 2267 friend constexpr year_month_weekday_last 2268 operator/(int __y, const chrono::month_weekday_last& __mwdl) noexcept 2269 { return chrono::year(__y) / __mwdl; } 2270 2271 friend constexpr year_month_weekday_last 2272 operator/(const chrono::month_weekday_last& __mwdl, 2273 const chrono::year& __y) noexcept 2274 { return __y / __mwdl; } 2275 2276 friend constexpr year_month_weekday_last 2277 operator/(const chrono::month_weekday_last& __mwdl, int __y) noexcept 2278 { return chrono::year(__y) / __mwdl; } 2279 }; 2280 2281 // HH_MM_SS 2282 2283 /// @cond undocumented 2284 namespace __detail 2285 { 2286 consteval long long 2287 __pow10(unsigned __n) 2288 { 2289 long long __r = 1; 2290 while (__n-- > 0) 2291 __r *= 10; 2292 return __r; 2293 } 2294 2295 template<typename _Duration> struct __utc_leap_second; 2296 } 2297 /// @endcond 2298 2299 /** Utility for splitting a duration into hours, minutes, and seconds 2300 * 2301 * This is a convenience type that provides accessors for the constituent 2302 * parts (hours, minutes, seconds and subseconds) of a duration. 2303 * 2304 * @since C++20 2305 */ 2306 template<typename _Duration> 2307 class hh_mm_ss 2308 { 2309 static_assert( __is_duration<_Duration>::value ); 2310 2311 private: 2312 static consteval int 2313 _S_fractional_width() 2314 { 2315 auto __den = _Duration::period::den; 2316 const int __multiplicity_2 = std::__countr_zero((uintmax_t)__den); 2317 __den >>= __multiplicity_2; 2318 int __multiplicity_5 = 0; 2319 while ((__den % 5) == 0) 2320 { 2321 ++__multiplicity_5; 2322 __den /= 5; 2323 } 2324 if (__den != 1) 2325 return 6; 2326 2327 int __width = (__multiplicity_2 > __multiplicity_5 2328 ? __multiplicity_2 : __multiplicity_5); 2329 if (__width > 18) 2330 __width = 18; 2331 return __width; 2332 } 2333 2334 constexpr 2335 hh_mm_ss(_Duration __d, bool __is_neg) 2336 : _M_h (duration_cast<chrono::hours>(__d)), 2337 _M_m (duration_cast<chrono::minutes>(__d - hours())), 2338 _M_s (duration_cast<chrono::seconds>(__d - hours() - minutes())), 2339 _M_is_neg(__is_neg) 2340 { 2341 auto __ss = __d - hours() - minutes() - seconds(); 2342 if constexpr (treat_as_floating_point_v<typename precision::rep>) 2343 _M_ss._M_r = __ss.count(); 2344 else if constexpr (precision::period::den != 1) 2345 _M_ss._M_r = duration_cast<precision>(__ss).count(); 2346 } 2347 2348 static constexpr _Duration 2349 _S_abs(_Duration __d) 2350 { 2351 if constexpr (numeric_limits<typename _Duration::rep>::is_signed) 2352 return chrono::abs(__d); 2353 else 2354 return __d; 2355 } 2356 2357 public: 2358 static constexpr unsigned fractional_width = {_S_fractional_width()}; 2359 2360 using precision 2361 = duration<common_type_t<typename _Duration::rep, 2362 chrono::seconds::rep>, 2363 ratio<1, __detail::__pow10(fractional_width)>>; 2364 2365 constexpr hh_mm_ss() noexcept = default; 2366 2367 constexpr explicit 2368 hh_mm_ss(_Duration __d) 2369 : hh_mm_ss(_S_abs(__d), __d < _Duration::zero()) 2370 { } 2371 2372 constexpr bool 2373 is_negative() const noexcept 2374 { 2375 if constexpr (!_S_is_unsigned) 2376 return _M_is_neg; 2377 else 2378 return false; 2379 } 2380 2381 constexpr chrono::hours 2382 hours() const noexcept 2383 { return _M_h; } 2384 2385 constexpr chrono::minutes 2386 minutes() const noexcept 2387 { return _M_m; } 2388 2389 constexpr chrono::seconds 2390 seconds() const noexcept 2391 { return _M_s; } 2392 2393 constexpr precision 2394 subseconds() const noexcept 2395 { return static_cast<precision>(_M_ss); } 2396 2397 constexpr explicit 2398 operator precision() const noexcept 2399 { return to_duration(); } 2400 2401 constexpr precision 2402 to_duration() const noexcept 2403 { 2404 if constexpr (!_S_is_unsigned) 2405 if (_M_is_neg) 2406 return -(_M_h + _M_m + _M_s + subseconds()); 2407 return _M_h + _M_m + _M_s + subseconds(); 2408 } 2409 2410 private: 2411 static constexpr bool _S_is_unsigned 2412 = __and_v<is_integral<typename _Duration::rep>, 2413 is_unsigned<typename _Duration::rep>>; 2414 2415 template<typename _Ratio> 2416 using __byte_duration = duration<unsigned char, _Ratio>; 2417 2418 // The type of the _M_ss member that holds the subsecond precision. 2419 template<typename _Dur> 2420 struct __subseconds 2421 { 2422 typename _Dur::rep _M_r{}; 2423 2424 constexpr explicit 2425 operator _Dur() const noexcept 2426 { return _Dur(_M_r); } 2427 }; 2428 2429 // An empty class if this precision doesn't need subseconds. 2430 template<typename _Rep> 2431 requires (!treat_as_floating_point_v<_Rep>) 2432 struct __subseconds<duration<_Rep, ratio<1>>> 2433 { 2434 constexpr explicit 2435 operator duration<_Rep, ratio<1>>() const noexcept 2436 { return {}; } 2437 }; 2438 2439 template<typename _Rep, typename _Period> 2440 requires (!treat_as_floating_point_v<_Rep>) 2441 && ratio_less_v<_Period, ratio<1, 1>> 2442 && ratio_greater_equal_v<_Period, ratio<1, 250>> 2443 struct __subseconds<duration<_Rep, _Period>> 2444 { 2445 unsigned char _M_r{}; 2446 2447 constexpr explicit 2448 operator duration<_Rep, _Period>() const noexcept 2449 { return duration<_Rep, _Period>(_M_r); } 2450 }; 2451 2452 template<typename _Rep, typename _Period> 2453 requires (!treat_as_floating_point_v<_Rep>) 2454 && ratio_less_v<_Period, ratio<1, 250>> 2455 && ratio_greater_equal_v<_Period, ratio<1, 4000000000>> 2456 struct __subseconds<duration<_Rep, _Period>> 2457 { 2458 uint_least32_t _M_r{}; 2459 2460 constexpr explicit 2461 operator duration<_Rep, _Period>() const noexcept 2462 { return duration<_Rep, _Period>(_M_r); } 2463 }; 2464 2465 chrono::hours _M_h{}; 2466 __byte_duration<ratio<60>> _M_m{}; 2467 __byte_duration<ratio<1>> _M_s{}; 2468 bool _M_is_neg{}; 2469 __subseconds<precision> _M_ss{}; 2470 2471 template<typename> friend struct __detail::__utc_leap_second; 2472 }; 2473 2474 /// @cond undocumented 2475 namespace __detail 2476 { 2477 // Represents a time that is within a leap second insertion. 2478 template<typename _Duration> 2479 struct __utc_leap_second 2480 { 2481 explicit 2482 __utc_leap_second(const sys_time<_Duration>& __s) 2483 : _M_date(chrono::floor<days>(__s)), _M_time(__s - _M_date) 2484 { 2485 ++_M_time._M_s; 2486 } 2487 2488 sys_days _M_date; 2489 hh_mm_ss<common_type_t<_Duration, days>> _M_time; 2490 }; 2491 } 2492 /// @endcond 2493 2494 // 12/24 HOURS FUNCTIONS 2495 2496 constexpr bool 2497 is_am(const hours& __h) noexcept 2498 { return 0h <= __h && __h <= 11h; } 2499 2500 constexpr bool 2501 is_pm(const hours& __h) noexcept 2502 { return 12h <= __h && __h <= 23h; } 2503 2504 constexpr hours 2505 make12(const hours& __h) noexcept 2506 { 2507 if (__h == 0h) 2508 return 12h; 2509 else if (__h > 12h) 2510 return __h - 12h; 2511 return __h; 2512 } 2513 2514 constexpr hours 2515 make24(const hours& __h, bool __is_pm) noexcept 2516 { 2517 if (!__is_pm) 2518 { 2519 if (__h == 12h) 2520 return 0h; 2521 else 2522 return __h; 2523 } 2524 else 2525 { 2526 if (__h == 12h) 2527 return __h; 2528 else 2529 return __h + 12h; 2530 } 2531 } 2532 2533 #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI 2534 // C++20 [time.zones] Time zones 2535 2536 struct tzdb; 2537 2538 struct sys_info 2539 { 2540 sys_seconds begin; 2541 sys_seconds end; 2542 seconds offset; 2543 minutes save; 2544 string abbrev; 2545 }; 2546 2547 struct local_info 2548 { 2549 static constexpr int unique = 0; 2550 static constexpr int nonexistent = 1; 2551 static constexpr int ambiguous = 2; 2552 2553 int result; 2554 sys_info first; 2555 sys_info second; 2556 }; 2557 2558 class nonexistent_local_time : public runtime_error 2559 { 2560 public: 2561 template<typename _Duration> 2562 nonexistent_local_time(const local_time<_Duration>& __tp, 2563 const local_info& __i) 2564 : runtime_error(_S_make_what_str(__tp, __i)) 2565 { __glibcxx_assert(__i.result == local_info::nonexistent); } 2566 2567 private: 2568 template<typename _Duration> 2569 static string 2570 _S_make_what_str(const local_time<_Duration>& __tp, 2571 const local_info& __i) 2572 { 2573 std::ostringstream __os; 2574 __os << __tp << " is in a gap between\n" 2575 << local_seconds(__i.first.end.time_since_epoch()) 2576 + __i.first.offset << ' ' << __i.first.abbrev << " and\n" 2577 << local_seconds(__i.second.begin.time_since_epoch()) 2578 + __i.second.offset << ' ' << __i.second.abbrev 2579 << " which are both equivalent to\n" 2580 << __i.first.end << " UTC"; 2581 return std::move(__os).str(); 2582 } 2583 }; 2584 2585 class ambiguous_local_time : public runtime_error 2586 { 2587 public: 2588 template<typename _Duration> 2589 ambiguous_local_time(const local_time<_Duration>& __tp, 2590 const local_info& __i) 2591 : runtime_error(_S_make_what_str(__tp, __i)) 2592 { __glibcxx_assert(__i.result == local_info::ambiguous); } 2593 2594 private: 2595 template<typename _Duration> 2596 static string 2597 _S_make_what_str(const local_time<_Duration>& __tp, 2598 const local_info& __i) 2599 { 2600 std::ostringstream __os; 2601 __os << __tp << " is ambiguous. It could be\n" 2602 << __tp << ' ' << __i.first.abbrev << " == " 2603 << __tp - __i.first.offset << " UTC or\n" 2604 << __tp << ' ' << __i.second.abbrev << " == " 2605 << __tp - __i.second.offset << " UTC"; 2606 return std::move(__os).str(); 2607 } 2608 }; 2609 2610 template<typename _Duration> 2611 [[noreturn]] void 2612 __throw_bad_local_time(const local_time<_Duration>& __tp, 2613 const local_info& __i) 2614 { 2615 #if __cpp_exceptions 2616 if (__i.result == local_info::nonexistent) 2617 throw nonexistent_local_time(__tp, __i); 2618 throw ambiguous_local_time(__tp, __i); 2619 #else 2620 __builtin_abort(); 2621 #endif 2622 } 2623 2624 enum class choose { earliest, latest }; 2625 2626 class time_zone 2627 { 2628 public: 2629 time_zone(time_zone&&) = default; 2630 time_zone& operator=(time_zone&&) = default; 2631 2632 ~time_zone(); 2633 2634 [[nodiscard]] 2635 string_view name() const noexcept { return _M_name; } 2636 2637 template<typename _Duration> 2638 sys_info 2639 get_info(const sys_time<_Duration>& __st) const 2640 { return _M_get_sys_info(chrono::floor<seconds>(__st)); } 2641 2642 template<typename _Duration> 2643 local_info 2644 get_info(const local_time<_Duration>& __tp) const 2645 { return _M_get_local_info(chrono::floor<seconds>(__tp)); } 2646 2647 template<typename _Duration> 2648 sys_time<common_type_t<_Duration, seconds>> 2649 to_sys(const local_time<_Duration>& __tp) const 2650 { 2651 local_info __info = get_info(__tp); 2652 2653 if (__info.result != local_info::unique) 2654 __throw_bad_local_time(__tp, __info); 2655 2656 return sys_time<_Duration>(__tp.time_since_epoch()) 2657 - __info.first.offset; 2658 } 2659 2660 template<typename _Duration> 2661 sys_time<common_type_t<_Duration, seconds>> 2662 to_sys(const local_time<_Duration>& __tp, choose __z) const 2663 { 2664 local_info __info = get_info(__tp); 2665 2666 if (__info.result == local_info::nonexistent) 2667 return __info.first.end; // Last second of the previous sys_info. 2668 2669 sys_time<_Duration> __st(__tp.time_since_epoch()); 2670 2671 if (__info.result == local_info::ambiguous && __z == choose::latest) 2672 return __st - __info.second.offset; // Time in the later sys_info. 2673 // else if __z == earliest, use __info.first.offset as below: 2674 2675 return __st - __info.first.offset; 2676 } 2677 2678 template<typename _Duration> 2679 local_time<common_type_t<_Duration, seconds>> 2680 to_local(const sys_time<_Duration>& __tp) const 2681 { 2682 auto __d = (__tp + get_info(__tp).offset).time_since_epoch(); 2683 return local_time<common_type_t<_Duration, seconds>>(__d); 2684 } 2685 2686 [[nodiscard]] friend bool 2687 operator==(const time_zone& __x, const time_zone& __y) noexcept 2688 { return __x._M_name == __y._M_name; } 2689 2690 [[nodiscard]] friend strong_ordering 2691 operator<=>(const time_zone& __x, const time_zone& __y) noexcept 2692 { return __x._M_name <=> __y._M_name; } 2693 2694 private: 2695 sys_info _M_get_sys_info(sys_seconds) const; 2696 local_info _M_get_local_info(local_seconds) const; 2697 2698 friend const tzdb& reload_tzdb(); 2699 friend struct tzdb; 2700 friend class tzdb_list; 2701 2702 struct _Impl; 2703 2704 explicit time_zone(unique_ptr<_Impl> __p); 2705 string _M_name; 2706 unique_ptr<_Impl> _M_impl; 2707 }; 2708 2709 const time_zone* locate_zone(string_view __tz_name); 2710 const time_zone* current_zone(); 2711 2712 /** The list of `chrono::tzdb` objects 2713 * 2714 * A single object of this type is constructed by the C++ runtime, 2715 * and can be accessed by calling `chrono::get_tzdb_list()`. 2716 * 2717 * The front of the list is the current `tzdb` object and can be accessed 2718 * via `chrono::get_tzdb_list().front()` or `chrono::get_tzdb()` or 2719 * `*chrono::get_tzdb_list().begin()`. 2720 * 2721 * The `chrono::reload_tzdb()` function will check for a newer version 2722 * and if found, insert it at the front of the list. 2723 * 2724 * @since C++20 2725 */ 2726 class tzdb_list 2727 { 2728 struct _Node; 2729 2730 public: 2731 tzdb_list(const tzdb_list&) = delete; 2732 tzdb_list& operator=(const tzdb_list&) = delete; 2733 2734 /** An iterator into the `tzdb_list` 2735 * 2736 * As a extension, in libstdc++ each `tzdb` is reference-counted 2737 * and the `const_iterator` type shares ownership of the object it 2738 * refers to. This ensures that a `tzdb` erased from the list will 2739 * not be destroyed while there is an iterator that refers to it. 2740 */ 2741 class const_iterator 2742 { 2743 public: 2744 using value_type = tzdb; 2745 using reference = const tzdb&; 2746 using pointer = const tzdb*; 2747 using difference_type = ptrdiff_t; 2748 using iterator_category = forward_iterator_tag; 2749 2750 constexpr const_iterator() = default; 2751 const_iterator(const const_iterator&) = default; 2752 const_iterator(const_iterator&&) = default; 2753 const_iterator& operator=(const const_iterator&) = default; 2754 const_iterator& operator=(const_iterator&&) = default; 2755 2756 reference operator*() const noexcept; 2757 pointer operator->() const noexcept { return &**this; } 2758 const_iterator& operator++(); 2759 const_iterator operator++(int); 2760 2761 bool operator==(const const_iterator&) const noexcept = default; 2762 2763 private: 2764 explicit const_iterator(const shared_ptr<_Node>&) noexcept; 2765 2766 friend class tzdb_list; 2767 2768 shared_ptr<_Node> _M_node; 2769 void* _M_reserved = nullptr; 2770 }; 2771 2772 /** Access the current `tzdb` at the front of the list. 2773 * 2774 * This returns a reference to the same object as `chrono::get_tzdb()`. 2775 * 2776 * @returns A reference to the current tzdb object. 2777 * @since C++20 2778 */ 2779 const tzdb& front() const noexcept; 2780 2781 /** Remove the tzdb object _after_ the one the iterator refers to. 2782 * 2783 * Calling this function concurrently with any of `front()`, `begin()`, 2784 * or `end()` does not cause a data race, but in general this function 2785 * is not thread-safe. The behaviour may be undefined if erasing an 2786 * element from the list while another thread is calling the same 2787 * function, or incrementing an iterator into the list, or accessing 2788 * the element being erased (unless it is accessed through an iterator). 2789 * 2790 * @param __p A dereferenceable iterator. 2791 * @returns An iterator the element after the one that was erased 2792 * (or `end()` if there is no such element). 2793 * @since C++20 2794 */ 2795 const_iterator erase_after(const_iterator __p); 2796 2797 const_iterator begin() const noexcept; 2798 const_iterator end() const noexcept { return {}; } 2799 const_iterator cbegin() const noexcept { return begin(); } 2800 const_iterator cend() const noexcept { return end(); } 2801 2802 private: 2803 constexpr explicit tzdb_list(nullptr_t); 2804 2805 friend tzdb_list& get_tzdb_list(); 2806 friend const tzdb& get_tzdb(); 2807 friend const tzdb& reload_tzdb(); 2808 friend struct tzdb; 2809 friend class leap_second; 2810 friend struct time_zone::_Impl; 2811 friend class time_zone_link; 2812 }; 2813 2814 class time_zone_link 2815 { 2816 public: 2817 time_zone_link(time_zone_link&&) = default; 2818 time_zone_link& operator=(time_zone_link&&) = default; 2819 2820 string_view name() const noexcept { return _M_name; } 2821 string_view target() const noexcept { return _M_target; } 2822 2823 friend bool 2824 operator==(const time_zone_link& __x, const time_zone_link& __y) noexcept 2825 { return __x.name() == __y.name(); } 2826 2827 friend strong_ordering 2828 operator<=>(const time_zone_link& __x, const time_zone_link& __y) noexcept 2829 { return __x.name() <=> __y.name(); } 2830 2831 private: 2832 friend const tzdb& reload_tzdb(); 2833 friend struct tzdb_list::_Node; 2834 2835 explicit time_zone_link(nullptr_t) { } 2836 2837 string _M_name; 2838 string _M_target; 2839 }; 2840 2841 class leap_second 2842 { 2843 public: 2844 leap_second(const leap_second&) = default; 2845 leap_second& operator=(const leap_second&) = default; 2846 2847 [[nodiscard]] 2848 constexpr sys_seconds 2849 date() const noexcept 2850 { 2851 if (_M_s >= _M_s.zero()) [[likely]] 2852 return sys_seconds(_M_s); 2853 return sys_seconds(-_M_s); 2854 } 2855 2856 [[nodiscard]] 2857 constexpr seconds 2858 value() const noexcept 2859 { 2860 if (_M_s >= _M_s.zero()) [[likely]] 2861 return seconds(1); 2862 return seconds(-1); 2863 } 2864 2865 // This can be defaulted because the database will never contain two 2866 // leap_second objects with the same date but different signs. 2867 [[nodiscard]] friend constexpr bool 2868 operator==(const leap_second&, const leap_second&) noexcept = default; 2869 2870 [[nodiscard]] friend constexpr strong_ordering 2871 operator<=>(const leap_second& __x, const leap_second& __y) noexcept 2872 { return __x.date() <=> __y.date(); } 2873 2874 template<typename _Duration> 2875 [[nodiscard]] friend constexpr bool 2876 operator==(const leap_second& __x, 2877 const sys_time<_Duration>& __y) noexcept 2878 { return __x.date() == __y; } 2879 2880 template<typename _Duration> 2881 [[nodiscard]] friend constexpr bool 2882 operator<(const leap_second& __x, 2883 const sys_time<_Duration>& __y) noexcept 2884 { return __x.date() < __y; } 2885 2886 template<typename _Duration> 2887 [[nodiscard]] friend constexpr bool 2888 operator<(const sys_time<_Duration>& __x, 2889 const leap_second& __y) noexcept 2890 { return __x < __y.date(); } 2891 2892 template<typename _Duration> 2893 [[nodiscard]] friend constexpr bool 2894 operator>(const leap_second& __x, 2895 const sys_time<_Duration>& __y) noexcept 2896 { return __y < __x.date(); } 2897 2898 template<typename _Duration> 2899 [[nodiscard]] friend constexpr bool 2900 operator>(const sys_time<_Duration>& __x, 2901 const leap_second& __y) noexcept 2902 { return __y.date() < __x; } 2903 2904 template<typename _Duration> 2905 [[nodiscard]] friend constexpr bool 2906 operator<=(const leap_second& __x, 2907 const sys_time<_Duration>& __y) noexcept 2908 { return !(__y < __x.date()); } 2909 2910 template<typename _Duration> 2911 [[nodiscard]] friend constexpr bool 2912 operator<=(const sys_time<_Duration>& __x, 2913 const leap_second& __y) noexcept 2914 { return !(__y.date() < __x); } 2915 2916 template<typename _Duration> 2917 [[nodiscard]] friend constexpr bool 2918 operator>=(const leap_second& __x, 2919 const sys_time<_Duration>& __y) noexcept 2920 { return !(__x.date() < __y); } 2921 2922 template<typename _Duration> 2923 [[nodiscard]] friend constexpr bool 2924 operator>=(const sys_time<_Duration>& __x, 2925 const leap_second& __y) noexcept 2926 { return !(__x < __y.date()); } 2927 2928 template<three_way_comparable_with<seconds> _Duration> 2929 [[nodiscard]] friend constexpr auto 2930 operator<=>(const leap_second& __x, 2931 const sys_time<_Duration>& __y) noexcept 2932 { return __x.date() <=> __y; } 2933 2934 private: 2935 explicit leap_second(seconds::rep __s) : _M_s(__s) { } 2936 2937 friend struct tzdb_list::_Node; 2938 2939 friend const tzdb& reload_tzdb(); 2940 2941 template<typename _Duration> 2942 friend leap_second_info 2943 get_leap_second_info(const utc_time<_Duration>&); 2944 2945 seconds _M_s; // == date().time_since_epoch() * value().count() 2946 }; 2947 2948 template<class _Tp> struct zoned_traits { }; 2949 2950 template<> 2951 struct zoned_traits<const time_zone*> 2952 { 2953 static const time_zone* 2954 default_zone() 2955 { return std::chrono::locate_zone("UTC"); } 2956 2957 static const time_zone* 2958 locate_zone(string_view __name) 2959 { return std::chrono::locate_zone(__name); } 2960 }; 2961 2962 struct tzdb 2963 { 2964 string version; 2965 _GLIBCXX_STD_C::vector<time_zone> zones; 2966 _GLIBCXX_STD_C::vector<time_zone_link> links; 2967 _GLIBCXX_STD_C::vector<leap_second> leap_seconds; 2968 2969 const time_zone* 2970 locate_zone(string_view __tz_name) const; 2971 2972 const time_zone* 2973 current_zone() const; 2974 2975 private: 2976 friend const tzdb& reload_tzdb(); 2977 friend class time_zone; 2978 friend struct tzdb_list::_Node; 2979 }; 2980 2981 tzdb_list& get_tzdb_list(); 2982 const tzdb& get_tzdb(); 2983 2984 const tzdb& reload_tzdb(); 2985 string remote_version(); 2986 2987 template<typename _Duration, typename _TimeZonePtr = const time_zone*> 2988 class zoned_time 2989 { 2990 static_assert(__is_duration_v<_Duration>); 2991 2992 using _Traits = zoned_traits<_TimeZonePtr>; 2993 2994 // Every constructor that accepts a string_view as its first parameter 2995 // does not participate in class template argument deduction. 2996 using string_view = type_identity_t<std::string_view>; 2997 2998 public: 2999 using duration = common_type_t<_Duration, seconds>; 3000 3001 zoned_time() requires requires { _Traits::default_zone(); } 3002 { } 3003 3004 zoned_time(const zoned_time&) = default; 3005 zoned_time& operator=(const zoned_time&) = default; 3006 3007 zoned_time(const sys_time<_Duration>& __st) 3008 requires requires { _Traits::default_zone(); } 3009 : _M_tp(__st) 3010 { } 3011 3012 explicit 3013 zoned_time(_TimeZonePtr __z) : _M_zone(std::move(__z)) { } 3014 3015 explicit 3016 zoned_time(string_view __name) 3017 requires requires { 3018 _TimeZonePtr{_Traits::locate_zone(std::string_view{})}; 3019 } 3020 : _M_zone(_Traits::locate_zone(__name)) 3021 { } 3022 3023 template<typename _Duration2> 3024 zoned_time(const zoned_time<_Duration2, _TimeZonePtr>& __zt) 3025 requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>> 3026 : _M_zone(__zt._M_zone), _M_tp(__zt._M_tp) 3027 { } 3028 3029 zoned_time(_TimeZonePtr __z, const sys_time<_Duration>& __st) 3030 : _M_zone(std::move(__z)), _M_tp(__st) 3031 { } 3032 3033 zoned_time(string_view __name, const sys_time<_Duration>& __st) 3034 : zoned_time(_Traits::locate_zone(__name), __st) 3035 { } 3036 3037 zoned_time(_TimeZonePtr __z, const local_time<_Duration>& __tp) 3038 requires requires { 3039 { __z->to_sys(__tp) } -> convertible_to<sys_time<_Duration>>; 3040 } 3041 : _M_zone(std::move(__z)), _M_tp(_M_zone->to_sys(__tp)) 3042 { } 3043 3044 zoned_time(string_view __name, const local_time<_Duration>& __tp) 3045 requires requires (_TimeZonePtr __z) { 3046 { _Traits::locate_zone(__name) } -> convertible_to<_TimeZonePtr>; 3047 { __z->to_sys(__tp) } -> convertible_to<sys_time<_Duration>>; 3048 } 3049 : zoned_time(_Traits::locate_zone(__name), __tp) 3050 { } 3051 3052 zoned_time(_TimeZonePtr __z, const local_time<_Duration>& __tp, 3053 choose __c) 3054 requires requires { 3055 { __z->to_sys(__tp, __c) } -> convertible_to<sys_time<_Duration>>; 3056 } 3057 : _M_zone(std::move(__z)), _M_tp(_M_zone->to_sys(__tp, __c)) 3058 { } 3059 3060 zoned_time(string_view __name, const local_time<_Duration>& __tp, 3061 choose __c) 3062 requires requires (_TimeZonePtr __z) { 3063 { _Traits::locate_zone(__name) } -> convertible_to<_TimeZonePtr>; 3064 { __z->to_sys(__tp, __c) } -> convertible_to<sys_time<_Duration>>; 3065 } 3066 : _M_zone(_Traits::locate_zone(__name)), 3067 _M_tp(_M_zone->to_sys(__tp, __c)) 3068 { } 3069 3070 template<typename _Duration2, typename _TimeZonePtr2> 3071 zoned_time(_TimeZonePtr __z, 3072 const zoned_time<_Duration2, _TimeZonePtr2>& __zt) 3073 requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>> 3074 : _M_zone(__z), _M_tp(__zt._M_tp) 3075 { } 3076 3077 template<typename _Duration2, typename _TimeZonePtr2> 3078 zoned_time(_TimeZonePtr __z, 3079 const zoned_time<_Duration2, _TimeZonePtr2>& __zt, 3080 choose) 3081 requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>> 3082 : _M_zone(__z), _M_tp(__zt._M_tp) 3083 { } 3084 3085 template<typename _Duration2, typename _TimeZonePtr2> 3086 zoned_time(string_view __name, 3087 const zoned_time<_Duration2, _TimeZonePtr2>& __zt) 3088 requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>> 3089 && requires { 3090 { _Traits::locate_zone(__name) } -> convertible_to<_TimeZonePtr>; 3091 } 3092 : _M_zone(_Traits::locate_zone(__name)), _M_tp(__zt._M_tp) 3093 { } 3094 3095 template<typename _Duration2, typename _TimeZonePtr2> 3096 zoned_time(string_view __name, 3097 const zoned_time<_Duration2, _TimeZonePtr2>& __zt, 3098 choose) 3099 requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>> 3100 && requires { 3101 { _Traits::locate_zone(__name) } -> convertible_to<_TimeZonePtr>; 3102 } 3103 : _M_zone(_Traits::locate_zone(__name)), _M_tp(__zt._M_tp) 3104 { } 3105 3106 zoned_time& 3107 operator=(const sys_time<_Duration>& __st) 3108 { 3109 _M_tp = __st; 3110 return *this; 3111 } 3112 3113 zoned_time& 3114 operator=(const local_time<_Duration>& __lt) 3115 { 3116 _M_tp = _M_zone->to_sys(__lt); 3117 return *this; 3118 } 3119 3120 [[nodiscard]] 3121 operator sys_time<duration>() const { return _M_tp; } 3122 3123 [[nodiscard]] 3124 explicit operator local_time<duration>() const 3125 { return get_local_time(); } 3126 3127 [[nodiscard]] 3128 _TimeZonePtr 3129 get_time_zone() const 3130 { return _M_zone; } 3131 3132 [[nodiscard]] 3133 local_time<duration> 3134 get_local_time() const 3135 { return _M_zone->to_local(_M_tp); } 3136 3137 [[nodiscard]] 3138 sys_time<duration> 3139 get_sys_time() const 3140 { return _M_tp; } 3141 3142 [[nodiscard]] 3143 sys_info 3144 get_info() const 3145 { return _M_zone->get_info(_M_tp); } 3146 3147 [[nodiscard]] friend bool 3148 operator==(const zoned_time&, const zoned_time&) = default; 3149 3150 private: 3151 _TimeZonePtr _M_zone{ _Traits::default_zone() }; 3152 sys_time<duration> _M_tp{}; 3153 3154 template<typename _Duration2, typename _TimeZonePtr2> 3155 friend class zoned_time; 3156 }; 3157 3158 zoned_time() -> zoned_time<seconds>; 3159 3160 template<typename _Duration> 3161 zoned_time(sys_time<_Duration>) 3162 -> zoned_time<common_type_t<_Duration, seconds>>; 3163 3164 /// @cond undocumented 3165 template<typename _TimeZonePtrOrName> 3166 using __time_zone_representation 3167 = __conditional_t<is_convertible_v<_TimeZonePtrOrName, string_view>, 3168 const time_zone*, 3169 remove_cvref_t<_TimeZonePtrOrName>>; 3170 /// @endcond 3171 3172 template<typename _TimeZonePtrOrName> 3173 zoned_time(_TimeZonePtrOrName&&) 3174 -> zoned_time<seconds, __time_zone_representation<_TimeZonePtrOrName>>; 3175 3176 template<typename _TimeZonePtrOrName, typename _Duration> 3177 zoned_time(_TimeZonePtrOrName&&, sys_time<_Duration>) 3178 -> zoned_time<common_type_t<_Duration, seconds>, 3179 __time_zone_representation<_TimeZonePtrOrName>>; 3180 3181 template<typename _TimeZonePtrOrName, typename _Duration> 3182 zoned_time(_TimeZonePtrOrName&&, local_time<_Duration>, 3183 choose = choose::earliest) 3184 -> zoned_time<common_type_t<_Duration, seconds>, 3185 __time_zone_representation<_TimeZonePtrOrName>>; 3186 3187 template<typename _Duration, typename _TimeZonePtrOrName, 3188 typename _TimeZonePtr2> 3189 zoned_time(_TimeZonePtrOrName&&, zoned_time<_Duration, _TimeZonePtr2>, 3190 choose = choose::earliest) 3191 -> zoned_time<common_type_t<_Duration, seconds>, 3192 __time_zone_representation<_TimeZonePtrOrName>>; 3193 3194 template<typename _Dur1, typename _TZPtr1, typename _Dur2, typename _TZPtr2> 3195 [[nodiscard]] 3196 inline bool 3197 operator==(const zoned_time<_Dur1, _TZPtr1>& __x, 3198 const zoned_time<_Dur2, _TZPtr2>& __y) 3199 { 3200 return __x.get_time_zone() == __y.get_time_zone() 3201 && __x.get_sys_time() == __y.get_sys_time(); 3202 } 3203 3204 using zoned_seconds = zoned_time<seconds>; 3205 #endif // _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI 3206 3207 namespace __detail 3208 { 3209 inline leap_second_info 3210 __get_leap_second_info(sys_seconds __ss, bool __is_utc) 3211 { 3212 if (__ss < sys_seconds{}) [[unlikely]] 3213 return {}; 3214 3215 const seconds::rep __leaps[] { 3216 78796800, // 1 Jul 1972 3217 94694400, // 1 Jan 1973 3218 126230400, // 1 Jan 1974 3219 157766400, // 1 Jan 1975 3220 189302400, // 1 Jan 1976 3221 220924800, // 1 Jan 1977 3222 252460800, // 1 Jan 1978 3223 283996800, // 1 Jan 1979 3224 315532800, // 1 Jan 1980 3225 362793600, // 1 Jul 1981 3226 394329600, // 1 Jul 1982 3227 425865600, // 1 Jul 1983 3228 489024000, // 1 Jul 1985 3229 567993600, // 1 Jan 1988 3230 631152000, // 1 Jan 1990 3231 662688000, // 1 Jan 1991 3232 709948800, // 1 Jul 1992 3233 741484800, // 1 Jul 1993 3234 773020800, // 1 Jul 1994 3235 820454400, // 1 Jan 1996 3236 867715200, // 1 Jul 1997 3237 915148800, // 1 Jan 1999 3238 1136073600, // 1 Jan 2006 3239 1230768000, // 1 Jan 2009 3240 1341100800, // 1 Jul 2012 3241 1435708800, // 1 Jul 2015 3242 1483228800, // 1 Jan 2017 3243 }; 3244 // The list above is known to be valid until (at least) this date 3245 // and only contains positive leap seconds. 3246 const sys_seconds __expires(1766880000s); // 2025-12-28 00:00:00 UTC 3247 3248 #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI 3249 if (__ss > __expires) 3250 { 3251 // Use updated leap_seconds from tzdb. 3252 size_t __n = std::size(__leaps); 3253 3254 auto __db = get_tzdb_list().begin(); 3255 auto __first = __db->leap_seconds.begin() + __n; 3256 auto __last = __db->leap_seconds.end(); 3257 auto __pos = std::upper_bound(__first, __last, __ss); 3258 seconds __elapsed(__n); 3259 for (auto __i = __first; __i != __pos; ++__i) 3260 __elapsed += __i->value(); 3261 3262 if (__is_utc) 3263 { 3264 // Convert utc_time to sys_time: 3265 __ss -= __elapsed; 3266 // See if that sys_time is before (or during) previous leap sec: 3267 if (__pos != __first && __ss < __pos[-1]) 3268 { 3269 if ((__ss + 1s) >= __pos[-1]) 3270 return {true, __elapsed}; 3271 __elapsed -= __pos[-1].value(); 3272 } 3273 } 3274 return {false, __elapsed}; 3275 } 3276 else 3277 #endif 3278 { 3279 seconds::rep __s = __ss.time_since_epoch().count(); 3280 const seconds::rep* __first = std::begin(__leaps); 3281 const seconds::rep* __last = std::end(__leaps); 3282 3283 // Don't bother searching the list if we're after the last one. 3284 if (__s > (__last[-1] + (__last - __first) + 1)) 3285 return { false, seconds(__last - __first) }; 3286 3287 auto __pos = std::upper_bound(__first, __last, __s); 3288 seconds __elapsed{__pos - __first}; 3289 if (__is_utc) 3290 { 3291 // Convert utc_time to sys_time: 3292 __s -= __elapsed.count(); 3293 // See if that sys_time is before (or during) previous leap sec: 3294 if (__pos != __first && __s < __pos[-1]) 3295 { 3296 if ((__s + 1) >= __pos[-1]) 3297 return {true, __elapsed}; 3298 --__elapsed; 3299 } 3300 } 3301 return {false, __elapsed}; 3302 } 3303 } 3304 } // namespace __detail 3305 3306 template<typename _Duration> 3307 [[nodiscard]] 3308 inline leap_second_info 3309 get_leap_second_info(const utc_time<_Duration>& __ut) 3310 { 3311 auto __s = chrono::duration_cast<seconds>(__ut.time_since_epoch()); 3312 return __detail::__get_leap_second_info(sys_seconds(__s), true); 3313 } 3314 3315 template<typename _Duration> 3316 [[nodiscard]] 3317 inline utc_time<common_type_t<_Duration, seconds>> 3318 utc_clock::from_sys(const sys_time<_Duration>& __t) 3319 { 3320 using _CDur = common_type_t<_Duration, seconds>; 3321 auto __s = chrono::time_point_cast<seconds>(__t); 3322 const auto __li = __detail::__get_leap_second_info(__s, false); 3323 return utc_time<_CDur>{__t.time_since_epoch()} + __li.elapsed; 3324 } 3325 3326 /// @} group chrono 3327 #endif // C++20 3328 } // namespace chrono 3329 3330 #if __cplusplus >= 202002L 3331 inline namespace literals 3332 { 3333 inline namespace chrono_literals 3334 { 3335 /// @addtogroup chrono 3336 /// @{ 3337 #pragma GCC diagnostic push 3338 #pragma GCC diagnostic ignored "-Wliteral-suffix" 3339 /// Literal suffix for creating chrono::day objects. 3340 /// @since C++20 3341 constexpr chrono::day 3342 operator""d(unsigned long long __d) noexcept 3343 { return chrono::day{static_cast<unsigned>(__d)}; } 3344 3345 /// Literal suffix for creating chrono::year objects. 3346 /// @since C++20 3347 constexpr chrono::year 3348 operator""y(unsigned long long __y) noexcept 3349 { return chrono::year{static_cast<int>(__y)}; } 3350 #pragma GCC diagnostic pop 3351 /// @} 3352 } // inline namespace chrono_literals 3353 } // inline namespace literals 3354 #endif // C++20 3355 3356 _GLIBCXX_END_NAMESPACE_VERSION 3357 } // namespace std 3358 3359 #if __cplusplus >= 202002L 3360 # include <bits/chrono_io.h> 3361 #endif 3362 3363 #endif // C++11 3364 3365 #endif //_GLIBCXX_CHRONO 3366