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