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