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