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