]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/std/chrono
libstdc++: Fix UB in weekday::weekday(sys_days) and add test
[thirdparty/gcc.git] / libstdc++-v3 / include / std / chrono
CommitLineData
15e38d0d
CF
1// <chrono> -*- C++ -*-
2
83ffe9cd 3// Copyright (C) 2008-2023 Free Software Foundation, Inc.
15e38d0d
CF
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
748086b7 8// Free Software Foundation; either version 3, or (at your option)
15e38d0d
CF
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
748086b7
JJ
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.
15e38d0d 19
748086b7
JJ
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/>.
15e38d0d
CF
24
25/** @file include/chrono
26 * This is a Standard C++ Library header.
c34d3fd3 27 * @ingroup chrono
15e38d0d
CF
28 */
29
30#ifndef _GLIBCXX_CHRONO
31#define _GLIBCXX_CHRONO 1
32
33#pragma GCC system_header
34
18f176d0
AA
35#include <bits/requires_hosted.h> // for <ctime> and clocks
36
734f5023 37#if __cplusplus < 201103L
ab65a4c7 38# include <bits/c++0x_warning.h>
15e38d0d
CF
39#else
40
7f78718b 41#include <bits/chrono.h>
1736bf5a
JW
42
43#if __cplusplus >= 202002L
5329e1a8 44# include <bit>
1736bf5a
JW
45# include <sstream>
46# include <string>
47# include <vector>
9fc61d45 48# include <bits/stl_algo.h> // upper_bound
1736bf5a
JW
49# include <bits/shared_ptr.h>
50# include <bits/unique_ptr.h>
fcc13d6f 51#endif
15e38d0d 52
12ffa228
BK
53namespace std _GLIBCXX_VISIBILITY(default)
54{
4a15d842
FD
55_GLIBCXX_BEGIN_NAMESPACE_VERSION
56
5b9daa7e
BK
57 /**
58 * @defgroup chrono Time
59 * @ingroup utilities
60 *
61 * Classes and functions for time.
f2ce64b5
JW
62 *
63 * @since C++11
5b9daa7e
BK
64 */
65
66 /** @namespace std::chrono
19aaf814 67 * @brief ISO C++ 2011 namespace for date and time utilities
f2ce64b5 68 * @ingroup chrono
5b9daa7e 69 */
15e38d0d
CF
70 namespace chrono
71 {
7f78718b 72#if __cplusplus >= 202002L
f2ce64b5
JW
73 /// @addtogroup chrono
74 /// @{
16948c54
JW
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>;
bf1fc37b 80
03d5044b
PP
81 class utc_clock;
82 class tai_clock;
83 class gps_clock;
5b9daa7e 84
03d5044b
PP
85 template<typename _Duration>
86 using utc_time = time_point<utc_clock, _Duration>;
87 using utc_seconds = utc_time<seconds>;
15e38d0d 88
03d5044b
PP
89 template<typename _Duration>
90 using tai_time = time_point<tai_clock, _Duration>;
91 using tai_seconds = tai_time<seconds>;
a15f7cb8 92
03d5044b
PP
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
1736bf5a
JW
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
ec8f914f 130 [[nodiscard]]
1736bf5a
JW
131 static time_point
132 now()
133 { return from_sys(system_clock::now()); }
134
135 template<typename _Duration>
ec8f914f 136 [[nodiscard]]
1736bf5a
JW
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);
9fc61d45 142 sys_time<_CDur> __s{__t.time_since_epoch() - __li.elapsed};
1736bf5a
JW
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>
ec8f914f 149 [[nodiscard]]
1736bf5a 150 static utc_time<common_type_t<_Duration, seconds>>
9fc61d45 151 from_sys(const sys_time<_Duration>& __t);
1736bf5a
JW
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.
ec8f914f 170 [[nodiscard]]
1736bf5a
JW
171 static time_point
172 now()
173 { return from_utc(utc_clock::now()); }
174
175 template<typename _Duration>
ec8f914f 176 [[nodiscard]]
1736bf5a
JW
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>
ec8f914f 185 [[nodiscard]]
1736bf5a
JW
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.
ec8f914f 210 [[nodiscard]]
1736bf5a
JW
211 static time_point
212 now()
213 { return from_utc(utc_clock::now()); }
214
215 template<typename _Duration>
ec8f914f 216 [[nodiscard]]
1736bf5a
JW
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>
ec8f914f 225 [[nodiscard]]
1736bf5a
JW
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>
ec8f914f 399 [[nodiscard]]
1736bf5a
JW
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
03d5044b
PP
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)
cd1464db 507 {
03d5044b
PP
508 if (__n >= 0)
509 return __n % __d;
510 else
511 return (__d + (__n % __d)) % __d;
cd1464db 512 }
1c9f675f 513
03d5044b
PP
514 inline constexpr unsigned __days_per_month[12]
515 = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
03d5044b 516 }
88c4d6b7 517
03d5044b 518 // DAY
1c9f675f 519
03d5044b
PP
520 class day
521 {
522 private:
523 unsigned char _M_d;
1c9f675f 524
03d5044b
PP
525 public:
526 day() = default;
1c9f675f 527
03d5044b
PP
528 explicit constexpr
529 day(unsigned __d) noexcept
530 : _M_d(__d)
531 { }
1c9f675f 532
03d5044b
PP
533 constexpr day&
534 operator++() noexcept
535 {
536 ++_M_d;
537 return *this;
538 }
1c9f675f 539
03d5044b
PP
540 constexpr day
541 operator++(int) noexcept
542 {
543 auto __ret = *this;
544 ++(*this);
545 return __ret;
546 }
1c9f675f 547
03d5044b
PP
548 constexpr day&
549 operator--() noexcept
550 {
551 --_M_d;
552 return *this;
553 }
1c9f675f 554
03d5044b
PP
555 constexpr day
556 operator--(int) noexcept
557 {
558 auto __ret = *this;
559 --(*this);
560 return __ret;
561 }
88c4d6b7 562
03d5044b
PP
563 constexpr day&
564 operator+=(const days& __d) noexcept
565 {
566 *this = *this + __d;
567 return *this;
568 }
88c4d6b7 569
03d5044b
PP
570 constexpr day&
571 operator-=(const days& __d) noexcept
572 {
573 *this = *this - __d;
574 return *this;
575 }
88c4d6b7 576
03d5044b
PP
577 constexpr explicit
578 operator unsigned() const noexcept
579 { return _M_d; }
88c4d6b7 580
03d5044b
PP
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;
03d5044b
PP
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;
03d5044b
PP
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
12679397 837 {
86a0df1a
CN
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.
12679397
CN
854
855 // References:
856 // [1] https://github.com/cassioneri/calendar
86a0df1a
CN
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;
12679397 861 }
03d5044b
PP
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
b6b9fd4a 881 { return year{int{__x} + static_cast<int>(__y.count())}; }
03d5044b
PP
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;
03d5044b
PP
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 {
f6ce081d
CN
933 using _Rep = days::rep;
934 using _URep = make_unsigned_t<_Rep>;
935 const auto __n = __d.count();
936 const auto __m = static_cast<_URep>(__n);
937
938 // 1970-01-01 (__n = 0, __m = 0 ) -> Thursday (4)
939 // 1969-31-12 (__n = -1, __m = _URep(-1)) -> Wednesday (3)
940 const auto __offset = __n >= 0 ? _URep(4) : 3 - _URep(-1) % 7 - 7;
941 return weekday((__m + __offset) % 7);
03d5044b
PP
942 }
943
944 public:
945 weekday() = default;
946
947 explicit constexpr
948 weekday(unsigned __wd) noexcept
949 : _M_wd(__wd == 7 ? 0 : __wd) // __wd % 7 ?
950 { }
951
952 constexpr
953 weekday(const sys_days& __dp) noexcept
954 : weekday{_S_from_days(__dp.time_since_epoch())}
955 { }
956
957 explicit constexpr
958 weekday(const local_days& __dp) noexcept
959 : weekday{sys_days{__dp.time_since_epoch()}}
960 { }
961
962 constexpr weekday&
963 operator++() noexcept
964 {
965 *this += days{1};
966 return *this;
967 }
968
969 constexpr weekday
970 operator++(int) noexcept
971 {
972 auto __ret = *this;
973 ++(*this);
974 return __ret;
975 }
976
977 constexpr weekday&
978 operator--() noexcept
979 {
980 *this -= days{1};
981 return *this;
982 }
983
984 constexpr weekday
985 operator--(int) noexcept
986 {
987 auto __ret = *this;
988 --(*this);
989 return __ret;
990 }
991
992 constexpr weekday&
993 operator+=(const days& __d) noexcept
994 {
995 *this = *this + __d;
996 return *this;
997 }
998
999 constexpr weekday&
1000 operator-=(const days& __d) noexcept
1001 {
1002 *this = *this - __d;
1003 return *this;
1004 }
1005
1006 constexpr unsigned
1007 c_encoding() const noexcept
1008 { return _M_wd; }
1009
1010 constexpr unsigned
1011 iso_encoding() const noexcept
1012 { return _M_wd == 0u ? 7u : _M_wd; }
1013
1014 constexpr bool
1015 ok() const noexcept
1016 { return _M_wd <= 6; }
1017
1018 constexpr weekday_indexed
1019 operator[](unsigned __index) const noexcept;
1020
1021 constexpr weekday_last
1022 operator[](last_spec) const noexcept;
1023
1024 friend constexpr bool
1025 operator==(const weekday& __x, const weekday& __y) noexcept
1026 { return __x._M_wd == __y._M_wd; }
1027
1028 friend constexpr weekday
1029 operator+(const weekday& __x, const days& __y) noexcept
1030 {
1031 auto __n = static_cast<long long>(__x._M_wd) + __y.count();
1032 return weekday{__detail::__modulo(__n, 7)};
1033 }
1034
1035 friend constexpr weekday
1036 operator+(const days& __x, const weekday& __y) noexcept
1037 { return __y + __x; }
1038
1039 friend constexpr weekday
1040 operator-(const weekday& __x, const days& __y) noexcept
1041 { return __x + -__y; }
1042
1043 friend constexpr days
1044 operator-(const weekday& __x, const weekday& __y) noexcept
1045 {
1046 auto __n = static_cast<long long>(__x._M_wd) - __y._M_wd;
1047 return days{__detail::__modulo(__n, 7)};
1048 }
03d5044b
PP
1049 };
1050
1051 inline constexpr weekday Sunday{0};
1052 inline constexpr weekday Monday{1};
1053 inline constexpr weekday Tuesday{2};
1054 inline constexpr weekday Wednesday{3};
1055 inline constexpr weekday Thursday{4};
1056 inline constexpr weekday Friday{5};
1057 inline constexpr weekday Saturday{6};
1058
1059 // WEEKDAY_INDEXED
1060
1061 class weekday_indexed
1062 {
1063 private:
1064 chrono::weekday _M_wd;
1065 unsigned char _M_index;
1066
1067 public:
1068 weekday_indexed() = default;
1069
1070 constexpr
1071 weekday_indexed(const chrono::weekday& __wd, unsigned __index) noexcept
1072 : _M_wd(__wd), _M_index(__index)
1073 { }
1074
1075 constexpr chrono::weekday
1076 weekday() const noexcept
1077 { return _M_wd; }
1078
1079 constexpr unsigned
1080 index() const noexcept
1081 { return _M_index; };
1082
1083 constexpr bool
1084 ok() const noexcept
1085 { return _M_wd.ok() && 1 <= _M_index && _M_index <= 5; }
1086
1087 friend constexpr bool
1088 operator==(const weekday_indexed& __x, const weekday_indexed& __y) noexcept
1089 { return __x.weekday() == __y.weekday() && __x.index() == __y.index(); }
1090
1091 friend constexpr month_weekday
1092 operator/(const month& __m, const weekday_indexed& __wdi) noexcept;
1093
1094 friend constexpr month_weekday
1095 operator/(int __m, const weekday_indexed& __wdi) noexcept;
1096
1097 friend constexpr month_weekday
1098 operator/(const weekday_indexed& __wdi, const month& __m) noexcept;
1099
1100 friend constexpr month_weekday
1101 operator/(const weekday_indexed& __wdi, int __m) noexcept;
1102
1103 friend constexpr year_month_weekday
1104 operator/(const year_month& __ym, const weekday_indexed& __wdi) noexcept;
03d5044b
PP
1105 };
1106
1107 constexpr weekday_indexed
1108 weekday::operator[](unsigned __index) const noexcept
1109 { return {*this, __index}; }
1110
1111 // WEEKDAY_LAST
1112
1113 class weekday_last
1114 {
1115 private:
1116 chrono::weekday _M_wd;
1117
1118 public:
1119 explicit constexpr
1120 weekday_last(const chrono::weekday& __wd) noexcept
1121 : _M_wd{__wd}
1122 { }
1123
1124 constexpr chrono::weekday
1125 weekday() const noexcept
1126 { return _M_wd; }
1127
1128 constexpr bool
1129 ok() const noexcept
1130 { return _M_wd.ok(); }
1131
1132 friend constexpr bool
1133 operator==(const weekday_last& __x, const weekday_last& __y) noexcept
1134 { return __x.weekday() == __y.weekday(); }
1135
1136 friend constexpr month_weekday_last
1137 operator/(int __m, const weekday_last& __wdl) noexcept;
1138
1139 friend constexpr month_weekday_last
1140 operator/(const weekday_last& __wdl, int __m) noexcept;
1141
1142 friend constexpr year_month_weekday_last
1143 operator/(const year_month& __ym, const weekday_last& __wdl) noexcept;
03d5044b
PP
1144 };
1145
1146 constexpr weekday_last
1147 weekday::operator[](last_spec) const noexcept
1148 { return weekday_last{*this}; }
1149
1150 // MONTH_DAY
1151
1152 class month_day
1153 {
1154 private:
1155 chrono::month _M_m;
1156 chrono::day _M_d;
1157
1158 public:
1159 month_day() = default;
1160
1161 constexpr
1162 month_day(const chrono::month& __m, const chrono::day& __d) noexcept
1163 : _M_m{__m}, _M_d{__d}
1164 { }
1165
1166 constexpr chrono::month
1167 month() const noexcept
1168 { return _M_m; }
1169
1170 constexpr chrono::day
1171 day() const noexcept
1172 { return _M_d; }
1173
1174 constexpr bool
1175 ok() const noexcept
1176 {
1177 return _M_m.ok()
1178 && 1u <= unsigned(_M_d)
1179 && unsigned(_M_d) <= __detail::__days_per_month[unsigned(_M_m) - 1];
1180 }
1181
1182 friend constexpr bool
1183 operator==(const month_day& __x, const month_day& __y) noexcept
1184 { return __x.month() == __y.month() && __x.day() == __y.day(); }
1185
1186 friend constexpr strong_ordering
1187 operator<=>(const month_day& __x, const month_day& __y) noexcept
1188 = default;
1189
1190 friend constexpr month_day
1191 operator/(const chrono::month& __m, const chrono::day& __d) noexcept
1192 { return {__m, __d}; }
1193
1194 friend constexpr month_day
1195 operator/(const chrono::month& __m, int __d) noexcept
1196 { return {__m, chrono::day(unsigned(__d))}; }
1197
1198 friend constexpr month_day
1199 operator/(int __m, const chrono::day& __d) noexcept
1200 { return {chrono::month(unsigned(__m)), __d}; }
1201
1202 friend constexpr month_day
1203 operator/(const chrono::day& __d, const chrono::month& __m) noexcept
1204 { return {__m, __d}; }
1205
1206 friend constexpr month_day
1207 operator/(const chrono::day& __d, int __m) noexcept
1208 { return {chrono::month(unsigned(__m)), __d}; }
1209
1210 friend constexpr year_month_day
1211 operator/(int __y, const month_day& __md) noexcept;
1212
1213 friend constexpr year_month_day
1214 operator/(const month_day& __md, int __y) noexcept;
03d5044b
PP
1215 };
1216
1217 // MONTH_DAY_LAST
1218
1219 class month_day_last
1220 {
1221 private:
1222 chrono::month _M_m;
1223
1224 public:
1225 explicit constexpr
1226 month_day_last(const chrono::month& __m) noexcept
1227 : _M_m{__m}
1228 { }
1229
1230 constexpr chrono::month
1231 month() const noexcept
1232 { return _M_m; }
1233
1234 constexpr bool
1235 ok() const noexcept
1236 { return _M_m.ok(); }
1237
1238 friend constexpr bool
1239 operator==(const month_day_last& __x, const month_day_last& __y) noexcept
1240 { return __x.month() == __y.month(); }
1241
1242 friend constexpr strong_ordering
1243 operator<=>(const month_day_last& __x, const month_day_last& __y) noexcept
1244 = default;
1245
1246 friend constexpr month_day_last
1247 operator/(const chrono::month& __m, last_spec) noexcept
1248 { return month_day_last{__m}; }
1249
1250 friend constexpr month_day_last
1251 operator/(int __m, last_spec) noexcept
1252 { return chrono::month(unsigned(__m)) / last; }
1253
1254 friend constexpr month_day_last
1255 operator/(last_spec, const chrono::month& __m) noexcept
1256 { return __m / last; }
1257
1258 friend constexpr month_day_last
1259 operator/(last_spec, int __m) noexcept
1260 { return __m / last; }
1261
1262 friend constexpr year_month_day_last
1263 operator/(int __y, const month_day_last& __mdl) noexcept;
1264
1265 friend constexpr year_month_day_last
1266 operator/(const month_day_last& __mdl, int __y) noexcept;
03d5044b
PP
1267 };
1268
1269 // MONTH_WEEKDAY
1270
1271 class month_weekday
1272 {
1273 private:
1274 chrono::month _M_m;
1275 chrono::weekday_indexed _M_wdi;
1276
1277 public:
1278 constexpr
1279 month_weekday(const chrono::month& __m,
1280 const chrono::weekday_indexed& __wdi) noexcept
1281 : _M_m{__m}, _M_wdi{__wdi}
1282 { }
1283
1284 constexpr chrono::month
1285 month() const noexcept
1286 { return _M_m; }
1287
1288 constexpr chrono::weekday_indexed
1289 weekday_indexed() const noexcept
1290 { return _M_wdi; }
1291
1292 constexpr bool
1293 ok() const noexcept
1294 { return _M_m.ok() && _M_wdi.ok(); }
1295
1296 friend constexpr bool
1297 operator==(const month_weekday& __x, const month_weekday& __y) noexcept
1298 {
1299 return __x.month() == __y.month()
1300 && __x.weekday_indexed() == __y.weekday_indexed();
1301 }
1302
1303 friend constexpr month_weekday
1304 operator/(const chrono::month& __m,
1305 const chrono::weekday_indexed& __wdi) noexcept
1306 { return {__m, __wdi}; }
1307
1308 friend constexpr month_weekday
1309 operator/(int __m, const chrono::weekday_indexed& __wdi) noexcept
1310 { return chrono::month(unsigned(__m)) / __wdi; }
1311
1312 friend constexpr month_weekday
1313 operator/(const chrono::weekday_indexed& __wdi,
1314 const chrono::month& __m) noexcept
1315 { return __m / __wdi; }
1316
1317 friend constexpr month_weekday
1318 operator/(const chrono::weekday_indexed& __wdi, int __m) noexcept
1319 { return __m / __wdi; }
1320
1321 friend constexpr year_month_weekday
1322 operator/(int __y, const month_weekday& __mwd) noexcept;
1323
1324 friend constexpr year_month_weekday
1325 operator/(const month_weekday& __mwd, int __y) noexcept;
03d5044b
PP
1326 };
1327
1328 // MONTH_WEEKDAY_LAST
1329
1330 class month_weekday_last
1331 {
1332 private:
1333 chrono::month _M_m;
1334 chrono::weekday_last _M_wdl;
1335
1336 public:
1337 constexpr
1338 month_weekday_last(const chrono::month& __m,
1339 const chrono::weekday_last& __wdl) noexcept
1340 :_M_m{__m}, _M_wdl{__wdl}
1341 { }
1342
1343 constexpr chrono::month
1344 month() const noexcept
1345 { return _M_m; }
1346
1347 constexpr chrono::weekday_last
1348 weekday_last() const noexcept
1349 { return _M_wdl; }
1350
1351 constexpr bool
1352 ok() const noexcept
1353 { return _M_m.ok() && _M_wdl.ok(); }
1354
1355 friend constexpr bool
1356 operator==(const month_weekday_last& __x,
1357 const month_weekday_last& __y) noexcept
1358 {
1359 return __x.month() == __y.month()
1360 && __x.weekday_last() == __y.weekday_last();
1361 }
1362
1363 friend constexpr month_weekday_last
1364 operator/(const chrono::month& __m,
1365 const chrono::weekday_last& __wdl) noexcept
1366 { return {__m, __wdl}; }
1367
1368 friend constexpr month_weekday_last
1369 operator/(int __m, const chrono::weekday_last& __wdl) noexcept
1370 { return chrono::month(unsigned(__m)) / __wdl; }
1371
1372 friend constexpr month_weekday_last
1373 operator/(const chrono::weekday_last& __wdl,
1374 const chrono::month& __m) noexcept
1375 { return __m / __wdl; }
1376
1377 friend constexpr month_weekday_last
1378 operator/(const chrono::weekday_last& __wdl, int __m) noexcept
1379 { return chrono::month(unsigned(__m)) / __wdl; }
1380
1381 friend constexpr year_month_weekday_last
1382 operator/(int __y, const month_weekday_last& __mwdl) noexcept;
1383
1384 friend constexpr year_month_weekday_last
1385 operator/(const month_weekday_last& __mwdl, int __y) noexcept;
03d5044b
PP
1386 };
1387
1388 // YEAR_MONTH
1389
7b743c67
PP
1390 namespace __detail
1391 {
1392 // [time.cal.ym], [time.cal.ymd], etc constrain the 'months'-based
1393 // addition/subtraction operator overloads like so:
1394 //
1395 // Constraints: if the argument supplied by the caller for the months
1396 // parameter is convertible to years, its implicit conversion sequence
1397 // to years is worse than its implicit conversion sequence to months.
1398 //
1399 // We realize this constraint by templatizing the 'months'-based
1400 // overloads (using a dummy defaulted template parameter), so that
1401 // overload resolution doesn't select the 'months'-based overload unless
1402 // the implicit conversion sequence to 'months' is better than that to
1403 // 'years'.
1404 using __months_years_conversion_disambiguator = void;
1405 }
1406
03d5044b
PP
1407 class year_month
1408 {
1409 private:
1410 chrono::year _M_y;
1411 chrono::month _M_m;
1412
1413 public:
1414 year_month() = default;
1415
1416 constexpr
1417 year_month(const chrono::year& __y, const chrono::month& __m) noexcept
1418 : _M_y{__y}, _M_m{__m}
1419 { }
1420
1421 constexpr chrono::year
1422 year() const noexcept
1423 { return _M_y; }
1424
1425 constexpr chrono::month
1426 month() const noexcept
1427 { return _M_m; }
1428
7b743c67
PP
1429 template<typename = __detail::__months_years_conversion_disambiguator>
1430 constexpr year_month&
1431 operator+=(const months& __dm) noexcept
1432 {
1433 *this = *this + __dm;
1434 return *this;
1435 }
03d5044b 1436
7b743c67
PP
1437 template<typename = __detail::__months_years_conversion_disambiguator>
1438 constexpr year_month&
1439 operator-=(const months& __dm) noexcept
1440 {
1441 *this = *this - __dm;
1442 return *this;
1443 }
03d5044b
PP
1444
1445 constexpr year_month&
1446 operator+=(const years& __dy) noexcept
1447 {
1448 *this = *this + __dy;
1449 return *this;
1450 }
1451
1452 constexpr year_month&
1453 operator-=(const years& __dy) noexcept
1454 {
1455 *this = *this - __dy;
1456 return *this;
1457 }
1458
1459 constexpr bool
1460 ok() const noexcept
1461 { return _M_y.ok() && _M_m.ok(); }
1462
1463 friend constexpr bool
1464 operator==(const year_month& __x, const year_month& __y) noexcept
1465 { return __x.year() == __y.year() && __x.month() == __y.month(); }
1466
1467 friend constexpr strong_ordering
1468 operator<=>(const year_month& __x, const year_month& __y) noexcept
1469 = default;
1470
7b743c67
PP
1471 template<typename = __detail::__months_years_conversion_disambiguator>
1472 friend constexpr year_month
1473 operator+(const year_month& __ym, const months& __dm) noexcept
1474 {
1475 // TODO: Optimize?
1476 auto __m = __ym.month() + __dm;
71e97161 1477 auto __i = int(unsigned(__ym.month())) - 1 + __dm.count();
7b743c67
PP
1478 auto __y = (__i < 0
1479 ? __ym.year() + years{(__i - 11) / 12}
1480 : __ym.year() + years{__i / 12});
1481 return __y / __m;
1482 }
03d5044b 1483
7b743c67
PP
1484 template<typename = __detail::__months_years_conversion_disambiguator>
1485 friend constexpr year_month
1486 operator+(const months& __dm, const year_month& __ym) noexcept
1487 { return __ym + __dm; }
03d5044b 1488
7b743c67
PP
1489 template<typename = __detail::__months_years_conversion_disambiguator>
1490 friend constexpr year_month
1491 operator-(const year_month& __ym, const months& __dm) noexcept
1492 { return __ym + -__dm; }
03d5044b
PP
1493
1494 friend constexpr months
1495 operator-(const year_month& __x, const year_month& __y) noexcept
1496 {
1497 return (__x.year() - __y.year()
1498 + months{static_cast<int>(unsigned{__x.month()})
1499 - static_cast<int>(unsigned{__y.month()})});
1500 }
1501
1502 friend constexpr year_month
1503 operator+(const year_month& __ym, const years& __dy) noexcept
1504 { return (__ym.year() + __dy) / __ym.month(); }
1505
1506 friend constexpr year_month
1507 operator+(const years& __dy, const year_month& __ym) noexcept
1508 { return __ym + __dy; }
1509
1510 friend constexpr year_month
1511 operator-(const year_month& __ym, const years& __dy) noexcept
1512 { return __ym + -__dy; }
1513
1514 friend constexpr year_month
1515 operator/(const chrono::year& __y, const chrono::month& __m) noexcept
1516 { return {__y, __m}; }
1517
1518 friend constexpr year_month
1519 operator/(const chrono::year& __y, int __m) noexcept
1520 { return {__y, chrono::month(unsigned(__m))}; }
1521
1522 friend constexpr year_month_day
1523 operator/(const year_month& __ym, int __d) noexcept;
1524
1525 friend constexpr year_month_day_last
1526 operator/(const year_month& __ym, last_spec) noexcept;
03d5044b
PP
1527 };
1528
1529 // YEAR_MONTH_DAY
1530
1531 class year_month_day
1532 {
1533 private:
1534 chrono::year _M_y;
1535 chrono::month _M_m;
1536 chrono::day _M_d;
1537
1538 static constexpr year_month_day _S_from_days(const days& __dp) noexcept;
1539
1540 constexpr days _M_days_since_epoch() const noexcept;
1541
1542 public:
1543 year_month_day() = default;
1544
1545 constexpr
1546 year_month_day(const chrono::year& __y, const chrono::month& __m,
1547 const chrono::day& __d) noexcept
1548 : _M_y{__y}, _M_m{__m}, _M_d{__d}
1549 { }
1550
1551 constexpr
1552 year_month_day(const year_month_day_last& __ymdl) noexcept;
1553
1554 constexpr
1555 year_month_day(const sys_days& __dp) noexcept
1556 : year_month_day(_S_from_days(__dp.time_since_epoch()))
1557 { }
1558
1559 explicit constexpr
1560 year_month_day(const local_days& __dp) noexcept
1561 : year_month_day(sys_days{__dp.time_since_epoch()})
1562 { }
1563
7b743c67
PP
1564 template<typename = __detail::__months_years_conversion_disambiguator>
1565 constexpr year_month_day&
1566 operator+=(const months& __m) noexcept
1567 {
1568 *this = *this + __m;
1569 return *this;
1570 }
03d5044b 1571
7b743c67
PP
1572 template<typename = __detail::__months_years_conversion_disambiguator>
1573 constexpr year_month_day&
1574 operator-=(const months& __m) noexcept
1575 {
1576 *this = *this - __m;
1577 return *this;
1578 }
03d5044b
PP
1579
1580 constexpr year_month_day&
1581 operator+=(const years& __y) noexcept
1582 {
1583 *this = *this + __y;
1584 return *this;
1585 }
1586
1587 constexpr year_month_day&
1588 operator-=(const years& __y) noexcept
1589 {
1590 *this = *this - __y;
1591 return *this;
1592 }
1593
1594 constexpr chrono::year
1595 year() const noexcept
1596 { return _M_y; }
1597
1598 constexpr chrono::month
1599 month() const noexcept
1600 { return _M_m; }
1601
1602 constexpr chrono::day
1603 day() const noexcept
1604 { return _M_d; }
1605
1606 constexpr
1607 operator sys_days() const noexcept
1608 { return sys_days{_M_days_since_epoch()}; }
1609
1610 explicit constexpr
1611 operator local_days() const noexcept
1612 { return local_days{sys_days{*this}.time_since_epoch()}; }
1613
1614 constexpr bool ok() const noexcept;
1615
1616 friend constexpr bool
1617 operator==(const year_month_day& __x, const year_month_day& __y) noexcept
1618 {
1619 return __x.year() == __y.year()
1620 && __x.month() == __y.month()
1621 && __x.day() == __y.day();
1622 }
1623
1624 friend constexpr strong_ordering
1625 operator<=>(const year_month_day& __x, const year_month_day& __y) noexcept
1626 = default;
1627
7b743c67
PP
1628 template<typename = __detail::__months_years_conversion_disambiguator>
1629 friend constexpr year_month_day
1630 operator+(const year_month_day& __ymd, const months& __dm) noexcept
1631 { return (__ymd.year() / __ymd.month() + __dm) / __ymd.day(); }
03d5044b 1632
7b743c67
PP
1633 template<typename = __detail::__months_years_conversion_disambiguator>
1634 friend constexpr year_month_day
1635 operator+(const months& __dm, const year_month_day& __ymd) noexcept
1636 { return __ymd + __dm; }
03d5044b
PP
1637
1638 friend constexpr year_month_day
1639 operator+(const year_month_day& __ymd, const years& __dy) noexcept
1640 { return (__ymd.year() + __dy) / __ymd.month() / __ymd.day(); }
1641
1642 friend constexpr year_month_day
1643 operator+(const years& __dy, const year_month_day& __ymd) noexcept
1644 { return __ymd + __dy; }
1645
7b743c67
PP
1646 template<typename = __detail::__months_years_conversion_disambiguator>
1647 friend constexpr year_month_day
1648 operator-(const year_month_day& __ymd, const months& __dm) noexcept
1649 { return __ymd + -__dm; }
03d5044b
PP
1650
1651 friend constexpr year_month_day
1652 operator-(const year_month_day& __ymd, const years& __dy) noexcept
1653 { return __ymd + -__dy; }
1654
1655 friend constexpr year_month_day
1656 operator/(const year_month& __ym, const chrono::day& __d) noexcept
1657 { return {__ym.year(), __ym.month(), __d}; }
1658
1659 friend constexpr year_month_day
1660 operator/(const year_month& __ym, int __d) noexcept
1661 { return __ym / chrono::day{unsigned(__d)}; }
1662
1663 friend constexpr year_month_day
1664 operator/(const chrono::year& __y, const month_day& __md) noexcept
1665 { return __y / __md.month() / __md.day(); }
1666
1667 friend constexpr year_month_day
1668 operator/(int __y, const month_day& __md) noexcept
1669 { return chrono::year{__y} / __md; }
1670
1671 friend constexpr year_month_day
1672 operator/(const month_day& __md, const chrono::year& __y) noexcept
1673 { return __y / __md; }
1674
1675 friend constexpr year_month_day
1676 operator/(const month_day& __md, int __y) noexcept
1677 { return chrono::year(__y) / __md; }
03d5044b
PP
1678 };
1679
3dfd5493
CN
1680 // Construct from days since 1970/01/01.
1681 // Proposition 6.3 of Neri and Schneider,
1682 // "Euclidean Affine Functions and Applications to Calendar Algorithms".
1683 // https://arxiv.org/abs/2102.06959
03d5044b
PP
1684 constexpr year_month_day
1685 year_month_day::_S_from_days(const days& __dp) noexcept
1686 {
3dfd5493
CN
1687 constexpr auto __z2 = static_cast<uint32_t>(-1468000);
1688 constexpr auto __r2_e3 = static_cast<uint32_t>(536895458);
1689
a47cec4c 1690 const auto __r0 = static_cast<uint32_t>(__dp.count()) + __r2_e3;
3dfd5493
CN
1691
1692 const auto __n1 = 4 * __r0 + 3;
1693 const auto __q1 = __n1 / 146097;
1694 const auto __r1 = __n1 % 146097 / 4;
1695
1696 constexpr auto __p32 = static_cast<uint64_t>(1) << 32;
1697 const auto __n2 = 4 * __r1 + 3;
1698 const auto __u2 = static_cast<uint64_t>(2939745) * __n2;
1699 const auto __q2 = static_cast<uint32_t>(__u2 / __p32);
1700 const auto __r2 = static_cast<uint32_t>(__u2 % __p32) / 2939745 / 4;
1701
1702 constexpr auto __p16 = static_cast<uint32_t>(1) << 16;
1703 const auto __n3 = 2141 * __r2 + 197913;
1704 const auto __q3 = __n3 / __p16;
1705 const auto __r3 = __n3 % __p16 / 2141;
1706
1707 const auto __y0 = 100 * __q1 + __q2;
1708 const auto __m0 = __q3;
1709 const auto __d0 = __r3;
1710
1711 const auto __j = __r2 >= 306;
1712 const auto __y1 = __y0 + __j;
1713 const auto __m1 = __j ? __m0 - 12 : __m0;
1714 const auto __d1 = __d0 + 1;
1715
75c74a83
JW
1716 return year_month_day{chrono::year{static_cast<int>(__y1 + __z2)},
1717 chrono::month{__m1}, chrono::day{__d1}};
03d5044b
PP
1718 }
1719
97d6161f
CN
1720 // Days since 1970/01/01.
1721 // Proposition 6.2 of Neri and Schneider,
1722 // "Euclidean Affine Functions and Applications to Calendar Algorithms".
1723 // https://arxiv.org/abs/2102.06959
03d5044b
PP
1724 constexpr days
1725 year_month_day::_M_days_since_epoch() const noexcept
1726 {
97d6161f
CN
1727 auto constexpr __z2 = static_cast<uint32_t>(-1468000);
1728 auto constexpr __r2_e3 = static_cast<uint32_t>(536895458);
1729
1730 const auto __y1 = static_cast<uint32_t>(static_cast<int>(_M_y)) - __z2;
699672d4
JW
1731 const auto __m1 = static_cast<uint32_t>(static_cast<unsigned>(_M_m));
1732 const auto __d1 = static_cast<uint32_t>(static_cast<unsigned>(_M_d));
97d6161f
CN
1733
1734 const auto __j = static_cast<uint32_t>(__m1 < 3);
1735 const auto __y0 = __y1 - __j;
1736 const auto __m0 = __j ? __m1 + 12 : __m1;
1737 const auto __d0 = __d1 - 1;
1738
1739 const auto __q1 = __y0 / 100;
1740 const auto __yc = 1461 * __y0 / 4 - __q1 + __q1 / 4;
1741 const auto __mc = (979 *__m0 - 2919) / 32;
1742 const auto __dc = __d0;
1743
1744 return days{static_cast<int32_t>(__yc + __mc + __dc - __r2_e3)};
03d5044b
PP
1745 }
1746
1747 // YEAR_MONTH_DAY_LAST
1748
1749 class year_month_day_last
1750 {
1751 private:
1752 chrono::year _M_y;
1753 chrono::month_day_last _M_mdl;
1754
1755 public:
1756 constexpr
1757 year_month_day_last(const chrono::year& __y,
1758 const chrono::month_day_last& __mdl) noexcept
1759 : _M_y{__y}, _M_mdl{__mdl}
1760 { }
1761
7b743c67
PP
1762 template<typename = __detail::__months_years_conversion_disambiguator>
1763 constexpr year_month_day_last&
1764 operator+=(const months& __m) noexcept
1765 {
1766 *this = *this + __m;
1767 return *this;
1768 }
03d5044b 1769
7b743c67
PP
1770 template<typename = __detail::__months_years_conversion_disambiguator>
1771 constexpr year_month_day_last&
1772 operator-=(const months& __m) noexcept
1773 {
1774 *this = *this - __m;
1775 return *this;
1776 }
03d5044b
PP
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 year_month_day_last&
1786 operator-=(const years& __y) noexcept
1787 {
1788 *this = *this - __y;
1789 return *this;
1790 }
1791
1792 constexpr chrono::year
1793 year() const noexcept
1794 { return _M_y; }
1795
1796 constexpr chrono::month
1797 month() const noexcept
1798 { return _M_mdl.month(); }
1799
1800 constexpr chrono::month_day_last
1801 month_day_last() const noexcept
1802 { return _M_mdl; }
1803
1804 // Return A day representing the last day of this year, month pair.
1805 constexpr chrono::day
1806 day() const noexcept
1807 {
8265ab07
CN
1808 const auto __m = static_cast<unsigned>(month());
1809
b0115354
CN
1810 // The result is unspecified if __m < 1 or __m > 12. Hence, assume
1811 // 1 <= __m <= 12. For __m != 2, day() == 30 or day() == 31 or, in
1812 // other words, day () == 30 | b, where b is in {0, 1}.
8265ab07 1813
b0115354
CN
1814 // If __m in {1, 3, 4, 5, 6, 7}, then b is 1 if, and only if, __m is
1815 // odd. Hence, b = __m & 1 = (__m ^ 0) & 1.
8265ab07 1816
b0115354
CN
1817 // If __m in {8, 9, 10, 11, 12}, then b is 1 if, and only if, __m is
1818 // even. Hence, b = (__m ^ 1) & 1.
8265ab07
CN
1819
1820 // Therefore, b = (__m ^ c) & 1, where c = 0, if __m < 8, or c = 1 if
1821 // __m >= 8, that is, c = __m >> 3.
1822
b0115354
CN
1823 // Since 30 = (11110)_2 and __m <= 31 = (11111)_2, the "& 1" in b's
1824 // calculation is unnecessary.
1825
1826 // The performance of this implementation does not depend on look-up
1827 // tables being on the L1 cache.
1828 return chrono::day{__m != 2 ? (__m ^ (__m >> 3)) | 30
1829 : _M_y.is_leap() ? 29 : 28};
03d5044b
PP
1830 }
1831
1832 constexpr
1833 operator sys_days() const noexcept
1834 { return sys_days{year() / month() / day()}; }
1835
1836 explicit constexpr
1837 operator local_days() const noexcept
1838 { return local_days{sys_days{*this}.time_since_epoch()}; }
1839
1840 constexpr bool
1841 ok() const noexcept
1842 { return _M_y.ok() && _M_mdl.ok(); }
1843
1844 friend constexpr bool
1845 operator==(const year_month_day_last& __x,
1846 const year_month_day_last& __y) noexcept
1847 {
1848 return __x.year() == __y.year()
1849 && __x.month_day_last() == __y.month_day_last();
1850 }
1851
1852 friend constexpr strong_ordering
1853 operator<=>(const year_month_day_last& __x,
1854 const year_month_day_last& __y) noexcept
1855 = default;
1856
7b743c67
PP
1857 template<typename = __detail::__months_years_conversion_disambiguator>
1858 friend constexpr year_month_day_last
1859 operator+(const year_month_day_last& __ymdl,
1860 const months& __dm) noexcept
1861 { return (__ymdl.year() / __ymdl.month() + __dm) / last; }
03d5044b 1862
7b743c67
PP
1863 template<typename = __detail::__months_years_conversion_disambiguator>
1864 friend constexpr year_month_day_last
1865 operator+(const months& __dm,
1866 const year_month_day_last& __ymdl) noexcept
1867 { return __ymdl + __dm; }
03d5044b 1868
7b743c67
PP
1869 template<typename = __detail::__months_years_conversion_disambiguator>
1870 friend constexpr year_month_day_last
1871 operator-(const year_month_day_last& __ymdl,
1872 const months& __dm) noexcept
1873 { return __ymdl + -__dm; }
03d5044b
PP
1874
1875 friend constexpr year_month_day_last
1876 operator+(const year_month_day_last& __ymdl,
1877 const years& __dy) noexcept
1878 { return {__ymdl.year() + __dy, __ymdl.month_day_last()}; }
1879
1880 friend constexpr year_month_day_last
1881 operator+(const years& __dy,
1882 const year_month_day_last& __ymdl) noexcept
1883 { return __ymdl + __dy; }
1884
1885 friend constexpr year_month_day_last
1886 operator-(const year_month_day_last& __ymdl,
1887 const years& __dy) noexcept
1888 { return __ymdl + -__dy; }
1889
1890 friend constexpr year_month_day_last
1891 operator/(const year_month& __ym, last_spec) noexcept
1892 { return {__ym.year(), chrono::month_day_last{__ym.month()}}; }
1893
1894 friend constexpr year_month_day_last
1895 operator/(const chrono::year& __y,
1896 const chrono::month_day_last& __mdl) noexcept
1897 { return {__y, __mdl}; }
1898
1899 friend constexpr year_month_day_last
1900 operator/(int __y, const chrono::month_day_last& __mdl) noexcept
1901 { return chrono::year(__y) / __mdl; }
1902
1903 friend constexpr year_month_day_last
1904 operator/(const chrono::month_day_last& __mdl,
1905 const chrono::year& __y) noexcept
1906 { return __y / __mdl; }
1907
1908 friend constexpr year_month_day_last
1909 operator/(const chrono::month_day_last& __mdl, int __y) noexcept
1910 { return chrono::year(__y) / __mdl; }
03d5044b
PP
1911 };
1912
1913 // year_month_day ctor from year_month_day_last
1914 constexpr
1915 year_month_day::year_month_day(const year_month_day_last& __ymdl) noexcept
1916 : _M_y{__ymdl.year()}, _M_m{__ymdl.month()}, _M_d{__ymdl.day()}
1917 { }
1918
1919 constexpr bool
1920 year_month_day::ok() const noexcept
1921 {
1922 if (!_M_y.ok() || !_M_m.ok())
1923 return false;
1924 return chrono::day{1} <= _M_d && _M_d <= (_M_y / _M_m / last).day();
1925 }
1926
1927 // YEAR_MONTH_WEEKDAY
1928
1929 class year_month_weekday
1930 {
1931 private:
1932 chrono::year _M_y;
1933 chrono::month _M_m;
1934 chrono::weekday_indexed _M_wdi;
1935
1936 static constexpr year_month_weekday
1937 _S_from_sys_days(const sys_days& __dp)
1938 {
1939 year_month_day __ymd{__dp};
1940 chrono::weekday __wd{__dp};
1941 auto __index = __wd[(unsigned{__ymd.day()} - 1) / 7 + 1];
1942 return {__ymd.year(), __ymd.month(), __index};
1943 }
1944
1945 public:
1946 year_month_weekday() = default;
1947
1948 constexpr
1949 year_month_weekday(const chrono::year& __y, const chrono::month& __m,
1950 const chrono::weekday_indexed& __wdi) noexcept
1951 : _M_y{__y}, _M_m{__m}, _M_wdi{__wdi}
1952 { }
1953
1954 constexpr
1955 year_month_weekday(const sys_days& __dp) noexcept
1956 : year_month_weekday{_S_from_sys_days(__dp)}
1957 { }
1958
1959 explicit constexpr
1960 year_month_weekday(const local_days& __dp) noexcept
1961 : year_month_weekday{sys_days{__dp.time_since_epoch()}}
1962 { }
1963
7b743c67
PP
1964 template<typename = __detail::__months_years_conversion_disambiguator>
1965 constexpr year_month_weekday&
1966 operator+=(const months& __m) noexcept
1967 {
1968 *this = *this + __m;
1969 return *this;
1970 }
03d5044b 1971
7b743c67
PP
1972 template<typename = __detail::__months_years_conversion_disambiguator>
1973 constexpr year_month_weekday&
1974 operator-=(const months& __m) noexcept
1975 {
1976 *this = *this - __m;
1977 return *this;
1978 }
03d5044b
PP
1979
1980 constexpr year_month_weekday&
1981 operator+=(const years& __y) noexcept
1982 {
1983 *this = *this + __y;
1984 return *this;
1985 }
1986
1987 constexpr year_month_weekday&
1988 operator-=(const years& __y) noexcept
1989 {
1990 *this = *this - __y;
1991 return *this;
1992 }
1993
1994 constexpr chrono::year
1995 year() const noexcept
1996 { return _M_y; }
1997
1998 constexpr chrono::month
1999 month() const noexcept
2000 { return _M_m; }
2001
2002 constexpr chrono::weekday
2003 weekday() const noexcept
2004 { return _M_wdi.weekday(); }
2005
2006 constexpr unsigned
2007 index() const noexcept
2008 { return _M_wdi.index(); }
2009
2010 constexpr chrono::weekday_indexed
2011 weekday_indexed() const noexcept
2012 { return _M_wdi; }
2013
2014 constexpr
2015 operator sys_days() const noexcept
2016 {
2017 auto __d = sys_days{year() / month() / 1};
8572edc8
PP
2018 return __d + (weekday() - chrono::weekday(__d)
2019 + days{(static_cast<int>(index())-1)*7});
03d5044b
PP
2020 }
2021
2022 explicit constexpr
2023 operator local_days() const noexcept
2024 { return local_days{sys_days{*this}.time_since_epoch()}; }
2025
2026 constexpr bool
2027 ok() const noexcept
2028 {
2029 if (!_M_y.ok() || !_M_m.ok() || !_M_wdi.ok())
2030 return false;
2031 if (_M_wdi.index() <= 4)
2032 return true;
2033 days __d = (_M_wdi.weekday()
2034 - chrono::weekday{sys_days{_M_y / _M_m / 1}}
2035 + days((_M_wdi.index()-1)*7 + 1));
1007170d 2036 __glibcxx_assert(__d.count() >= 1);
9fc61d45 2037 return (unsigned)__d.count() <= (unsigned)(_M_y / _M_m / last).day();
03d5044b
PP
2038 }
2039
2040 friend constexpr bool
2041 operator==(const year_month_weekday& __x,
2042 const year_month_weekday& __y) noexcept
2043 {
2044 return __x.year() == __y.year()
2045 && __x.month() == __y.month()
0c5df67f 2046 && __x.weekday_indexed() == __y.weekday_indexed();
03d5044b
PP
2047 }
2048
7b743c67
PP
2049 template<typename = __detail::__months_years_conversion_disambiguator>
2050 friend constexpr year_month_weekday
2051 operator+(const year_month_weekday& __ymwd, const months& __dm) noexcept
2052 {
2053 return ((__ymwd.year() / __ymwd.month() + __dm)
2054 / __ymwd.weekday_indexed());
2055 }
03d5044b 2056
7b743c67
PP
2057 template<typename = __detail::__months_years_conversion_disambiguator>
2058 friend constexpr year_month_weekday
2059 operator+(const months& __dm, const year_month_weekday& __ymwd) noexcept
2060 { return __ymwd + __dm; }
03d5044b
PP
2061
2062 friend constexpr year_month_weekday
2063 operator+(const year_month_weekday& __ymwd, const years& __dy) noexcept
2064 { return {__ymwd.year() + __dy, __ymwd.month(), __ymwd.weekday_indexed()}; }
2065
2066 friend constexpr year_month_weekday
2067 operator+(const years& __dy, const year_month_weekday& __ymwd) noexcept
2068 { return __ymwd + __dy; }
2069
7b743c67
PP
2070 template<typename = __detail::__months_years_conversion_disambiguator>
2071 friend constexpr year_month_weekday
2072 operator-(const year_month_weekday& __ymwd, const months& __dm) noexcept
2073 { return __ymwd + -__dm; }
03d5044b
PP
2074
2075 friend constexpr year_month_weekday
2076 operator-(const year_month_weekday& __ymwd, const years& __dy) noexcept
2077 { return __ymwd + -__dy; }
2078
2079 friend constexpr year_month_weekday
2080 operator/(const year_month& __ym,
2081 const chrono::weekday_indexed& __wdi) noexcept
2082 { return {__ym.year(), __ym.month(), __wdi}; }
2083
2084 friend constexpr year_month_weekday
2085 operator/(const chrono::year& __y, const month_weekday& __mwd) noexcept
2086 { return {__y, __mwd.month(), __mwd.weekday_indexed()}; }
2087
2088 friend constexpr year_month_weekday
2089 operator/(int __y, const month_weekday& __mwd) noexcept
2090 { return chrono::year(__y) / __mwd; }
2091
2092 friend constexpr year_month_weekday
2093 operator/(const month_weekday& __mwd, const chrono::year& __y) noexcept
2094 { return __y / __mwd; }
2095
2096 friend constexpr year_month_weekday
2097 operator/(const month_weekday& __mwd, int __y) noexcept
2098 { return chrono::year(__y) / __mwd; }
03d5044b
PP
2099 };
2100
2101 // YEAR_MONTH_WEEKDAY_LAST
2102
2103 class year_month_weekday_last
2104 {
2105 private:
2106 chrono::year _M_y;
2107 chrono::month _M_m;
2108 chrono::weekday_last _M_wdl;
2109
2110 public:
2111 constexpr
2112 year_month_weekday_last(const chrono::year& __y, const chrono::month& __m,
2113 const chrono::weekday_last& __wdl) noexcept
2114 : _M_y{__y}, _M_m{__m}, _M_wdl{__wdl}
2115 { }
2116
7b743c67
PP
2117 template<typename = __detail::__months_years_conversion_disambiguator>
2118 constexpr year_month_weekday_last&
2119 operator+=(const months& __m) noexcept
2120 {
2121 *this = *this + __m;
2122 return *this;
2123 }
03d5044b 2124
7b743c67
PP
2125 template<typename = __detail::__months_years_conversion_disambiguator>
2126 constexpr year_month_weekday_last&
2127 operator-=(const months& __m) noexcept
2128 {
2129 *this = *this - __m;
2130 return *this;
2131 }
03d5044b
PP
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 year_month_weekday_last&
2141 operator-=(const years& __y) noexcept
2142 {
2143 *this = *this - __y;
2144 return *this;
2145 }
2146
2147 constexpr chrono::year
2148 year() const noexcept
2149 { return _M_y; }
2150
2151 constexpr chrono::month
2152 month() const noexcept
2153 { return _M_m; }
2154
2155 constexpr chrono::weekday
2156 weekday() const noexcept
2157 { return _M_wdl.weekday(); }
2158
2159 constexpr chrono::weekday_last
2160 weekday_last() const noexcept
2161 { return _M_wdl; }
2162
2163 constexpr
2164 operator sys_days() const noexcept
2165 {
2166 const auto __d = sys_days{_M_y / _M_m / last};
2167 return sys_days{(__d - (chrono::weekday{__d}
2168 - _M_wdl.weekday())).time_since_epoch()};
2169 }
2170
2171 explicit constexpr
2172 operator local_days() const noexcept
2173 { return local_days{sys_days{*this}.time_since_epoch()}; }
2174
2175 constexpr bool
2176 ok() const noexcept
2177 { return _M_y.ok() && _M_m.ok() && _M_wdl.ok(); }
2178
2179 friend constexpr bool
2180 operator==(const year_month_weekday_last& __x,
2181 const year_month_weekday_last& __y) noexcept
2182 {
2183 return __x.year() == __y.year()
2184 && __x.month() == __y.month()
2185 && __x.weekday_last() == __y.weekday_last();
2186 }
2187
7b743c67
PP
2188 template<typename = __detail::__months_years_conversion_disambiguator>
2189 friend constexpr year_month_weekday_last
2190 operator+(const year_month_weekday_last& __ymwdl,
2191 const months& __dm) noexcept
2192 {
2193 return ((__ymwdl.year() / __ymwdl.month() + __dm)
2194 / __ymwdl.weekday_last());
2195 }
03d5044b 2196
7b743c67
PP
2197 template<typename = __detail::__months_years_conversion_disambiguator>
2198 friend constexpr year_month_weekday_last
2199 operator+(const months& __dm,
2200 const year_month_weekday_last& __ymwdl) noexcept
2201 { return __ymwdl + __dm; }
03d5044b
PP
2202
2203 friend constexpr year_month_weekday_last
2204 operator+(const year_month_weekday_last& __ymwdl,
2205 const years& __dy) noexcept
2206 { return {__ymwdl.year() + __dy, __ymwdl.month(), __ymwdl.weekday_last()}; }
2207
2208 friend constexpr year_month_weekday_last
2209 operator+(const years& __dy,
2210 const year_month_weekday_last& __ymwdl) noexcept
2211 { return __ymwdl + __dy; }
2212
7b743c67
PP
2213 template<typename = __detail::__months_years_conversion_disambiguator>
2214 friend constexpr year_month_weekday_last
2215 operator-(const year_month_weekday_last& __ymwdl,
2216 const months& __dm) noexcept
2217 { return __ymwdl + -__dm; }
03d5044b
PP
2218
2219 friend constexpr year_month_weekday_last
2220 operator-(const year_month_weekday_last& __ymwdl,
2221 const years& __dy) noexcept
2222 { return __ymwdl + -__dy; }
2223
2224 friend constexpr year_month_weekday_last
2225 operator/(const year_month& __ym,
2226 const chrono::weekday_last& __wdl) noexcept
2227 { return {__ym.year(), __ym.month(), __wdl}; }
2228
2229 friend constexpr year_month_weekday_last
2230 operator/(const chrono::year& __y,
2231 const chrono::month_weekday_last& __mwdl) noexcept
2232 { return {__y, __mwdl.month(), __mwdl.weekday_last()}; }
2233
2234 friend constexpr year_month_weekday_last
2235 operator/(int __y, const chrono::month_weekday_last& __mwdl) noexcept
2236 { return chrono::year(__y) / __mwdl; }
2237
2238 friend constexpr year_month_weekday_last
2239 operator/(const chrono::month_weekday_last& __mwdl,
2240 const chrono::year& __y) noexcept
2241 { return __y / __mwdl; }
2242
2243 friend constexpr year_month_weekday_last
2244 operator/(const chrono::month_weekday_last& __mwdl, int __y) noexcept
2245 { return chrono::year(__y) / __mwdl; }
03d5044b
PP
2246 };
2247
2248 // HH_MM_SS
2249
5329e1a8 2250 /// @cond undocumented
03d5044b
PP
2251 namespace __detail
2252 {
2253 consteval long long
2254 __pow10(unsigned __n)
2255 {
2256 long long __r = 1;
2257 while (__n-- > 0)
2258 __r *= 10;
2259 return __r;
2260 }
f99b9486
JW
2261
2262 template<typename _Duration> struct __utc_leap_second;
03d5044b 2263 }
5329e1a8 2264 /// @endcond
03d5044b 2265
5329e1a8
JW
2266 /** Utility for splitting a duration into hours, minutes, and seconds
2267 *
2268 * This is a convenience type that provides accessors for the constituent
2269 * parts (hours, minutes, seconds and subseconds) of a duration.
2270 *
2271 * @since C++20
2272 */
03d5044b
PP
2273 template<typename _Duration>
2274 class hh_mm_ss
2275 {
5329e1a8
JW
2276 static_assert( __is_duration<_Duration>::value );
2277
03d5044b 2278 private:
5329e1a8 2279 static consteval int
03d5044b
PP
2280 _S_fractional_width()
2281 {
03d5044b 2282 auto __den = _Duration::period::den;
5329e1a8
JW
2283 const int __multiplicity_2 = std::__countr_zero((uintmax_t)__den);
2284 __den >>= __multiplicity_2;
2285 int __multiplicity_5 = 0;
03d5044b
PP
2286 while ((__den % 5) == 0)
2287 {
2288 ++__multiplicity_5;
2289 __den /= 5;
2290 }
2291 if (__den != 1)
2292 return 6;
2293
2294 int __width = (__multiplicity_2 > __multiplicity_5
2295 ? __multiplicity_2 : __multiplicity_5);
2296 if (__width > 18)
2297 __width = 18;
2298 return __width;
2299 }
2300
5329e1a8 2301 constexpr
e36e57b0 2302 hh_mm_ss(_Duration __d, bool __is_neg)
5329e1a8
JW
2303 : _M_h (duration_cast<chrono::hours>(__d)),
2304 _M_m (duration_cast<chrono::minutes>(__d - hours())),
2305 _M_s (duration_cast<chrono::seconds>(__d - hours() - minutes())),
2306 _M_is_neg(__is_neg)
2307 {
2308 auto __ss = __d - hours() - minutes() - seconds();
2309 if constexpr (treat_as_floating_point_v<typename precision::rep>)
2310 _M_ss._M_r = __ss.count();
2311 else if constexpr (precision::period::den != 1)
2312 _M_ss._M_r = duration_cast<precision>(__ss).count();
2313 }
2314
e36e57b0
JW
2315 static constexpr _Duration
2316 _S_abs(_Duration __d)
2317 {
2318 if constexpr (numeric_limits<typename _Duration::rep>::is_signed)
2319 return chrono::abs(__d);
2320 else
2321 return __d;
2322 }
2323
03d5044b
PP
2324 public:
2325 static constexpr unsigned fractional_width = {_S_fractional_width()};
2326
2327 using precision
2328 = duration<common_type_t<typename _Duration::rep,
2329 chrono::seconds::rep>,
2330 ratio<1, __detail::__pow10(fractional_width)>>;
2331
5329e1a8 2332 constexpr hh_mm_ss() noexcept = default;
03d5044b
PP
2333
2334 constexpr explicit
e36e57b0
JW
2335 hh_mm_ss(_Duration __d)
2336 : hh_mm_ss(_S_abs(__d), __d < _Duration::zero())
5329e1a8 2337 { }
03d5044b
PP
2338
2339 constexpr bool
2340 is_negative() const noexcept
5329e1a8 2341 {
cb363fd9 2342 if constexpr (!_S_is_unsigned)
5329e1a8
JW
2343 return _M_is_neg;
2344 else
2345 return false;
2346 }
03d5044b
PP
2347
2348 constexpr chrono::hours
2349 hours() const noexcept
2350 { return _M_h; }
2351
2352 constexpr chrono::minutes
2353 minutes() const noexcept
2354 { return _M_m; }
2355
2356 constexpr chrono::seconds
2357 seconds() const noexcept
2358 { return _M_s; }
2359
2360 constexpr precision
2361 subseconds() const noexcept
5329e1a8 2362 { return static_cast<precision>(_M_ss); }
03d5044b
PP
2363
2364 constexpr explicit
2365 operator precision() const noexcept
2366 { return to_duration(); }
2367
2368 constexpr precision
2369 to_duration() const noexcept
2370 {
cb363fd9 2371 if constexpr (!_S_is_unsigned)
5329e1a8
JW
2372 if (_M_is_neg)
2373 return -(_M_h + _M_m + _M_s + subseconds());
2374 return _M_h + _M_m + _M_s + subseconds();
03d5044b
PP
2375 }
2376
03d5044b 2377 private:
cb363fd9 2378 static constexpr bool _S_is_unsigned
5329e1a8
JW
2379 = __and_v<is_integral<typename _Duration::rep>,
2380 is_unsigned<typename _Duration::rep>>;
2381
2382 template<typename _Ratio>
2383 using __byte_duration = duration<unsigned char, _Ratio>;
2384
2385 // The type of the _M_ss member that holds the subsecond precision.
2386 template<typename _Dur>
2387 struct __subseconds
2388 {
2389 typename _Dur::rep _M_r{};
2390
2391 constexpr explicit
2392 operator _Dur() const noexcept
2393 { return _Dur(_M_r); }
2394 };
2395
2396 // An empty class if this precision doesn't need subseconds.
2397 template<typename _Rep>
2398 requires (!treat_as_floating_point_v<_Rep>)
2399 struct __subseconds<duration<_Rep, ratio<1>>>
2400 {
2401 constexpr explicit
2402 operator duration<_Rep, ratio<1>>() const noexcept
2403 { return {}; }
2404 };
2405
5329e1a8
JW
2406 template<typename _Rep, typename _Period>
2407 requires (!treat_as_floating_point_v<_Rep>)
2408 && ratio_less_v<_Period, ratio<1, 1>>
aa39ed44 2409 && ratio_greater_equal_v<_Period, ratio<1, 250>>
5329e1a8
JW
2410 struct __subseconds<duration<_Rep, _Period>>
2411 {
2412 unsigned char _M_r{};
2413
2414 constexpr explicit
2415 operator duration<_Rep, _Period>() const noexcept
2416 { return duration<_Rep, _Period>(_M_r); }
2417 };
2418
2419 template<typename _Rep, typename _Period>
2420 requires (!treat_as_floating_point_v<_Rep>)
2421 && ratio_less_v<_Period, ratio<1, 250>>
aa39ed44 2422 && ratio_greater_equal_v<_Period, ratio<1, 4000000000>>
5329e1a8
JW
2423 struct __subseconds<duration<_Rep, _Period>>
2424 {
2425 uint_least32_t _M_r{};
2426
2427 constexpr explicit
2428 operator duration<_Rep, _Period>() const noexcept
2429 { return duration<_Rep, _Period>(_M_r); }
2430 };
2431
2432 chrono::hours _M_h{};
2433 __byte_duration<ratio<60>> _M_m{};
2434 __byte_duration<ratio<1>> _M_s{};
2435 bool _M_is_neg{};
2436 __subseconds<precision> _M_ss{};
f99b9486
JW
2437
2438 template<typename> friend struct __detail::__utc_leap_second;
03d5044b 2439 };
f2ce64b5 2440
f99b9486
JW
2441 /// @cond undocumented
2442 namespace __detail
2443 {
2444 // Represents a time that is within a leap second insertion.
2445 template<typename _Duration>
2446 struct __utc_leap_second
2447 {
2448 explicit
2449 __utc_leap_second(const sys_time<_Duration>& __s)
2450 : _M_date(chrono::floor<days>(__s)), _M_time(__s - _M_date)
2451 {
2452 ++_M_time._M_s;
2453 }
2454
2455 sys_days _M_date;
2456 hh_mm_ss<common_type_t<_Duration, days>> _M_time;
2457 };
2458 }
2459 /// @endcond
2460
03d5044b
PP
2461 // 12/24 HOURS FUNCTIONS
2462
2463 constexpr bool
2464 is_am(const hours& __h) noexcept
2465 { return 0h <= __h && __h <= 11h; }
2466
2467 constexpr bool
2468 is_pm(const hours& __h) noexcept
2469 { return 12h <= __h && __h <= 23h; }
2470
2471 constexpr hours
2472 make12(const hours& __h) noexcept
2473 {
2474 if (__h == 0h)
2475 return 12h;
2476 else if (__h > 12h)
2477 return __h - 12h;
2478 return __h;
2479 }
2480
2481 constexpr hours
2482 make24(const hours& __h, bool __is_pm) noexcept
2483 {
2484 if (!__is_pm)
2485 {
2486 if (__h == 12h)
2487 return 0h;
2488 else
2489 return __h;
2490 }
2491 else
2492 {
2493 if (__h == 12h)
2494 return __h;
2495 else
2496 return __h + 12h;
2497 }
2498 }
1736bf5a 2499
9fc61d45 2500#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
1736bf5a
JW
2501 // C++20 [time.zones] Time zones
2502
9fc61d45
JW
2503 struct tzdb;
2504
1736bf5a
JW
2505 struct sys_info
2506 {
2507 sys_seconds begin;
2508 sys_seconds end;
2509 seconds offset;
2510 minutes save;
2511 string abbrev;
2512 };
2513
2514 struct local_info
2515 {
2516 static constexpr int unique = 0;
2517 static constexpr int nonexistent = 1;
2518 static constexpr int ambiguous = 2;
2519
2520 int result;
2521 sys_info first;
2522 sys_info second;
2523 };
2524
2525 class nonexistent_local_time : public runtime_error
2526 {
2527 public:
2528 template<typename _Duration>
2529 nonexistent_local_time(const local_time<_Duration>& __tp,
2530 const local_info& __i)
2531 : runtime_error(_S_make_what_str(__tp, __i))
2532 { __glibcxx_assert(__i.result == local_info::nonexistent); }
2533
2534 private:
9fc61d45 2535 template<typename _Duration>
1736bf5a 2536 static string
9fc61d45
JW
2537 _S_make_what_str(const local_time<_Duration>& __tp,
2538 const local_info& __i)
2539 {
9fc61d45
JW
2540 std::ostringstream __os;
2541 __os << __tp << " is in a gap between\n"
2542 << local_seconds(__i.first.end.time_since_epoch())
2543 + __i.first.offset << ' ' << __i.first.abbrev << " and\n"
2544 << local_seconds(__i.second.begin.time_since_epoch())
2545 + __i.second.offset << ' ' << __i.second.abbrev
2546 << " which are both equivalent to\n"
2547 << __i.first.end << " UTC";
2548 return std::move(__os).str();
9fc61d45 2549 }
1736bf5a
JW
2550 };
2551
2552 class ambiguous_local_time : public runtime_error
2553 {
2554 public:
2555 template<typename _Duration>
2556 ambiguous_local_time(const local_time<_Duration>& __tp,
9fc61d45 2557 const local_info& __i)
1736bf5a 2558 : runtime_error(_S_make_what_str(__tp, __i))
9fc61d45 2559 { __glibcxx_assert(__i.result == local_info::ambiguous); }
1736bf5a
JW
2560
2561 private:
9fc61d45 2562 template<typename _Duration>
1736bf5a 2563 static string
9fc61d45
JW
2564 _S_make_what_str(const local_time<_Duration>& __tp,
2565 const local_info& __i)
2566 {
9fc61d45
JW
2567 std::ostringstream __os;
2568 __os << __tp << " is ambiguous. It could be\n"
2569 << __tp << ' ' << __i.first.abbrev << " == "
2570 << __tp - __i.first.offset << " UTC or\n"
2571 << __tp << ' ' << __i.second.abbrev << " == "
2572 << __tp - __i.second.offset << " UTC";
2573 return std::move(__os).str();
9fc61d45 2574 }
1736bf5a
JW
2575 };
2576
9fc61d45
JW
2577 template<typename _Duration>
2578 [[noreturn]] void
2579 __throw_bad_local_time(const local_time<_Duration>& __tp,
2580 const local_info& __i)
2581 {
2582#if __cpp_exceptions
2583 if (__i.result == local_info::nonexistent)
2584 throw nonexistent_local_time(__tp, __i);
2585 throw ambiguous_local_time(__tp, __i);
2586#else
2587 __builtin_abort();
2588#endif
2589 }
2590
1736bf5a
JW
2591 enum class choose { earliest, latest };
2592
2593 class time_zone
2594 {
2595 public:
2596 time_zone(time_zone&&) = default;
2597 time_zone& operator=(time_zone&&) = default;
2598
9fc61d45
JW
2599 ~time_zone();
2600
2601 [[nodiscard]]
1736bf5a
JW
2602 string_view name() const noexcept { return _M_name; }
2603
2604 template<typename _Duration>
2605 sys_info
9fc61d45
JW
2606 get_info(const sys_time<_Duration>& __st) const
2607 { return _M_get_sys_info(chrono::floor<seconds>(__st)); }
1736bf5a
JW
2608
2609 template<typename _Duration>
2610 local_info
9fc61d45
JW
2611 get_info(const local_time<_Duration>& __tp) const
2612 { return _M_get_local_info(chrono::floor<seconds>(__tp)); }
1736bf5a
JW
2613
2614 template<typename _Duration>
2615 sys_time<common_type_t<_Duration, seconds>>
9fc61d45
JW
2616 to_sys(const local_time<_Duration>& __tp) const
2617 {
2618 local_info __info = get_info(__tp);
2619
2620 if (__info.result != local_info::unique)
2621 __throw_bad_local_time(__tp, __info);
2622
2623 return sys_time<_Duration>(__tp.time_since_epoch())
2624 - __info.first.offset;
2625 }
1736bf5a
JW
2626
2627 template<typename _Duration>
2628 sys_time<common_type_t<_Duration, seconds>>
9fc61d45
JW
2629 to_sys(const local_time<_Duration>& __tp, choose __z) const
2630 {
2631 local_info __info = get_info(__tp);
2632
2633 if (__info.result == local_info::nonexistent)
2634 return __info.first.end; // Last second of the previous sys_info.
2635
2636 sys_time<_Duration> __st(__tp.time_since_epoch());
2637
2638 if (__info.result == local_info::ambiguous && __z == choose::latest)
2639 return __st - __info.second.offset; // Time in the later sys_info.
2640 // else if __z == earliest, use __info.first.offset as below:
2641
2642 return __st - __info.first.offset;
2643 }
1736bf5a
JW
2644
2645 template<typename _Duration>
2646 local_time<common_type_t<_Duration, seconds>>
9fc61d45
JW
2647 to_local(const sys_time<_Duration>& __tp) const
2648 {
2649 auto __d = (__tp + get_info(__tp).offset).time_since_epoch();
2650 return local_time<common_type_t<_Duration, seconds>>(__d);
2651 }
1736bf5a 2652
9fc61d45 2653 [[nodiscard]] friend bool
1736bf5a 2654 operator==(const time_zone& __x, const time_zone& __y) noexcept
9fc61d45 2655 { return __x._M_name == __y._M_name; }
1736bf5a 2656
9fc61d45 2657 [[nodiscard]] friend strong_ordering
1736bf5a 2658 operator<=>(const time_zone& __x, const time_zone& __y) noexcept
9fc61d45 2659 { return __x._M_name <=> __y._M_name; }
1736bf5a
JW
2660
2661 private:
9fc61d45
JW
2662 sys_info _M_get_sys_info(sys_seconds) const;
2663 local_info _M_get_local_info(local_seconds) const;
2664
2665 friend const tzdb& reload_tzdb();
2666 friend struct tzdb;
2667 friend class tzdb_list;
2668
1736bf5a 2669 struct _Impl;
9fc61d45
JW
2670
2671 explicit time_zone(unique_ptr<_Impl> __p);
2672 string _M_name;
1736bf5a
JW
2673 unique_ptr<_Impl> _M_impl;
2674 };
2675
1736bf5a
JW
2676 const time_zone* locate_zone(string_view __tz_name);
2677 const time_zone* current_zone();
2678
9fc61d45
JW
2679 /** The list of `chrono::tzdb` objects
2680 *
2681 * A single object of this type is constructed by the C++ runtime,
2682 * and can be accessed by calling `chrono::get_tzdb_list()`.
2683 *
2684 * The front of the list is the current `tzdb` object and can be accessed
2685 * via `chrono::get_tzdb_list().front()` or `chrono::get_tzdb()` or
2686 * `*chrono::get_tzdb_list().begin()`.
2687 *
2688 * The `chrono::reload_tzdb()` function will check for a newer version
2689 * and if found, insert it at the front of the list.
2690 *
2691 * @since C++20
2692 */
2693 class tzdb_list
2694 {
2695 struct _Node;
2696
2697 public:
2698 tzdb_list(const tzdb_list&) = delete;
2699 tzdb_list& operator=(const tzdb_list&) = delete;
2700
2701 /** An iterator into the `tzdb_list`
2702 *
2703 * As a extension, in libstdc++ each `tzdb` is reference-counted
2704 * and the `const_iterator` type shares ownership of the object it
2705 * refers to. This ensures that a `tzdb` erased from the list will
2706 * not be destroyed while there is an iterator that refers to it.
2707 */
2708 class const_iterator
2709 {
2710 public:
2711 using value_type = tzdb;
2712 using reference = const tzdb&;
2713 using pointer = const tzdb*;
2714 using difference_type = ptrdiff_t;
2715 using iterator_category = forward_iterator_tag;
2716
2717 constexpr const_iterator() = default;
2718 const_iterator(const const_iterator&) = default;
2719 const_iterator(const_iterator&&) = default;
2720 const_iterator& operator=(const const_iterator&) = default;
2721 const_iterator& operator=(const_iterator&&) = default;
2722
2723 reference operator*() const noexcept;
2724 pointer operator->() const noexcept { return &**this; }
2725 const_iterator& operator++();
2726 const_iterator operator++(int);
2727
2728 bool operator==(const const_iterator&) const noexcept = default;
2729
2730 private:
2731 explicit const_iterator(const shared_ptr<_Node>&) noexcept;
2732
2733 friend class tzdb_list;
2734
2735 shared_ptr<_Node> _M_node;
2736 void* _M_reserved = nullptr;
2737 };
2738
2739 /** Access the current `tzdb` at the front of the list.
2740 *
2741 * This returns a reference to the same object as `chrono::get_tzdb()`.
2742 *
2743 * @returns A reference to the current tzdb object.
2744 * @since C++20
2745 */
2746 const tzdb& front() const noexcept;
2747
2748 /** Remove the tzdb object _after_ the one the iterator refers to.
2749 *
2750 * Calling this function concurently with any of `front()`, `begin()`,
2751 * or `end()` does not cause a data race, but in general this function
2752 * is not thread-safe. The behaviour may be undefined if erasing an
2753 * element from the list while another thread is calling the same
2754 * function, or incrementing an iterator into the list, or accessing
2755 * the element being erased (unless it is accessed through an iterator).
2756 *
2757 * @param __p A dereferenceable iterator.
2758 * @returns An iterator the element after the one that was erased
2759 * (or `end()` if there is no such element).
2760 * @since C++20
2761 */
2762 const_iterator erase_after(const_iterator __p);
2763
2764 const_iterator begin() const noexcept;
2765 const_iterator end() const noexcept { return {}; }
2766 const_iterator cbegin() const noexcept { return begin(); }
2767 const_iterator cend() const noexcept { return end(); }
2768
2769 private:
2770 constexpr explicit tzdb_list(nullptr_t);
2771
2772 friend tzdb_list& get_tzdb_list();
2773 friend const tzdb& get_tzdb();
2774 friend const tzdb& reload_tzdb();
2775 friend struct tzdb;
2776 friend class leap_second;
2777 friend struct time_zone::_Impl;
2778 friend class time_zone_link;
2779 };
2780
1736bf5a
JW
2781 class time_zone_link
2782 {
2783 public:
2784 time_zone_link(time_zone_link&&) = default;
2785 time_zone_link& operator=(time_zone_link&&) = default;
2786
2787 string_view name() const noexcept { return _M_name; }
2788 string_view target() const noexcept { return _M_target; }
2789
2790 friend bool
2791 operator==(const time_zone_link& __x, const time_zone_link& __y) noexcept
2792 { return __x.name() == __y.name(); }
2793
2794 friend strong_ordering
2795 operator<=>(const time_zone_link& __x, const time_zone_link& __y) noexcept
2796 { return __x.name() <=> __y.name(); }
2797
2798 private:
2799 friend const tzdb& reload_tzdb();
5b46eacc 2800 friend struct tzdb_list::_Node;
9fc61d45
JW
2801
2802 explicit time_zone_link(nullptr_t) { }
2803
1736bf5a
JW
2804 string _M_name;
2805 string _M_target;
2806 };
2807
2808 class leap_second
2809 {
2810 public:
2811 leap_second(const leap_second&) = default;
2812 leap_second& operator=(const leap_second&) = default;
2813
ec8f914f 2814 [[nodiscard]]
1736bf5a
JW
2815 constexpr sys_seconds
2816 date() const noexcept
2817 {
2818 if (_M_s >= _M_s.zero()) [[likely]]
2819 return sys_seconds(_M_s);
2820 return sys_seconds(-_M_s);
2821 }
2822
ec8f914f 2823 [[nodiscard]]
1736bf5a
JW
2824 constexpr seconds
2825 value() const noexcept
2826 {
2827 if (_M_s >= _M_s.zero()) [[likely]]
2828 return seconds(1);
2829 return seconds(-1);
2830 }
2831
2832 // This can be defaulted because the database will never contain two
2833 // leap_second objects with the same date but different signs.
ec8f914f 2834 [[nodiscard]] friend constexpr bool
1736bf5a
JW
2835 operator==(const leap_second&, const leap_second&) noexcept = default;
2836
ec8f914f 2837 [[nodiscard]] friend constexpr strong_ordering
1736bf5a
JW
2838 operator<=>(const leap_second& __x, const leap_second& __y) noexcept
2839 { return __x.date() <=> __y.date(); }
2840
2841 template<typename _Duration>
ec8f914f 2842 [[nodiscard]] friend constexpr bool
1736bf5a
JW
2843 operator==(const leap_second& __x,
2844 const sys_time<_Duration>& __y) noexcept
2845 { return __x.date() == __y; }
2846
2847 template<typename _Duration>
ec8f914f 2848 [[nodiscard]] friend constexpr bool
1736bf5a
JW
2849 operator<(const leap_second& __x,
2850 const sys_time<_Duration>& __y) noexcept
2851 { return __x.date() < __y; }
2852
2853 template<typename _Duration>
ec8f914f 2854 [[nodiscard]] friend constexpr bool
1736bf5a
JW
2855 operator<(const sys_time<_Duration>& __x,
2856 const leap_second& __y) noexcept
2857 { return __x < __y.date(); }
2858
2859 template<typename _Duration>
ec8f914f 2860 [[nodiscard]] friend constexpr bool
1736bf5a
JW
2861 operator>(const leap_second& __x,
2862 const sys_time<_Duration>& __y) noexcept
2863 { return __y < __x.date(); }
2864
2865 template<typename _Duration>
ec8f914f 2866 [[nodiscard]] friend constexpr bool
1736bf5a
JW
2867 operator>(const sys_time<_Duration>& __x,
2868 const leap_second& __y) noexcept
2869 { return __y.date() < __x; }
2870
2871 template<typename _Duration>
ec8f914f 2872 [[nodiscard]] friend constexpr bool
1736bf5a 2873 operator<=(const leap_second& __x,
ec8f914f 2874 const sys_time<_Duration>& __y) noexcept
1736bf5a
JW
2875 { return !(__y < __x.date()); }
2876
2877 template<typename _Duration>
ec8f914f 2878 [[nodiscard]] friend constexpr bool
1736bf5a 2879 operator<=(const sys_time<_Duration>& __x,
ec8f914f 2880 const leap_second& __y) noexcept
1736bf5a
JW
2881 { return !(__y.date() < __x); }
2882
2883 template<typename _Duration>
ec8f914f 2884 [[nodiscard]] friend constexpr bool
1736bf5a 2885 operator>=(const leap_second& __x,
ec8f914f 2886 const sys_time<_Duration>& __y) noexcept
1736bf5a
JW
2887 { return !(__x.date() < __y); }
2888
2889 template<typename _Duration>
ec8f914f 2890 [[nodiscard]] friend constexpr bool
1736bf5a 2891 operator>=(const sys_time<_Duration>& __x,
ec8f914f 2892 const leap_second& __y) noexcept
1736bf5a
JW
2893 { return !(__x < __y.date()); }
2894
2895 template<three_way_comparable_with<seconds> _Duration>
ec8f914f 2896 [[nodiscard]] friend constexpr auto
1736bf5a 2897 operator<=>(const leap_second& __x,
ec8f914f 2898 const sys_time<_Duration>& __y) noexcept
1736bf5a
JW
2899 { return __x.date() <=> __y; }
2900
2901 private:
2902 explicit leap_second(seconds::rep __s) : _M_s(__s) { }
2903
5b46eacc 2904 friend struct tzdb_list::_Node;
9fc61d45 2905
1736bf5a 2906 friend const tzdb& reload_tzdb();
9fc61d45
JW
2907
2908 template<typename _Duration>
1736bf5a 2909 friend leap_second_info
9fc61d45 2910 get_leap_second_info(const utc_time<_Duration>&);
1736bf5a
JW
2911
2912 seconds _M_s; // == date().time_since_epoch() * value().count()
2913 };
2914
2915 template<class _Tp> struct zoned_traits { };
2916
2917 template<>
2918 struct zoned_traits<const time_zone*>
2919 {
2920 static const time_zone*
2921 default_zone()
2922 { return std::chrono::locate_zone("UTC"); }
2923
2924 static const time_zone*
2925 locate_zone(string_view __name)
2926 { return std::chrono::locate_zone(__name); }
2927 };
2928
2929 struct tzdb
2930 {
2931 string version;
9fc61d45
JW
2932 _GLIBCXX_STD_C::vector<time_zone> zones;
2933 _GLIBCXX_STD_C::vector<time_zone_link> links;
2934 _GLIBCXX_STD_C::vector<leap_second> leap_seconds;
1736bf5a
JW
2935
2936 const time_zone*
2937 locate_zone(string_view __tz_name) const;
2938
2939 const time_zone*
2940 current_zone() const;
2941
2942 private:
2943 friend const tzdb& reload_tzdb();
9fc61d45 2944 friend class time_zone;
5b46eacc 2945 friend struct tzdb_list::_Node;
1736bf5a
JW
2946 };
2947
9fc61d45
JW
2948 tzdb_list& get_tzdb_list();
2949 const tzdb& get_tzdb();
1736bf5a 2950
9fc61d45
JW
2951 const tzdb& reload_tzdb();
2952 string remote_version();
2953
2954 template<typename _Duration, typename _TimeZonePtr = const time_zone*>
2955 class zoned_time
1736bf5a 2956 {
9fc61d45
JW
2957 static_assert(__is_duration_v<_Duration>);
2958
2959 using _Traits = zoned_traits<_TimeZonePtr>;
2960
2961 // Every constructor that accepts a string_view as its first parameter
2962 // does not participate in class template argument deduction.
2963 using string_view = type_identity_t<std::string_view>;
2964
1736bf5a 2965 public:
9fc61d45 2966 using duration = common_type_t<_Duration, seconds>;
1736bf5a 2967
9fc61d45
JW
2968 zoned_time() requires requires { _Traits::default_zone(); }
2969 { }
1736bf5a 2970
9fc61d45
JW
2971 zoned_time(const zoned_time&) = default;
2972 zoned_time& operator=(const zoned_time&) = default;
1736bf5a 2973
9fc61d45
JW
2974 zoned_time(const sys_time<_Duration>& __st)
2975 requires requires { _Traits::default_zone(); }
2976 : _M_tp(__st)
2977 { }
1736bf5a 2978
9fc61d45
JW
2979 explicit
2980 zoned_time(_TimeZonePtr __z) : _M_zone(std::move(__z)) { }
1736bf5a 2981
9fc61d45
JW
2982 explicit
2983 zoned_time(string_view __name)
2984 requires requires {
2985 _TimeZonePtr{_Traits::locate_zone(std::string_view{})};
2986 }
2987 : _M_zone(_Traits::locate_zone(__name))
2988 { }
1736bf5a 2989
9fc61d45
JW
2990 template<typename _Duration2>
2991 zoned_time(const zoned_time<_Duration2, _TimeZonePtr>& __zt)
2992 requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>
2993 : _M_zone(__zt._M_zone), _M_tp(__zt._M_tp)
2994 { }
1736bf5a 2995
9fc61d45
JW
2996 zoned_time(_TimeZonePtr __z, const sys_time<_Duration>& __st)
2997 : _M_zone(std::move(__z)), _M_tp(__st)
2998 { }
1736bf5a 2999
9fc61d45
JW
3000 zoned_time(string_view __name, const sys_time<_Duration>& __st)
3001 : zoned_time(_Traits::locate_zone(__name), __st)
3002 { }
1736bf5a 3003
9fc61d45
JW
3004 zoned_time(_TimeZonePtr __z, const local_time<_Duration>& __tp)
3005 requires requires {
3006 { __z->to_sys(__tp) } -> convertible_to<sys_time<_Duration>>;
3007 }
3008 : _M_zone(std::move(__z)), _M_tp(_M_zone->to_sys(__tp))
3009 { }
1736bf5a 3010
9fc61d45
JW
3011 zoned_time(string_view __name, const local_time<_Duration>& __tp)
3012 requires requires (_TimeZonePtr __z) {
3013 { _Traits::locate_zone(__name) } -> convertible_to<_TimeZonePtr>;
3014 { __z->to_sys(__tp) } -> convertible_to<sys_time<_Duration>>;
3015 }
3016 : zoned_time(_Traits::locate_zone(__name), __tp)
3017 { }
1736bf5a 3018
9fc61d45
JW
3019 zoned_time(_TimeZonePtr __z, const local_time<_Duration>& __tp,
3020 choose __c)
3021 requires requires {
3022 { __z->to_sys(__tp, __c) } -> convertible_to<sys_time<_Duration>>;
3023 }
3024 : _M_zone(std::move(__z)), _M_tp(_M_zone->to_sys(__tp, __c))
3025 { }
1736bf5a 3026
9fc61d45
JW
3027 zoned_time(string_view __name, const local_time<_Duration>& __tp,
3028 choose __c)
3029 requires requires (_TimeZonePtr __z) {
3030 { _Traits::locate_zone(__name) } -> convertible_to<_TimeZonePtr>;
3031 { __z->to_sys(__tp, __c) } -> convertible_to<sys_time<_Duration>>;
3032 }
3033 : _M_zone(_Traits::locate_zone(__name)),
3034 _M_tp(_M_zone->to_sys(__tp, __c))
3035 { }
1736bf5a 3036
9fc61d45
JW
3037 template<typename _Duration2, typename _TimeZonePtr2>
3038 zoned_time(_TimeZonePtr __z,
3039 const zoned_time<_Duration2, _TimeZonePtr2>& __zt)
3040 requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>
3041 : _M_zone(__z), _M_tp(__zt._M_tp)
3042 { }
3043
3044 template<typename _Duration2, typename _TimeZonePtr2>
3045 zoned_time(_TimeZonePtr __z,
3046 const zoned_time<_Duration2, _TimeZonePtr2>& __zt,
af89c779 3047 choose)
9fc61d45
JW
3048 requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>
3049 : _M_zone(__z), _M_tp(__zt._M_tp)
3050 { }
3051
3052 template<typename _Duration2, typename _TimeZonePtr2>
3053 zoned_time(string_view __name,
3054 const zoned_time<_Duration2, _TimeZonePtr2>& __zt)
3055 requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>
3056 && requires {
3057 { _Traits::locate_zone(__name) } -> convertible_to<_TimeZonePtr>;
3058 }
3059 : _M_zone(_Traits::locate_zone(__name)), _M_tp(__zt._M_tp)
3060 { }
3061
3062 template<typename _Duration2, typename _TimeZonePtr2>
3063 zoned_time(string_view __name,
3064 const zoned_time<_Duration2, _TimeZonePtr2>& __zt,
af89c779 3065 choose)
9fc61d45
JW
3066 requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>
3067 && requires {
3068 { _Traits::locate_zone(__name) } -> convertible_to<_TimeZonePtr>;
3069 }
3070 : _M_zone(_Traits::locate_zone(__name)), _M_tp(__zt._M_tp)
3071 { }
1736bf5a 3072
9fc61d45
JW
3073 zoned_time&
3074 operator=(const sys_time<_Duration>& __st)
3075 {
3076 _M_tp = __st;
3077 return *this;
3078 }
3079
3080 zoned_time&
3081 operator=(const local_time<_Duration>& __lt)
3082 {
3083 _M_tp = _M_zone->to_sys(__lt);
3084 return *this;
3085 }
3086
3087 [[nodiscard]]
3088 operator sys_time<duration>() const { return _M_tp; }
3089
3090 [[nodiscard]]
3091 explicit operator local_time<duration>() const
3092 { return get_local_time(); }
3093
3094 [[nodiscard]]
3095 _TimeZonePtr
3096 get_time_zone() const
3097 { return _M_zone; }
3098
3099 [[nodiscard]]
3100 local_time<duration>
3101 get_local_time() const
3102 { return _M_zone->to_local(_M_tp); }
3103
3104 [[nodiscard]]
3105 sys_time<duration>
3106 get_sys_time() const
3107 { return _M_tp; }
3108
3109 [[nodiscard]]
3110 sys_info
3111 get_info() const
3112 { return _M_zone->get_info(_M_tp); }
3113
3114 [[nodiscard]] friend bool
3115 operator==(const zoned_time&, const zoned_time&) = default;
3116
3117 private:
3118 _TimeZonePtr _M_zone{ _Traits::default_zone() };
3119 sys_time<duration> _M_tp{};
3120
3121 template<typename _Duration2, typename _TimeZonePtr2>
3122 friend class zoned_time;
3123 };
3124
3125 zoned_time() -> zoned_time<seconds>;
3126
3127 template<typename _Duration>
3128 zoned_time(sys_time<_Duration>)
3129 -> zoned_time<common_type_t<_Duration, seconds>>;
3130
3131 /// @cond undocumented
3132 template<typename _TimeZonePtrOrName>
3133 using __time_zone_representation
3134 = __conditional_t<is_convertible_v<_TimeZonePtrOrName, string_view>,
3135 const time_zone*,
3136 remove_cvref_t<_TimeZonePtrOrName>>;
3137 /// @endcond
3138
3139 template<typename _TimeZonePtrOrName>
3140 zoned_time(_TimeZonePtrOrName&&)
3141 -> zoned_time<seconds, __time_zone_representation<_TimeZonePtrOrName>>;
3142
3143 template<typename _TimeZonePtrOrName, typename _Duration>
3144 zoned_time(_TimeZonePtrOrName&&, sys_time<_Duration>)
3145 -> zoned_time<common_type_t<_Duration, seconds>,
3146 __time_zone_representation<_TimeZonePtrOrName>>;
3147
3148 template<typename _TimeZonePtrOrName, typename _Duration>
3149 zoned_time(_TimeZonePtrOrName&&, local_time<_Duration>,
3150 choose = choose::earliest)
3151 -> zoned_time<common_type_t<_Duration, seconds>,
3152 __time_zone_representation<_TimeZonePtrOrName>>;
3153
3154 template<typename _Duration, typename _TimeZonePtrOrName,
3155 typename _TimeZonePtr2>
3156 zoned_time(_TimeZonePtrOrName&&, zoned_time<_Duration, _TimeZonePtr2>,
3157 choose = choose::earliest)
3158 -> zoned_time<common_type_t<_Duration, seconds>,
3159 __time_zone_representation<_TimeZonePtrOrName>>;
3160
3161 template<typename _Dur1, typename _TZPtr1, typename _Dur2, typename _TZPtr2>
3162 [[nodiscard]]
3163 inline bool
3164 operator==(const zoned_time<_Dur1, _TZPtr1>& __x,
3165 const zoned_time<_Dur2, _TZPtr2>& __y)
3166 {
3167 return __x.get_time_zone() == __y.get_time_zone()
3168 && __x.get_sys_time() == __y.get_sys_time();
3169 }
1736bf5a
JW
3170
3171 using zoned_seconds = zoned_time<seconds>;
9fc61d45
JW
3172#endif // _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
3173
3174namespace __detail
3175{
3176 inline leap_second_info
3177 __get_leap_second_info(sys_seconds __ss, bool __is_utc)
3178 {
3179 if (__ss < sys_seconds{}) [[unlikely]]
3180 return {};
3181
3182 const seconds::rep __leaps[] {
3183 78796800, // 1 Jul 1972
3184 94694400, // 1 Jan 1973
3185 126230400, // 1 Jan 1974
3186 157766400, // 1 Jan 1975
3187 189302400, // 1 Jan 1976
3188 220924800, // 1 Jan 1977
3189 252460800, // 1 Jan 1978
3190 283996800, // 1 Jan 1979
3191 315532800, // 1 Jan 1980
3192 362793600, // 1 Jul 1981
3193 394329600, // 1 Jul 1982
3194 425865600, // 1 Jul 1983
3195 489024000, // 1 Jul 1985
3196 567993600, // 1 Jan 1988
3197 631152000, // 1 Jan 1990
3198 662688000, // 1 Jan 1991
3199 709948800, // 1 Jul 1992
3200 741484800, // 1 Jul 1993
3201 773020800, // 1 Jul 1994
3202 820454400, // 1 Jan 1996
3203 867715200, // 1 Jul 1997
3204 915148800, // 1 Jan 1999
3205 1136073600, // 1 Jan 2006
3206 1230768000, // 1 Jan 2009
3207 1341100800, // 1 Jul 2012
3208 1435708800, // 1 Jul 2015
3209 1483228800, // 1 Jan 2017
3210 };
3211 // The list above is known to be valid until (at least) this date
3212 // and only contains positive leap seconds.
cf19ef9e 3213 const sys_seconds __expires(1703721600s); // 2023-12-28 00:00:00 UTC
9fc61d45
JW
3214
3215#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
3216 if (__ss > __expires)
3217 {
3218 // Use updated leap_seconds from tzdb.
3219 size_t __n = std::size(__leaps);
3220
3221 auto __db = get_tzdb_list().begin();
3222 auto __first = __db->leap_seconds.begin() + __n;
3223 auto __last = __db->leap_seconds.end();
3224 auto __pos = std::upper_bound(__first, __last, __ss);
3225 seconds __elapsed(__n);
3226 for (auto __i = __first; __i != __pos; ++__i)
3227 __elapsed += __i->value();
3228
3229 if (__is_utc)
3230 {
3231 // Convert utc_time to sys_time:
3232 __ss -= __elapsed;
3233 // See if that sys_time is before (or during) previous leap sec:
3234 if (__pos != __first && __ss < __pos[-1])
3235 {
3236 if ((__ss + 1s) >= __pos[-1])
3237 return {true, __elapsed};
3238 __elapsed -= __pos[-1].value();
3239 }
3240 }
3241 return {false, __elapsed};
3242 }
3243 else
3244#endif
3245 {
3246 seconds::rep __s = __ss.time_since_epoch().count();
3247 const seconds::rep* __first = std::begin(__leaps);
3248 const seconds::rep* __last = std::end(__leaps);
3249
3250 // Don't bother searching the list if we're after the last one.
3251 if (__s > (__last[-1] + (__last - __first) + 1))
3252 return { false, seconds(__last - __first) };
3253
3254 auto __pos = std::upper_bound(__first, __last, __s);
3255 seconds __elapsed{__pos - __first};
3256 if (__is_utc)
3257 {
3258 // Convert utc_time to sys_time:
3259 __s -= __elapsed.count();
3260 // See if that sys_time is before (or during) previous leap sec:
3261 if (__pos != __first && __s < __pos[-1])
3262 {
3263 if ((__s + 1) >= __pos[-1])
3264 return {true, __elapsed};
3265 --__elapsed;
3266 }
3267 }
3268 return {false, __elapsed};
3269 }
3270 }
3271} // namespace __detail
1736bf5a
JW
3272
3273 template<typename _Duration>
9fc61d45
JW
3274 [[nodiscard]]
3275 inline leap_second_info
1736bf5a
JW
3276 get_leap_second_info(const utc_time<_Duration>& __ut)
3277 {
9fc61d45
JW
3278 auto __s = chrono::duration_cast<seconds>(__ut.time_since_epoch());
3279 return __detail::__get_leap_second_info(sys_seconds(__s), true);
3280 }
1736bf5a 3281
9fc61d45
JW
3282 template<typename _Duration>
3283 [[nodiscard]]
3284 inline utc_time<common_type_t<_Duration, seconds>>
3285 utc_clock::from_sys(const sys_time<_Duration>& __t)
3286 {
3287 using _CDur = common_type_t<_Duration, seconds>;
3288 auto __s = chrono::time_point_cast<seconds>(__t);
3289 const auto __li = __detail::__get_leap_second_info(__s, false);
3290 return utc_time<_CDur>{__t.time_since_epoch()} + __li.elapsed;
1736bf5a
JW
3291 }
3292
f2ce64b5 3293 /// @} group chrono
7f78718b 3294#endif // C++20
f2ce64b5 3295 } // namespace chrono
04f69fda 3296
7f78718b
JW
3297#if __cplusplus >= 202002L
3298 inline namespace literals
bf1fc37b 3299 {
7f78718b
JW
3300 inline namespace chrono_literals
3301 {
3302 /// @addtogroup chrono
3303 /// @{
3304#pragma GCC diagnostic push
3305#pragma GCC diagnostic ignored "-Wliteral-suffix"
3306 /// Literal suffix for creating chrono::day objects.
3307 /// @since C++20
3308 constexpr chrono::day
3309 operator""d(unsigned long long __d) noexcept
3310 { return chrono::day{static_cast<unsigned>(__d)}; }
bf1fc37b 3311
7f78718b
JW
3312 /// Literal suffix for creating chrono::year objects.
3313 /// @since C++20
3314 constexpr chrono::year
3315 operator""y(unsigned long long __y) noexcept
3316 { return chrono::year{static_cast<int>(__y)}; }
3317#pragma GCC diagnostic pop
3318 /// @}
3319 } // inline namespace chrono_literals
3320 } // inline namespace literals
3321#endif // C++20
88c4d6b7 3322
4a15d842 3323_GLIBCXX_END_NAMESPACE_VERSION
1c9f675f
ESR
3324} // namespace std
3325
f99b9486
JW
3326#if __cplusplus >= 202002L
3327# include <bits/chrono_io.h>
3328#endif
3329
88c4d6b7 3330#endif // C++11
1c9f675f 3331
15e38d0d 3332#endif //_GLIBCXX_CHRONO