]>
Commit | Line | Data |
---|---|---|
15e38d0d CF |
1 | // <chrono> -*- C++ -*- |
2 | ||
7adcbafe | 3 | // Copyright (C) 2008-2022 Free Software Foundation, Inc. |
15e38d0d CF |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
748086b7 | 8 | // Free Software Foundation; either version 3, or (at your option) |
15e38d0d CF |
9 | // any later version. |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
748086b7 JJ |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
15e38d0d | 19 | |
748086b7 JJ |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
15e38d0d CF |
24 | |
25 | /** @file include/chrono | |
26 | * This is a Standard C++ Library header. | |
c34d3fd3 | 27 | * @ingroup chrono |
15e38d0d CF |
28 | */ |
29 | ||
30 | #ifndef _GLIBCXX_CHRONO | |
31 | #define _GLIBCXX_CHRONO 1 | |
32 | ||
33 | #pragma GCC system_header | |
34 | ||
734f5023 | 35 | #if __cplusplus < 201103L |
ab65a4c7 | 36 | # include <bits/c++0x_warning.h> |
15e38d0d CF |
37 | #else |
38 | ||
7f78718b | 39 | #include <bits/chrono.h> |
fcc13d6f JW |
40 | #if __cplusplus > 201703L |
41 | # include <sstream> // ostringstream | |
42 | # include <bits/charconv.h> | |
43 | #endif | |
15e38d0d | 44 | |
12ffa228 BK |
45 | namespace std _GLIBCXX_VISIBILITY(default) |
46 | { | |
4a15d842 FD |
47 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
48 | ||
5b9daa7e BK |
49 | /** |
50 | * @defgroup chrono Time | |
51 | * @ingroup utilities | |
52 | * | |
53 | * Classes and functions for time. | |
f2ce64b5 JW |
54 | * |
55 | * @since C++11 | |
5b9daa7e BK |
56 | */ |
57 | ||
58 | /** @namespace std::chrono | |
19aaf814 | 59 | * @brief ISO C++ 2011 namespace for date and time utilities |
f2ce64b5 | 60 | * @ingroup chrono |
5b9daa7e | 61 | */ |
15e38d0d CF |
62 | namespace chrono |
63 | { | |
7f78718b | 64 | #if __cplusplus >= 202002L |
f2ce64b5 JW |
65 | /// @addtogroup chrono |
66 | /// @{ | |
16948c54 JW |
67 | struct local_t { }; |
68 | template<typename _Duration> | |
69 | using local_time = time_point<local_t, _Duration>; | |
70 | using local_seconds = local_time<seconds>; | |
71 | using local_days = local_time<days>; | |
bf1fc37b | 72 | |
03d5044b PP |
73 | class utc_clock; |
74 | class tai_clock; | |
75 | class gps_clock; | |
5b9daa7e | 76 | |
03d5044b PP |
77 | template<typename _Duration> |
78 | using utc_time = time_point<utc_clock, _Duration>; | |
79 | using utc_seconds = utc_time<seconds>; | |
15e38d0d | 80 | |
03d5044b PP |
81 | template<typename _Duration> |
82 | using tai_time = time_point<tai_clock, _Duration>; | |
83 | using tai_seconds = tai_time<seconds>; | |
a15f7cb8 | 84 | |
03d5044b PP |
85 | template<typename _Duration> |
86 | using gps_time = time_point<gps_clock, _Duration>; | |
87 | using gps_seconds = gps_time<seconds>; | |
88 | ||
89 | template<> struct is_clock<utc_clock> : true_type { }; | |
90 | template<> struct is_clock<tai_clock> : true_type { }; | |
91 | template<> struct is_clock<gps_clock> : true_type { }; | |
92 | ||
93 | template<> inline constexpr bool is_clock_v<utc_clock> = true; | |
94 | template<> inline constexpr bool is_clock_v<tai_clock> = true; | |
95 | template<> inline constexpr bool is_clock_v<gps_clock> = true; | |
96 | ||
97 | struct leap_second_info | |
98 | { | |
99 | bool is_leap_second; | |
100 | seconds elapsed; | |
101 | }; | |
102 | ||
103 | // CALENDRICAL TYPES | |
104 | ||
105 | // CLASS DECLARATIONS | |
106 | class day; | |
107 | class month; | |
108 | class year; | |
109 | class weekday; | |
110 | class weekday_indexed; | |
111 | class weekday_last; | |
112 | class month_day; | |
113 | class month_day_last; | |
114 | class month_weekday; | |
115 | class month_weekday_last; | |
116 | class year_month; | |
117 | class year_month_day; | |
118 | class year_month_day_last; | |
119 | class year_month_weekday; | |
120 | class year_month_weekday_last; | |
121 | ||
122 | struct last_spec | |
123 | { | |
124 | explicit last_spec() = default; | |
125 | ||
126 | friend constexpr month_day_last | |
127 | operator/(int __m, last_spec) noexcept; | |
128 | ||
129 | friend constexpr month_day_last | |
130 | operator/(last_spec, int __m) noexcept; | |
131 | }; | |
132 | ||
133 | inline constexpr last_spec last{}; | |
134 | ||
135 | namespace __detail | |
136 | { | |
137 | // Compute the remainder of the Euclidean division of __n divided by __d. | |
138 | // Euclidean division truncates toward negative infinity and always | |
139 | // produces a remainder in the range of [0,__d-1] (whereas standard | |
140 | // division truncates toward zero and yields a nonpositive remainder | |
141 | // for negative __n). | |
142 | constexpr unsigned | |
143 | __modulo(long long __n, unsigned __d) | |
cd1464db | 144 | { |
03d5044b PP |
145 | if (__n >= 0) |
146 | return __n % __d; | |
147 | else | |
148 | return (__d + (__n % __d)) % __d; | |
cd1464db | 149 | } |
1c9f675f | 150 | |
03d5044b PP |
151 | inline constexpr unsigned __days_per_month[12] |
152 | = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; | |
03d5044b | 153 | } |
88c4d6b7 | 154 | |
03d5044b | 155 | // DAY |
1c9f675f | 156 | |
03d5044b PP |
157 | class day |
158 | { | |
159 | private: | |
160 | unsigned char _M_d; | |
1c9f675f | 161 | |
03d5044b PP |
162 | public: |
163 | day() = default; | |
1c9f675f | 164 | |
03d5044b PP |
165 | explicit constexpr |
166 | day(unsigned __d) noexcept | |
167 | : _M_d(__d) | |
168 | { } | |
1c9f675f | 169 | |
03d5044b PP |
170 | constexpr day& |
171 | operator++() noexcept | |
172 | { | |
173 | ++_M_d; | |
174 | return *this; | |
175 | } | |
1c9f675f | 176 | |
03d5044b PP |
177 | constexpr day |
178 | operator++(int) noexcept | |
179 | { | |
180 | auto __ret = *this; | |
181 | ++(*this); | |
182 | return __ret; | |
183 | } | |
1c9f675f | 184 | |
03d5044b PP |
185 | constexpr day& |
186 | operator--() noexcept | |
187 | { | |
188 | --_M_d; | |
189 | return *this; | |
190 | } | |
1c9f675f | 191 | |
03d5044b PP |
192 | constexpr day |
193 | operator--(int) noexcept | |
194 | { | |
195 | auto __ret = *this; | |
196 | --(*this); | |
197 | return __ret; | |
198 | } | |
88c4d6b7 | 199 | |
03d5044b PP |
200 | constexpr day& |
201 | operator+=(const days& __d) noexcept | |
202 | { | |
203 | *this = *this + __d; | |
204 | return *this; | |
205 | } | |
88c4d6b7 | 206 | |
03d5044b PP |
207 | constexpr day& |
208 | operator-=(const days& __d) noexcept | |
209 | { | |
210 | *this = *this - __d; | |
211 | return *this; | |
212 | } | |
88c4d6b7 | 213 | |
03d5044b PP |
214 | constexpr explicit |
215 | operator unsigned() const noexcept | |
216 | { return _M_d; } | |
88c4d6b7 | 217 | |
03d5044b PP |
218 | constexpr bool |
219 | ok() const noexcept | |
220 | { return 1 <= _M_d && _M_d <= 31; } | |
221 | ||
222 | friend constexpr bool | |
223 | operator==(const day& __x, const day& __y) noexcept | |
224 | { return unsigned{__x} == unsigned{__y}; } | |
225 | ||
226 | friend constexpr strong_ordering | |
227 | operator<=>(const day& __x, const day& __y) noexcept | |
228 | { return unsigned{__x} <=> unsigned{__y}; } | |
229 | ||
230 | friend constexpr day | |
231 | operator+(const day& __x, const days& __y) noexcept | |
232 | { return day(unsigned{__x} + __y.count()); } | |
233 | ||
234 | friend constexpr day | |
235 | operator+(const days& __x, const day& __y) noexcept | |
236 | { return __y + __x; } | |
237 | ||
238 | friend constexpr day | |
239 | operator-(const day& __x, const days& __y) noexcept | |
240 | { return __x + -__y; } | |
241 | ||
242 | friend constexpr days | |
243 | operator-(const day& __x, const day& __y) noexcept | |
244 | { return days{int(unsigned{__x}) - int(unsigned{__y})}; } | |
245 | ||
246 | friend constexpr month_day | |
247 | operator/(const month& __m, const day& __d) noexcept; | |
248 | ||
249 | friend constexpr month_day | |
250 | operator/(int __m, const day& __d) noexcept; | |
251 | ||
252 | friend constexpr month_day | |
253 | operator/(const day& __d, const month& __m) noexcept; | |
254 | ||
255 | friend constexpr month_day | |
256 | operator/(const day& __d, int __m) noexcept; | |
257 | ||
258 | friend constexpr year_month_day | |
259 | operator/(const year_month& __ym, const day& __d) noexcept; | |
260 | ||
261 | // TODO: Implement operator<<, to_stream, from_stream. | |
262 | }; | |
263 | ||
264 | // MONTH | |
265 | ||
266 | class month | |
267 | { | |
268 | private: | |
269 | unsigned char _M_m; | |
270 | ||
271 | public: | |
272 | month() = default; | |
273 | ||
274 | explicit constexpr | |
275 | month(unsigned __m) noexcept | |
276 | : _M_m(__m) | |
277 | { } | |
278 | ||
279 | constexpr month& | |
280 | operator++() noexcept | |
281 | { | |
282 | *this += months{1}; | |
283 | return *this; | |
284 | } | |
285 | ||
286 | constexpr month | |
287 | operator++(int) noexcept | |
288 | { | |
289 | auto __ret = *this; | |
290 | ++(*this); | |
291 | return __ret; | |
292 | } | |
293 | ||
294 | constexpr month& | |
295 | operator--() noexcept | |
296 | { | |
297 | *this -= months{1}; | |
298 | return *this; | |
299 | } | |
300 | ||
301 | constexpr month | |
302 | operator--(int) noexcept | |
303 | { | |
304 | auto __ret = *this; | |
305 | --(*this); | |
306 | return __ret; | |
307 | } | |
308 | ||
309 | constexpr month& | |
310 | operator+=(const months& __m) noexcept | |
311 | { | |
312 | *this = *this + __m; | |
313 | return *this; | |
314 | } | |
315 | ||
316 | constexpr month& | |
317 | operator-=(const months& __m) noexcept | |
318 | { | |
319 | *this = *this - __m; | |
320 | return *this; | |
321 | } | |
322 | ||
323 | explicit constexpr | |
324 | operator unsigned() const noexcept | |
325 | { return _M_m; } | |
326 | ||
327 | constexpr bool | |
328 | ok() const noexcept | |
329 | { return 1 <= _M_m && _M_m <= 12; } | |
330 | ||
331 | friend constexpr bool | |
332 | operator==(const month& __x, const month& __y) noexcept | |
333 | { return unsigned{__x} == unsigned{__y}; } | |
334 | ||
335 | friend constexpr strong_ordering | |
336 | operator<=>(const month& __x, const month& __y) noexcept | |
337 | { return unsigned{__x} <=> unsigned{__y}; } | |
338 | ||
339 | friend constexpr month | |
340 | operator+(const month& __x, const months& __y) noexcept | |
341 | { | |
342 | auto __n = static_cast<long long>(unsigned{__x}) + (__y.count() - 1); | |
343 | return month{__detail::__modulo(__n, 12) + 1}; | |
344 | } | |
345 | ||
346 | friend constexpr month | |
347 | operator+(const months& __x, const month& __y) noexcept | |
348 | { return __y + __x; } | |
349 | ||
350 | friend constexpr month | |
351 | operator-(const month& __x, const months& __y) noexcept | |
352 | { return __x + -__y; } | |
353 | ||
354 | friend constexpr months | |
355 | operator-(const month& __x, const month& __y) noexcept | |
356 | { | |
357 | const auto __dm = int(unsigned(__x)) - int(unsigned(__y)); | |
358 | return months{__dm < 0 ? 12 + __dm : __dm}; | |
359 | } | |
360 | ||
361 | friend constexpr year_month | |
362 | operator/(const year& __y, const month& __m) noexcept; | |
363 | ||
364 | friend constexpr month_day | |
365 | operator/(const month& __m, int __d) noexcept; | |
366 | ||
367 | friend constexpr month_day_last | |
368 | operator/(const month& __m, last_spec) noexcept; | |
369 | ||
370 | friend constexpr month_day_last | |
371 | operator/(last_spec, const month& __m) noexcept; | |
372 | ||
373 | friend constexpr month_weekday | |
374 | operator/(const month& __m, const weekday_indexed& __wdi) noexcept; | |
375 | ||
376 | friend constexpr month_weekday | |
377 | operator/(const weekday_indexed& __wdi, const month& __m) noexcept; | |
378 | ||
379 | friend constexpr month_weekday_last | |
380 | operator/(const month& __m, const weekday_last& __wdl) noexcept; | |
381 | ||
382 | friend constexpr month_weekday_last | |
383 | operator/(const weekday_last& __wdl, const month& __m) noexcept; | |
384 | ||
385 | // TODO: Implement operator<<, to_stream, from_stream. | |
386 | }; | |
387 | ||
388 | inline constexpr month January{1}; | |
389 | inline constexpr month February{2}; | |
390 | inline constexpr month March{3}; | |
391 | inline constexpr month April{4}; | |
392 | inline constexpr month May{5}; | |
393 | inline constexpr month June{6}; | |
394 | inline constexpr month July{7}; | |
395 | inline constexpr month August{8}; | |
396 | inline constexpr month September{9}; | |
397 | inline constexpr month October{10}; | |
398 | inline constexpr month November{11}; | |
399 | inline constexpr month December{12}; | |
400 | ||
401 | // YEAR | |
402 | ||
403 | class year | |
404 | { | |
405 | private: | |
406 | short _M_y; | |
407 | ||
408 | public: | |
409 | year() = default; | |
410 | ||
411 | explicit constexpr | |
412 | year(int __y) noexcept | |
413 | : _M_y{static_cast<short>(__y)} | |
414 | { } | |
415 | ||
416 | static constexpr year | |
417 | min() noexcept | |
418 | { return year{-32767}; } | |
419 | ||
420 | static constexpr year | |
421 | max() noexcept | |
422 | { return year{32767}; } | |
423 | ||
424 | constexpr year& | |
425 | operator++() noexcept | |
426 | { | |
427 | ++_M_y; | |
428 | return *this; | |
429 | } | |
430 | ||
431 | constexpr year | |
432 | operator++(int) noexcept | |
433 | { | |
434 | auto __ret = *this; | |
435 | ++(*this); | |
436 | return __ret; | |
437 | } | |
438 | ||
439 | constexpr year& | |
440 | operator--() noexcept | |
441 | { | |
442 | --_M_y; | |
443 | return *this; | |
444 | } | |
445 | ||
446 | constexpr year | |
447 | operator--(int) noexcept | |
448 | { | |
449 | auto __ret = *this; | |
450 | --(*this); | |
451 | return __ret; | |
452 | } | |
453 | ||
454 | constexpr year& | |
455 | operator+=(const years& __y) noexcept | |
456 | { | |
457 | *this = *this + __y; | |
458 | return *this; | |
459 | } | |
460 | ||
461 | constexpr year& | |
462 | operator-=(const years& __y) noexcept | |
463 | { | |
464 | *this = *this - __y; | |
465 | return *this; | |
466 | } | |
467 | ||
468 | constexpr year | |
469 | operator+() const noexcept | |
470 | { return *this; } | |
471 | ||
472 | constexpr year | |
473 | operator-() const noexcept | |
474 | { return year{-_M_y}; } | |
475 | ||
476 | constexpr bool | |
477 | is_leap() const noexcept | |
12679397 CN |
478 | { |
479 | // Testing divisibility by 100 first gives better performance, that is, | |
480 | // return (_M_y % 100 != 0 || _M_y % 400 == 0) && _M_y % 4 == 0; | |
481 | ||
482 | // It gets even faster if _M_y is in [-536870800, 536870999] | |
483 | // (which is the case here) and _M_y % 100 is replaced by | |
484 | // __is_multiple_of_100 below. | |
485 | ||
486 | // References: | |
487 | // [1] https://github.com/cassioneri/calendar | |
488 | // [2] https://accu.org/journals/overload/28/155/overload155.pdf#page=16 | |
489 | ||
4a404f66 JW |
490 | // Furthermore, if y%100 == 0, then y%400==0 is equivalent to y%16==0, |
491 | // so we can simplify it to (!mult_100 && y % 4 == 0) || y % 16 == 0, | |
b92d12d3 CN |
492 | // which is equivalent to (y & (mult_100 ? 15 : 3)) == 0. |
493 | // See https://gcc.gnu.org/pipermail/libstdc++/2021-June/052815.html | |
494 | ||
12679397 CN |
495 | constexpr uint32_t __multiplier = 42949673; |
496 | constexpr uint32_t __bound = 42949669; | |
497 | constexpr uint32_t __max_dividend = 1073741799; | |
498 | constexpr uint32_t __offset = __max_dividend / 2 / 100 * 100; | |
499 | const bool __is_multiple_of_100 | |
500 | = __multiplier * (_M_y + __offset) < __bound; | |
b92d12d3 | 501 | return (_M_y & (__is_multiple_of_100 ? 15 : 3)) == 0; |
12679397 | 502 | } |
03d5044b PP |
503 | |
504 | explicit constexpr | |
505 | operator int() const noexcept | |
506 | { return _M_y; } | |
507 | ||
508 | constexpr bool | |
509 | ok() const noexcept | |
510 | { return min()._M_y <= _M_y && _M_y <= max()._M_y; } | |
511 | ||
512 | friend constexpr bool | |
513 | operator==(const year& __x, const year& __y) noexcept | |
514 | { return int{__x} == int{__y}; } | |
515 | ||
516 | friend constexpr strong_ordering | |
517 | operator<=>(const year& __x, const year& __y) noexcept | |
518 | { return int{__x} <=> int{__y}; } | |
519 | ||
520 | friend constexpr year | |
521 | operator+(const year& __x, const years& __y) noexcept | |
b6b9fd4a | 522 | { return year{int{__x} + static_cast<int>(__y.count())}; } |
03d5044b PP |
523 | |
524 | friend constexpr year | |
525 | operator+(const years& __x, const year& __y) noexcept | |
526 | { return __y + __x; } | |
527 | ||
528 | friend constexpr year | |
529 | operator-(const year& __x, const years& __y) noexcept | |
530 | { return __x + -__y; } | |
531 | ||
532 | friend constexpr years | |
533 | operator-(const year& __x, const year& __y) noexcept | |
534 | { return years{int{__x} - int{__y}}; } | |
535 | ||
536 | friend constexpr year_month | |
537 | operator/(const year& __y, int __m) noexcept; | |
538 | ||
539 | friend constexpr year_month_day | |
540 | operator/(const year& __y, const month_day& __md) noexcept; | |
541 | ||
542 | friend constexpr year_month_day | |
543 | operator/(const month_day& __md, const year& __y) noexcept; | |
544 | ||
545 | friend constexpr year_month_day_last | |
546 | operator/(const year& __y, const month_day_last& __mdl) noexcept; | |
547 | ||
548 | friend constexpr year_month_day_last | |
549 | operator/(const month_day_last& __mdl, const year& __y) noexcept; | |
550 | ||
551 | friend constexpr year_month_weekday | |
552 | operator/(const year& __y, const month_weekday& __mwd) noexcept; | |
553 | ||
554 | friend constexpr year_month_weekday | |
555 | operator/(const month_weekday& __mwd, const year& __y) noexcept; | |
556 | ||
557 | friend constexpr year_month_weekday_last | |
558 | operator/(const year& __y, const month_weekday_last& __mwdl) noexcept; | |
559 | ||
560 | friend constexpr year_month_weekday_last | |
561 | operator/(const month_weekday_last& __mwdl, const year& __y) noexcept; | |
562 | ||
563 | // TODO: Implement operator<<, to_stream, from_stream. | |
564 | }; | |
565 | ||
566 | // WEEKDAY | |
567 | ||
568 | class weekday | |
569 | { | |
570 | private: | |
571 | unsigned char _M_wd; | |
572 | ||
573 | static constexpr weekday | |
574 | _S_from_days(const days& __d) | |
575 | { | |
576 | auto __n = __d.count(); | |
577 | return weekday(__n >= -4 ? (__n + 4) % 7 : (__n + 5) % 7 + 6); | |
578 | } | |
579 | ||
580 | public: | |
581 | weekday() = default; | |
582 | ||
583 | explicit constexpr | |
584 | weekday(unsigned __wd) noexcept | |
585 | : _M_wd(__wd == 7 ? 0 : __wd) // __wd % 7 ? | |
586 | { } | |
587 | ||
588 | constexpr | |
589 | weekday(const sys_days& __dp) noexcept | |
590 | : weekday{_S_from_days(__dp.time_since_epoch())} | |
591 | { } | |
592 | ||
593 | explicit constexpr | |
594 | weekday(const local_days& __dp) noexcept | |
595 | : weekday{sys_days{__dp.time_since_epoch()}} | |
596 | { } | |
597 | ||
598 | constexpr weekday& | |
599 | operator++() noexcept | |
600 | { | |
601 | *this += days{1}; | |
602 | return *this; | |
603 | } | |
604 | ||
605 | constexpr weekday | |
606 | operator++(int) noexcept | |
607 | { | |
608 | auto __ret = *this; | |
609 | ++(*this); | |
610 | return __ret; | |
611 | } | |
612 | ||
613 | constexpr weekday& | |
614 | operator--() noexcept | |
615 | { | |
616 | *this -= days{1}; | |
617 | return *this; | |
618 | } | |
619 | ||
620 | constexpr weekday | |
621 | operator--(int) noexcept | |
622 | { | |
623 | auto __ret = *this; | |
624 | --(*this); | |
625 | return __ret; | |
626 | } | |
627 | ||
628 | constexpr weekday& | |
629 | operator+=(const days& __d) noexcept | |
630 | { | |
631 | *this = *this + __d; | |
632 | return *this; | |
633 | } | |
634 | ||
635 | constexpr weekday& | |
636 | operator-=(const days& __d) noexcept | |
637 | { | |
638 | *this = *this - __d; | |
639 | return *this; | |
640 | } | |
641 | ||
642 | constexpr unsigned | |
643 | c_encoding() const noexcept | |
644 | { return _M_wd; } | |
645 | ||
646 | constexpr unsigned | |
647 | iso_encoding() const noexcept | |
648 | { return _M_wd == 0u ? 7u : _M_wd; } | |
649 | ||
650 | constexpr bool | |
651 | ok() const noexcept | |
652 | { return _M_wd <= 6; } | |
653 | ||
654 | constexpr weekday_indexed | |
655 | operator[](unsigned __index) const noexcept; | |
656 | ||
657 | constexpr weekday_last | |
658 | operator[](last_spec) const noexcept; | |
659 | ||
660 | friend constexpr bool | |
661 | operator==(const weekday& __x, const weekday& __y) noexcept | |
662 | { return __x._M_wd == __y._M_wd; } | |
663 | ||
664 | friend constexpr weekday | |
665 | operator+(const weekday& __x, const days& __y) noexcept | |
666 | { | |
667 | auto __n = static_cast<long long>(__x._M_wd) + __y.count(); | |
668 | return weekday{__detail::__modulo(__n, 7)}; | |
669 | } | |
670 | ||
671 | friend constexpr weekday | |
672 | operator+(const days& __x, const weekday& __y) noexcept | |
673 | { return __y + __x; } | |
674 | ||
675 | friend constexpr weekday | |
676 | operator-(const weekday& __x, const days& __y) noexcept | |
677 | { return __x + -__y; } | |
678 | ||
679 | friend constexpr days | |
680 | operator-(const weekday& __x, const weekday& __y) noexcept | |
681 | { | |
682 | auto __n = static_cast<long long>(__x._M_wd) - __y._M_wd; | |
683 | return days{__detail::__modulo(__n, 7)}; | |
684 | } | |
685 | ||
686 | // TODO: operator<<, from_stream. | |
687 | }; | |
688 | ||
689 | inline constexpr weekday Sunday{0}; | |
690 | inline constexpr weekday Monday{1}; | |
691 | inline constexpr weekday Tuesday{2}; | |
692 | inline constexpr weekday Wednesday{3}; | |
693 | inline constexpr weekday Thursday{4}; | |
694 | inline constexpr weekday Friday{5}; | |
695 | inline constexpr weekday Saturday{6}; | |
696 | ||
697 | // WEEKDAY_INDEXED | |
698 | ||
699 | class weekday_indexed | |
700 | { | |
701 | private: | |
702 | chrono::weekday _M_wd; | |
703 | unsigned char _M_index; | |
704 | ||
705 | public: | |
706 | weekday_indexed() = default; | |
707 | ||
708 | constexpr | |
709 | weekday_indexed(const chrono::weekday& __wd, unsigned __index) noexcept | |
710 | : _M_wd(__wd), _M_index(__index) | |
711 | { } | |
712 | ||
713 | constexpr chrono::weekday | |
714 | weekday() const noexcept | |
715 | { return _M_wd; } | |
716 | ||
717 | constexpr unsigned | |
718 | index() const noexcept | |
719 | { return _M_index; }; | |
720 | ||
721 | constexpr bool | |
722 | ok() const noexcept | |
723 | { return _M_wd.ok() && 1 <= _M_index && _M_index <= 5; } | |
724 | ||
725 | friend constexpr bool | |
726 | operator==(const weekday_indexed& __x, const weekday_indexed& __y) noexcept | |
727 | { return __x.weekday() == __y.weekday() && __x.index() == __y.index(); } | |
728 | ||
729 | friend constexpr month_weekday | |
730 | operator/(const month& __m, const weekday_indexed& __wdi) noexcept; | |
731 | ||
732 | friend constexpr month_weekday | |
733 | operator/(int __m, const weekday_indexed& __wdi) noexcept; | |
734 | ||
735 | friend constexpr month_weekday | |
736 | operator/(const weekday_indexed& __wdi, const month& __m) noexcept; | |
737 | ||
738 | friend constexpr month_weekday | |
739 | operator/(const weekday_indexed& __wdi, int __m) noexcept; | |
740 | ||
741 | friend constexpr year_month_weekday | |
742 | operator/(const year_month& __ym, const weekday_indexed& __wdi) noexcept; | |
743 | ||
744 | // TODO: Implement operator<<. | |
745 | }; | |
746 | ||
747 | constexpr weekday_indexed | |
748 | weekday::operator[](unsigned __index) const noexcept | |
749 | { return {*this, __index}; } | |
750 | ||
751 | // WEEKDAY_LAST | |
752 | ||
753 | class weekday_last | |
754 | { | |
755 | private: | |
756 | chrono::weekday _M_wd; | |
757 | ||
758 | public: | |
759 | explicit constexpr | |
760 | weekday_last(const chrono::weekday& __wd) noexcept | |
761 | : _M_wd{__wd} | |
762 | { } | |
763 | ||
764 | constexpr chrono::weekday | |
765 | weekday() const noexcept | |
766 | { return _M_wd; } | |
767 | ||
768 | constexpr bool | |
769 | ok() const noexcept | |
770 | { return _M_wd.ok(); } | |
771 | ||
772 | friend constexpr bool | |
773 | operator==(const weekday_last& __x, const weekday_last& __y) noexcept | |
774 | { return __x.weekday() == __y.weekday(); } | |
775 | ||
776 | friend constexpr month_weekday_last | |
777 | operator/(int __m, const weekday_last& __wdl) noexcept; | |
778 | ||
779 | friend constexpr month_weekday_last | |
780 | operator/(const weekday_last& __wdl, int __m) noexcept; | |
781 | ||
782 | friend constexpr year_month_weekday_last | |
783 | operator/(const year_month& __ym, const weekday_last& __wdl) noexcept; | |
784 | ||
785 | // TODO: Implement operator<<. | |
786 | }; | |
787 | ||
788 | constexpr weekday_last | |
789 | weekday::operator[](last_spec) const noexcept | |
790 | { return weekday_last{*this}; } | |
791 | ||
792 | // MONTH_DAY | |
793 | ||
794 | class month_day | |
795 | { | |
796 | private: | |
797 | chrono::month _M_m; | |
798 | chrono::day _M_d; | |
799 | ||
800 | public: | |
801 | month_day() = default; | |
802 | ||
803 | constexpr | |
804 | month_day(const chrono::month& __m, const chrono::day& __d) noexcept | |
805 | : _M_m{__m}, _M_d{__d} | |
806 | { } | |
807 | ||
808 | constexpr chrono::month | |
809 | month() const noexcept | |
810 | { return _M_m; } | |
811 | ||
812 | constexpr chrono::day | |
813 | day() const noexcept | |
814 | { return _M_d; } | |
815 | ||
816 | constexpr bool | |
817 | ok() const noexcept | |
818 | { | |
819 | return _M_m.ok() | |
820 | && 1u <= unsigned(_M_d) | |
821 | && unsigned(_M_d) <= __detail::__days_per_month[unsigned(_M_m) - 1]; | |
822 | } | |
823 | ||
824 | friend constexpr bool | |
825 | operator==(const month_day& __x, const month_day& __y) noexcept | |
826 | { return __x.month() == __y.month() && __x.day() == __y.day(); } | |
827 | ||
828 | friend constexpr strong_ordering | |
829 | operator<=>(const month_day& __x, const month_day& __y) noexcept | |
830 | = default; | |
831 | ||
832 | friend constexpr month_day | |
833 | operator/(const chrono::month& __m, const chrono::day& __d) noexcept | |
834 | { return {__m, __d}; } | |
835 | ||
836 | friend constexpr month_day | |
837 | operator/(const chrono::month& __m, int __d) noexcept | |
838 | { return {__m, chrono::day(unsigned(__d))}; } | |
839 | ||
840 | friend constexpr month_day | |
841 | operator/(int __m, const chrono::day& __d) noexcept | |
842 | { return {chrono::month(unsigned(__m)), __d}; } | |
843 | ||
844 | friend constexpr month_day | |
845 | operator/(const chrono::day& __d, const chrono::month& __m) noexcept | |
846 | { return {__m, __d}; } | |
847 | ||
848 | friend constexpr month_day | |
849 | operator/(const chrono::day& __d, int __m) noexcept | |
850 | { return {chrono::month(unsigned(__m)), __d}; } | |
851 | ||
852 | friend constexpr year_month_day | |
853 | operator/(int __y, const month_day& __md) noexcept; | |
854 | ||
855 | friend constexpr year_month_day | |
856 | operator/(const month_day& __md, int __y) noexcept; | |
857 | ||
858 | // TODO: Implement operator<<, from_stream. | |
859 | }; | |
860 | ||
861 | // MONTH_DAY_LAST | |
862 | ||
863 | class month_day_last | |
864 | { | |
865 | private: | |
866 | chrono::month _M_m; | |
867 | ||
868 | public: | |
869 | explicit constexpr | |
870 | month_day_last(const chrono::month& __m) noexcept | |
871 | : _M_m{__m} | |
872 | { } | |
873 | ||
874 | constexpr chrono::month | |
875 | month() const noexcept | |
876 | { return _M_m; } | |
877 | ||
878 | constexpr bool | |
879 | ok() const noexcept | |
880 | { return _M_m.ok(); } | |
881 | ||
882 | friend constexpr bool | |
883 | operator==(const month_day_last& __x, const month_day_last& __y) noexcept | |
884 | { return __x.month() == __y.month(); } | |
885 | ||
886 | friend constexpr strong_ordering | |
887 | operator<=>(const month_day_last& __x, const month_day_last& __y) noexcept | |
888 | = default; | |
889 | ||
890 | friend constexpr month_day_last | |
891 | operator/(const chrono::month& __m, last_spec) noexcept | |
892 | { return month_day_last{__m}; } | |
893 | ||
894 | friend constexpr month_day_last | |
895 | operator/(int __m, last_spec) noexcept | |
896 | { return chrono::month(unsigned(__m)) / last; } | |
897 | ||
898 | friend constexpr month_day_last | |
899 | operator/(last_spec, const chrono::month& __m) noexcept | |
900 | { return __m / last; } | |
901 | ||
902 | friend constexpr month_day_last | |
903 | operator/(last_spec, int __m) noexcept | |
904 | { return __m / last; } | |
905 | ||
906 | friend constexpr year_month_day_last | |
907 | operator/(int __y, const month_day_last& __mdl) noexcept; | |
908 | ||
909 | friend constexpr year_month_day_last | |
910 | operator/(const month_day_last& __mdl, int __y) noexcept; | |
911 | ||
912 | // TODO: Implement operator<<. | |
913 | }; | |
914 | ||
915 | // MONTH_WEEKDAY | |
916 | ||
917 | class month_weekday | |
918 | { | |
919 | private: | |
920 | chrono::month _M_m; | |
921 | chrono::weekday_indexed _M_wdi; | |
922 | ||
923 | public: | |
924 | constexpr | |
925 | month_weekday(const chrono::month& __m, | |
926 | const chrono::weekday_indexed& __wdi) noexcept | |
927 | : _M_m{__m}, _M_wdi{__wdi} | |
928 | { } | |
929 | ||
930 | constexpr chrono::month | |
931 | month() const noexcept | |
932 | { return _M_m; } | |
933 | ||
934 | constexpr chrono::weekday_indexed | |
935 | weekday_indexed() const noexcept | |
936 | { return _M_wdi; } | |
937 | ||
938 | constexpr bool | |
939 | ok() const noexcept | |
940 | { return _M_m.ok() && _M_wdi.ok(); } | |
941 | ||
942 | friend constexpr bool | |
943 | operator==(const month_weekday& __x, const month_weekday& __y) noexcept | |
944 | { | |
945 | return __x.month() == __y.month() | |
946 | && __x.weekday_indexed() == __y.weekday_indexed(); | |
947 | } | |
948 | ||
949 | friend constexpr month_weekday | |
950 | operator/(const chrono::month& __m, | |
951 | const chrono::weekday_indexed& __wdi) noexcept | |
952 | { return {__m, __wdi}; } | |
953 | ||
954 | friend constexpr month_weekday | |
955 | operator/(int __m, const chrono::weekday_indexed& __wdi) noexcept | |
956 | { return chrono::month(unsigned(__m)) / __wdi; } | |
957 | ||
958 | friend constexpr month_weekday | |
959 | operator/(const chrono::weekday_indexed& __wdi, | |
960 | const chrono::month& __m) noexcept | |
961 | { return __m / __wdi; } | |
962 | ||
963 | friend constexpr month_weekday | |
964 | operator/(const chrono::weekday_indexed& __wdi, int __m) noexcept | |
965 | { return __m / __wdi; } | |
966 | ||
967 | friend constexpr year_month_weekday | |
968 | operator/(int __y, const month_weekday& __mwd) noexcept; | |
969 | ||
970 | friend constexpr year_month_weekday | |
971 | operator/(const month_weekday& __mwd, int __y) noexcept; | |
972 | ||
973 | // TODO: Implement operator<<. | |
974 | }; | |
975 | ||
976 | // MONTH_WEEKDAY_LAST | |
977 | ||
978 | class month_weekday_last | |
979 | { | |
980 | private: | |
981 | chrono::month _M_m; | |
982 | chrono::weekday_last _M_wdl; | |
983 | ||
984 | public: | |
985 | constexpr | |
986 | month_weekday_last(const chrono::month& __m, | |
987 | const chrono::weekday_last& __wdl) noexcept | |
988 | :_M_m{__m}, _M_wdl{__wdl} | |
989 | { } | |
990 | ||
991 | constexpr chrono::month | |
992 | month() const noexcept | |
993 | { return _M_m; } | |
994 | ||
995 | constexpr chrono::weekday_last | |
996 | weekday_last() const noexcept | |
997 | { return _M_wdl; } | |
998 | ||
999 | constexpr bool | |
1000 | ok() const noexcept | |
1001 | { return _M_m.ok() && _M_wdl.ok(); } | |
1002 | ||
1003 | friend constexpr bool | |
1004 | operator==(const month_weekday_last& __x, | |
1005 | const month_weekday_last& __y) noexcept | |
1006 | { | |
1007 | return __x.month() == __y.month() | |
1008 | && __x.weekday_last() == __y.weekday_last(); | |
1009 | } | |
1010 | ||
1011 | friend constexpr month_weekday_last | |
1012 | operator/(const chrono::month& __m, | |
1013 | const chrono::weekday_last& __wdl) noexcept | |
1014 | { return {__m, __wdl}; } | |
1015 | ||
1016 | friend constexpr month_weekday_last | |
1017 | operator/(int __m, const chrono::weekday_last& __wdl) noexcept | |
1018 | { return chrono::month(unsigned(__m)) / __wdl; } | |
1019 | ||
1020 | friend constexpr month_weekday_last | |
1021 | operator/(const chrono::weekday_last& __wdl, | |
1022 | const chrono::month& __m) noexcept | |
1023 | { return __m / __wdl; } | |
1024 | ||
1025 | friend constexpr month_weekday_last | |
1026 | operator/(const chrono::weekday_last& __wdl, int __m) noexcept | |
1027 | { return chrono::month(unsigned(__m)) / __wdl; } | |
1028 | ||
1029 | friend constexpr year_month_weekday_last | |
1030 | operator/(int __y, const month_weekday_last& __mwdl) noexcept; | |
1031 | ||
1032 | friend constexpr year_month_weekday_last | |
1033 | operator/(const month_weekday_last& __mwdl, int __y) noexcept; | |
1034 | ||
1035 | // TODO: Implement operator<<. | |
1036 | }; | |
1037 | ||
1038 | // YEAR_MONTH | |
1039 | ||
7b743c67 PP |
1040 | namespace __detail |
1041 | { | |
1042 | // [time.cal.ym], [time.cal.ymd], etc constrain the 'months'-based | |
1043 | // addition/subtraction operator overloads like so: | |
1044 | // | |
1045 | // Constraints: if the argument supplied by the caller for the months | |
1046 | // parameter is convertible to years, its implicit conversion sequence | |
1047 | // to years is worse than its implicit conversion sequence to months. | |
1048 | // | |
1049 | // We realize this constraint by templatizing the 'months'-based | |
1050 | // overloads (using a dummy defaulted template parameter), so that | |
1051 | // overload resolution doesn't select the 'months'-based overload unless | |
1052 | // the implicit conversion sequence to 'months' is better than that to | |
1053 | // 'years'. | |
1054 | using __months_years_conversion_disambiguator = void; | |
1055 | } | |
1056 | ||
03d5044b PP |
1057 | class year_month |
1058 | { | |
1059 | private: | |
1060 | chrono::year _M_y; | |
1061 | chrono::month _M_m; | |
1062 | ||
1063 | public: | |
1064 | year_month() = default; | |
1065 | ||
1066 | constexpr | |
1067 | year_month(const chrono::year& __y, const chrono::month& __m) noexcept | |
1068 | : _M_y{__y}, _M_m{__m} | |
1069 | { } | |
1070 | ||
1071 | constexpr chrono::year | |
1072 | year() const noexcept | |
1073 | { return _M_y; } | |
1074 | ||
1075 | constexpr chrono::month | |
1076 | month() const noexcept | |
1077 | { return _M_m; } | |
1078 | ||
7b743c67 PP |
1079 | template<typename = __detail::__months_years_conversion_disambiguator> |
1080 | constexpr year_month& | |
1081 | operator+=(const months& __dm) noexcept | |
1082 | { | |
1083 | *this = *this + __dm; | |
1084 | return *this; | |
1085 | } | |
03d5044b | 1086 | |
7b743c67 PP |
1087 | template<typename = __detail::__months_years_conversion_disambiguator> |
1088 | constexpr year_month& | |
1089 | operator-=(const months& __dm) noexcept | |
1090 | { | |
1091 | *this = *this - __dm; | |
1092 | return *this; | |
1093 | } | |
03d5044b PP |
1094 | |
1095 | constexpr year_month& | |
1096 | operator+=(const years& __dy) noexcept | |
1097 | { | |
1098 | *this = *this + __dy; | |
1099 | return *this; | |
1100 | } | |
1101 | ||
1102 | constexpr year_month& | |
1103 | operator-=(const years& __dy) noexcept | |
1104 | { | |
1105 | *this = *this - __dy; | |
1106 | return *this; | |
1107 | } | |
1108 | ||
1109 | constexpr bool | |
1110 | ok() const noexcept | |
1111 | { return _M_y.ok() && _M_m.ok(); } | |
1112 | ||
1113 | friend constexpr bool | |
1114 | operator==(const year_month& __x, const year_month& __y) noexcept | |
1115 | { return __x.year() == __y.year() && __x.month() == __y.month(); } | |
1116 | ||
1117 | friend constexpr strong_ordering | |
1118 | operator<=>(const year_month& __x, const year_month& __y) noexcept | |
1119 | = default; | |
1120 | ||
7b743c67 PP |
1121 | template<typename = __detail::__months_years_conversion_disambiguator> |
1122 | friend constexpr year_month | |
1123 | operator+(const year_month& __ym, const months& __dm) noexcept | |
1124 | { | |
1125 | // TODO: Optimize? | |
1126 | auto __m = __ym.month() + __dm; | |
71e97161 | 1127 | auto __i = int(unsigned(__ym.month())) - 1 + __dm.count(); |
7b743c67 PP |
1128 | auto __y = (__i < 0 |
1129 | ? __ym.year() + years{(__i - 11) / 12} | |
1130 | : __ym.year() + years{__i / 12}); | |
1131 | return __y / __m; | |
1132 | } | |
03d5044b | 1133 | |
7b743c67 PP |
1134 | template<typename = __detail::__months_years_conversion_disambiguator> |
1135 | friend constexpr year_month | |
1136 | operator+(const months& __dm, const year_month& __ym) noexcept | |
1137 | { return __ym + __dm; } | |
03d5044b | 1138 | |
7b743c67 PP |
1139 | template<typename = __detail::__months_years_conversion_disambiguator> |
1140 | friend constexpr year_month | |
1141 | operator-(const year_month& __ym, const months& __dm) noexcept | |
1142 | { return __ym + -__dm; } | |
03d5044b PP |
1143 | |
1144 | friend constexpr months | |
1145 | operator-(const year_month& __x, const year_month& __y) noexcept | |
1146 | { | |
1147 | return (__x.year() - __y.year() | |
1148 | + months{static_cast<int>(unsigned{__x.month()}) | |
1149 | - static_cast<int>(unsigned{__y.month()})}); | |
1150 | } | |
1151 | ||
1152 | friend constexpr year_month | |
1153 | operator+(const year_month& __ym, const years& __dy) noexcept | |
1154 | { return (__ym.year() + __dy) / __ym.month(); } | |
1155 | ||
1156 | friend constexpr year_month | |
1157 | operator+(const years& __dy, const year_month& __ym) noexcept | |
1158 | { return __ym + __dy; } | |
1159 | ||
1160 | friend constexpr year_month | |
1161 | operator-(const year_month& __ym, const years& __dy) noexcept | |
1162 | { return __ym + -__dy; } | |
1163 | ||
1164 | friend constexpr year_month | |
1165 | operator/(const chrono::year& __y, const chrono::month& __m) noexcept | |
1166 | { return {__y, __m}; } | |
1167 | ||
1168 | friend constexpr year_month | |
1169 | operator/(const chrono::year& __y, int __m) noexcept | |
1170 | { return {__y, chrono::month(unsigned(__m))}; } | |
1171 | ||
1172 | friend constexpr year_month_day | |
1173 | operator/(const year_month& __ym, int __d) noexcept; | |
1174 | ||
1175 | friend constexpr year_month_day_last | |
1176 | operator/(const year_month& __ym, last_spec) noexcept; | |
1177 | ||
1178 | // TODO: Implement operator<<, from_stream. | |
1179 | }; | |
1180 | ||
1181 | // YEAR_MONTH_DAY | |
1182 | ||
1183 | class year_month_day | |
1184 | { | |
1185 | private: | |
1186 | chrono::year _M_y; | |
1187 | chrono::month _M_m; | |
1188 | chrono::day _M_d; | |
1189 | ||
1190 | static constexpr year_month_day _S_from_days(const days& __dp) noexcept; | |
1191 | ||
1192 | constexpr days _M_days_since_epoch() const noexcept; | |
1193 | ||
1194 | public: | |
1195 | year_month_day() = default; | |
1196 | ||
1197 | constexpr | |
1198 | year_month_day(const chrono::year& __y, const chrono::month& __m, | |
1199 | const chrono::day& __d) noexcept | |
1200 | : _M_y{__y}, _M_m{__m}, _M_d{__d} | |
1201 | { } | |
1202 | ||
1203 | constexpr | |
1204 | year_month_day(const year_month_day_last& __ymdl) noexcept; | |
1205 | ||
1206 | constexpr | |
1207 | year_month_day(const sys_days& __dp) noexcept | |
1208 | : year_month_day(_S_from_days(__dp.time_since_epoch())) | |
1209 | { } | |
1210 | ||
1211 | explicit constexpr | |
1212 | year_month_day(const local_days& __dp) noexcept | |
1213 | : year_month_day(sys_days{__dp.time_since_epoch()}) | |
1214 | { } | |
1215 | ||
7b743c67 PP |
1216 | template<typename = __detail::__months_years_conversion_disambiguator> |
1217 | constexpr year_month_day& | |
1218 | operator+=(const months& __m) noexcept | |
1219 | { | |
1220 | *this = *this + __m; | |
1221 | return *this; | |
1222 | } | |
03d5044b | 1223 | |
7b743c67 PP |
1224 | template<typename = __detail::__months_years_conversion_disambiguator> |
1225 | constexpr year_month_day& | |
1226 | operator-=(const months& __m) noexcept | |
1227 | { | |
1228 | *this = *this - __m; | |
1229 | return *this; | |
1230 | } | |
03d5044b PP |
1231 | |
1232 | constexpr year_month_day& | |
1233 | operator+=(const years& __y) noexcept | |
1234 | { | |
1235 | *this = *this + __y; | |
1236 | return *this; | |
1237 | } | |
1238 | ||
1239 | constexpr year_month_day& | |
1240 | operator-=(const years& __y) noexcept | |
1241 | { | |
1242 | *this = *this - __y; | |
1243 | return *this; | |
1244 | } | |
1245 | ||
1246 | constexpr chrono::year | |
1247 | year() const noexcept | |
1248 | { return _M_y; } | |
1249 | ||
1250 | constexpr chrono::month | |
1251 | month() const noexcept | |
1252 | { return _M_m; } | |
1253 | ||
1254 | constexpr chrono::day | |
1255 | day() const noexcept | |
1256 | { return _M_d; } | |
1257 | ||
1258 | constexpr | |
1259 | operator sys_days() const noexcept | |
1260 | { return sys_days{_M_days_since_epoch()}; } | |
1261 | ||
1262 | explicit constexpr | |
1263 | operator local_days() const noexcept | |
1264 | { return local_days{sys_days{*this}.time_since_epoch()}; } | |
1265 | ||
1266 | constexpr bool ok() const noexcept; | |
1267 | ||
1268 | friend constexpr bool | |
1269 | operator==(const year_month_day& __x, const year_month_day& __y) noexcept | |
1270 | { | |
1271 | return __x.year() == __y.year() | |
1272 | && __x.month() == __y.month() | |
1273 | && __x.day() == __y.day(); | |
1274 | } | |
1275 | ||
1276 | friend constexpr strong_ordering | |
1277 | operator<=>(const year_month_day& __x, const year_month_day& __y) noexcept | |
1278 | = default; | |
1279 | ||
7b743c67 PP |
1280 | template<typename = __detail::__months_years_conversion_disambiguator> |
1281 | friend constexpr year_month_day | |
1282 | operator+(const year_month_day& __ymd, const months& __dm) noexcept | |
1283 | { return (__ymd.year() / __ymd.month() + __dm) / __ymd.day(); } | |
03d5044b | 1284 | |
7b743c67 PP |
1285 | template<typename = __detail::__months_years_conversion_disambiguator> |
1286 | friend constexpr year_month_day | |
1287 | operator+(const months& __dm, const year_month_day& __ymd) noexcept | |
1288 | { return __ymd + __dm; } | |
03d5044b PP |
1289 | |
1290 | friend constexpr year_month_day | |
1291 | operator+(const year_month_day& __ymd, const years& __dy) noexcept | |
1292 | { return (__ymd.year() + __dy) / __ymd.month() / __ymd.day(); } | |
1293 | ||
1294 | friend constexpr year_month_day | |
1295 | operator+(const years& __dy, const year_month_day& __ymd) noexcept | |
1296 | { return __ymd + __dy; } | |
1297 | ||
7b743c67 PP |
1298 | template<typename = __detail::__months_years_conversion_disambiguator> |
1299 | friend constexpr year_month_day | |
1300 | operator-(const year_month_day& __ymd, const months& __dm) noexcept | |
1301 | { return __ymd + -__dm; } | |
03d5044b PP |
1302 | |
1303 | friend constexpr year_month_day | |
1304 | operator-(const year_month_day& __ymd, const years& __dy) noexcept | |
1305 | { return __ymd + -__dy; } | |
1306 | ||
1307 | friend constexpr year_month_day | |
1308 | operator/(const year_month& __ym, const chrono::day& __d) noexcept | |
1309 | { return {__ym.year(), __ym.month(), __d}; } | |
1310 | ||
1311 | friend constexpr year_month_day | |
1312 | operator/(const year_month& __ym, int __d) noexcept | |
1313 | { return __ym / chrono::day{unsigned(__d)}; } | |
1314 | ||
1315 | friend constexpr year_month_day | |
1316 | operator/(const chrono::year& __y, const month_day& __md) noexcept | |
1317 | { return __y / __md.month() / __md.day(); } | |
1318 | ||
1319 | friend constexpr year_month_day | |
1320 | operator/(int __y, const month_day& __md) noexcept | |
1321 | { return chrono::year{__y} / __md; } | |
1322 | ||
1323 | friend constexpr year_month_day | |
1324 | operator/(const month_day& __md, const chrono::year& __y) noexcept | |
1325 | { return __y / __md; } | |
1326 | ||
1327 | friend constexpr year_month_day | |
1328 | operator/(const month_day& __md, int __y) noexcept | |
1329 | { return chrono::year(__y) / __md; } | |
1330 | ||
1331 | // TODO: Implement operator<<, from_stream. | |
1332 | }; | |
1333 | ||
3dfd5493 CN |
1334 | // Construct from days since 1970/01/01. |
1335 | // Proposition 6.3 of Neri and Schneider, | |
1336 | // "Euclidean Affine Functions and Applications to Calendar Algorithms". | |
1337 | // https://arxiv.org/abs/2102.06959 | |
03d5044b PP |
1338 | constexpr year_month_day |
1339 | year_month_day::_S_from_days(const days& __dp) noexcept | |
1340 | { | |
3dfd5493 CN |
1341 | constexpr auto __z2 = static_cast<uint32_t>(-1468000); |
1342 | constexpr auto __r2_e3 = static_cast<uint32_t>(536895458); | |
1343 | ||
a47cec4c | 1344 | const auto __r0 = static_cast<uint32_t>(__dp.count()) + __r2_e3; |
3dfd5493 CN |
1345 | |
1346 | const auto __n1 = 4 * __r0 + 3; | |
1347 | const auto __q1 = __n1 / 146097; | |
1348 | const auto __r1 = __n1 % 146097 / 4; | |
1349 | ||
1350 | constexpr auto __p32 = static_cast<uint64_t>(1) << 32; | |
1351 | const auto __n2 = 4 * __r1 + 3; | |
1352 | const auto __u2 = static_cast<uint64_t>(2939745) * __n2; | |
1353 | const auto __q2 = static_cast<uint32_t>(__u2 / __p32); | |
1354 | const auto __r2 = static_cast<uint32_t>(__u2 % __p32) / 2939745 / 4; | |
1355 | ||
1356 | constexpr auto __p16 = static_cast<uint32_t>(1) << 16; | |
1357 | const auto __n3 = 2141 * __r2 + 197913; | |
1358 | const auto __q3 = __n3 / __p16; | |
1359 | const auto __r3 = __n3 % __p16 / 2141; | |
1360 | ||
1361 | const auto __y0 = 100 * __q1 + __q2; | |
1362 | const auto __m0 = __q3; | |
1363 | const auto __d0 = __r3; | |
1364 | ||
1365 | const auto __j = __r2 >= 306; | |
1366 | const auto __y1 = __y0 + __j; | |
1367 | const auto __m1 = __j ? __m0 - 12 : __m0; | |
1368 | const auto __d1 = __d0 + 1; | |
1369 | ||
75c74a83 JW |
1370 | return year_month_day{chrono::year{static_cast<int>(__y1 + __z2)}, |
1371 | chrono::month{__m1}, chrono::day{__d1}}; | |
03d5044b PP |
1372 | } |
1373 | ||
97d6161f CN |
1374 | // Days since 1970/01/01. |
1375 | // Proposition 6.2 of Neri and Schneider, | |
1376 | // "Euclidean Affine Functions and Applications to Calendar Algorithms". | |
1377 | // https://arxiv.org/abs/2102.06959 | |
03d5044b PP |
1378 | constexpr days |
1379 | year_month_day::_M_days_since_epoch() const noexcept | |
1380 | { | |
97d6161f CN |
1381 | auto constexpr __z2 = static_cast<uint32_t>(-1468000); |
1382 | auto constexpr __r2_e3 = static_cast<uint32_t>(536895458); | |
1383 | ||
1384 | const auto __y1 = static_cast<uint32_t>(static_cast<int>(_M_y)) - __z2; | |
699672d4 JW |
1385 | const auto __m1 = static_cast<uint32_t>(static_cast<unsigned>(_M_m)); |
1386 | const auto __d1 = static_cast<uint32_t>(static_cast<unsigned>(_M_d)); | |
97d6161f CN |
1387 | |
1388 | const auto __j = static_cast<uint32_t>(__m1 < 3); | |
1389 | const auto __y0 = __y1 - __j; | |
1390 | const auto __m0 = __j ? __m1 + 12 : __m1; | |
1391 | const auto __d0 = __d1 - 1; | |
1392 | ||
1393 | const auto __q1 = __y0 / 100; | |
1394 | const auto __yc = 1461 * __y0 / 4 - __q1 + __q1 / 4; | |
1395 | const auto __mc = (979 *__m0 - 2919) / 32; | |
1396 | const auto __dc = __d0; | |
1397 | ||
1398 | return days{static_cast<int32_t>(__yc + __mc + __dc - __r2_e3)}; | |
03d5044b PP |
1399 | } |
1400 | ||
1401 | // YEAR_MONTH_DAY_LAST | |
1402 | ||
1403 | class year_month_day_last | |
1404 | { | |
1405 | private: | |
1406 | chrono::year _M_y; | |
1407 | chrono::month_day_last _M_mdl; | |
1408 | ||
1409 | public: | |
1410 | constexpr | |
1411 | year_month_day_last(const chrono::year& __y, | |
1412 | const chrono::month_day_last& __mdl) noexcept | |
1413 | : _M_y{__y}, _M_mdl{__mdl} | |
1414 | { } | |
1415 | ||
7b743c67 PP |
1416 | template<typename = __detail::__months_years_conversion_disambiguator> |
1417 | constexpr year_month_day_last& | |
1418 | operator+=(const months& __m) noexcept | |
1419 | { | |
1420 | *this = *this + __m; | |
1421 | return *this; | |
1422 | } | |
03d5044b | 1423 | |
7b743c67 PP |
1424 | template<typename = __detail::__months_years_conversion_disambiguator> |
1425 | constexpr year_month_day_last& | |
1426 | operator-=(const months& __m) noexcept | |
1427 | { | |
1428 | *this = *this - __m; | |
1429 | return *this; | |
1430 | } | |
03d5044b PP |
1431 | |
1432 | constexpr year_month_day_last& | |
1433 | operator+=(const years& __y) noexcept | |
1434 | { | |
1435 | *this = *this + __y; | |
1436 | return *this; | |
1437 | } | |
1438 | ||
1439 | constexpr year_month_day_last& | |
1440 | operator-=(const years& __y) noexcept | |
1441 | { | |
1442 | *this = *this - __y; | |
1443 | return *this; | |
1444 | } | |
1445 | ||
1446 | constexpr chrono::year | |
1447 | year() const noexcept | |
1448 | { return _M_y; } | |
1449 | ||
1450 | constexpr chrono::month | |
1451 | month() const noexcept | |
1452 | { return _M_mdl.month(); } | |
1453 | ||
1454 | constexpr chrono::month_day_last | |
1455 | month_day_last() const noexcept | |
1456 | { return _M_mdl; } | |
1457 | ||
1458 | // Return A day representing the last day of this year, month pair. | |
1459 | constexpr chrono::day | |
1460 | day() const noexcept | |
1461 | { | |
8265ab07 CN |
1462 | const auto __m = static_cast<unsigned>(month()); |
1463 | ||
1464 | // Excluding February, the last day of month __m is either 30 or 31 or, | |
1465 | // in another words, it is 30 + b = 30 | b, where b is in {0, 1}. | |
1466 | ||
1467 | // If __m in {1, 3, 4, 5, 6, 7}, then b is 1 if, and only if __m is odd. | |
1468 | // Hence, b = __m & 1 = (__m ^ 0) & 1. | |
1469 | ||
1470 | // If __m in {8, 9, 10, 11, 12}, then b is 1 if, and only if __m is even. | |
1471 | // Hence, b = (__m ^ 1) & 1. | |
1472 | ||
1473 | // Therefore, b = (__m ^ c) & 1, where c = 0, if __m < 8, or c = 1 if | |
1474 | // __m >= 8, that is, c = __m >> 3. | |
1475 | ||
1476 | // The above mathematically justifies this implementation whose | |
1477 | // performance does not depend on look-up tables being on the L1 cache. | |
1478 | return chrono::day{__m != 2 ? ((__m ^ (__m >> 3)) & 1) | 30 | |
1479 | : _M_y.is_leap() ? 29 : 28}; | |
03d5044b PP |
1480 | } |
1481 | ||
1482 | constexpr | |
1483 | operator sys_days() const noexcept | |
1484 | { return sys_days{year() / month() / day()}; } | |
1485 | ||
1486 | explicit constexpr | |
1487 | operator local_days() const noexcept | |
1488 | { return local_days{sys_days{*this}.time_since_epoch()}; } | |
1489 | ||
1490 | constexpr bool | |
1491 | ok() const noexcept | |
1492 | { return _M_y.ok() && _M_mdl.ok(); } | |
1493 | ||
1494 | friend constexpr bool | |
1495 | operator==(const year_month_day_last& __x, | |
1496 | const year_month_day_last& __y) noexcept | |
1497 | { | |
1498 | return __x.year() == __y.year() | |
1499 | && __x.month_day_last() == __y.month_day_last(); | |
1500 | } | |
1501 | ||
1502 | friend constexpr strong_ordering | |
1503 | operator<=>(const year_month_day_last& __x, | |
1504 | const year_month_day_last& __y) noexcept | |
1505 | = default; | |
1506 | ||
7b743c67 PP |
1507 | template<typename = __detail::__months_years_conversion_disambiguator> |
1508 | friend constexpr year_month_day_last | |
1509 | operator+(const year_month_day_last& __ymdl, | |
1510 | const months& __dm) noexcept | |
1511 | { return (__ymdl.year() / __ymdl.month() + __dm) / last; } | |
03d5044b | 1512 | |
7b743c67 PP |
1513 | template<typename = __detail::__months_years_conversion_disambiguator> |
1514 | friend constexpr year_month_day_last | |
1515 | operator+(const months& __dm, | |
1516 | const year_month_day_last& __ymdl) noexcept | |
1517 | { return __ymdl + __dm; } | |
03d5044b | 1518 | |
7b743c67 PP |
1519 | template<typename = __detail::__months_years_conversion_disambiguator> |
1520 | friend constexpr year_month_day_last | |
1521 | operator-(const year_month_day_last& __ymdl, | |
1522 | const months& __dm) noexcept | |
1523 | { return __ymdl + -__dm; } | |
03d5044b PP |
1524 | |
1525 | friend constexpr year_month_day_last | |
1526 | operator+(const year_month_day_last& __ymdl, | |
1527 | const years& __dy) noexcept | |
1528 | { return {__ymdl.year() + __dy, __ymdl.month_day_last()}; } | |
1529 | ||
1530 | friend constexpr year_month_day_last | |
1531 | operator+(const years& __dy, | |
1532 | const year_month_day_last& __ymdl) noexcept | |
1533 | { return __ymdl + __dy; } | |
1534 | ||
1535 | friend constexpr year_month_day_last | |
1536 | operator-(const year_month_day_last& __ymdl, | |
1537 | const years& __dy) noexcept | |
1538 | { return __ymdl + -__dy; } | |
1539 | ||
1540 | friend constexpr year_month_day_last | |
1541 | operator/(const year_month& __ym, last_spec) noexcept | |
1542 | { return {__ym.year(), chrono::month_day_last{__ym.month()}}; } | |
1543 | ||
1544 | friend constexpr year_month_day_last | |
1545 | operator/(const chrono::year& __y, | |
1546 | const chrono::month_day_last& __mdl) noexcept | |
1547 | { return {__y, __mdl}; } | |
1548 | ||
1549 | friend constexpr year_month_day_last | |
1550 | operator/(int __y, const chrono::month_day_last& __mdl) noexcept | |
1551 | { return chrono::year(__y) / __mdl; } | |
1552 | ||
1553 | friend constexpr year_month_day_last | |
1554 | operator/(const chrono::month_day_last& __mdl, | |
1555 | const chrono::year& __y) noexcept | |
1556 | { return __y / __mdl; } | |
1557 | ||
1558 | friend constexpr year_month_day_last | |
1559 | operator/(const chrono::month_day_last& __mdl, int __y) noexcept | |
1560 | { return chrono::year(__y) / __mdl; } | |
1561 | ||
1562 | // TODO: Implement operator<<. | |
1563 | }; | |
1564 | ||
1565 | // year_month_day ctor from year_month_day_last | |
1566 | constexpr | |
1567 | year_month_day::year_month_day(const year_month_day_last& __ymdl) noexcept | |
1568 | : _M_y{__ymdl.year()}, _M_m{__ymdl.month()}, _M_d{__ymdl.day()} | |
1569 | { } | |
1570 | ||
1571 | constexpr bool | |
1572 | year_month_day::ok() const noexcept | |
1573 | { | |
1574 | if (!_M_y.ok() || !_M_m.ok()) | |
1575 | return false; | |
1576 | return chrono::day{1} <= _M_d && _M_d <= (_M_y / _M_m / last).day(); | |
1577 | } | |
1578 | ||
1579 | // YEAR_MONTH_WEEKDAY | |
1580 | ||
1581 | class year_month_weekday | |
1582 | { | |
1583 | private: | |
1584 | chrono::year _M_y; | |
1585 | chrono::month _M_m; | |
1586 | chrono::weekday_indexed _M_wdi; | |
1587 | ||
1588 | static constexpr year_month_weekday | |
1589 | _S_from_sys_days(const sys_days& __dp) | |
1590 | { | |
1591 | year_month_day __ymd{__dp}; | |
1592 | chrono::weekday __wd{__dp}; | |
1593 | auto __index = __wd[(unsigned{__ymd.day()} - 1) / 7 + 1]; | |
1594 | return {__ymd.year(), __ymd.month(), __index}; | |
1595 | } | |
1596 | ||
1597 | public: | |
1598 | year_month_weekday() = default; | |
1599 | ||
1600 | constexpr | |
1601 | year_month_weekday(const chrono::year& __y, const chrono::month& __m, | |
1602 | const chrono::weekday_indexed& __wdi) noexcept | |
1603 | : _M_y{__y}, _M_m{__m}, _M_wdi{__wdi} | |
1604 | { } | |
1605 | ||
1606 | constexpr | |
1607 | year_month_weekday(const sys_days& __dp) noexcept | |
1608 | : year_month_weekday{_S_from_sys_days(__dp)} | |
1609 | { } | |
1610 | ||
1611 | explicit constexpr | |
1612 | year_month_weekday(const local_days& __dp) noexcept | |
1613 | : year_month_weekday{sys_days{__dp.time_since_epoch()}} | |
1614 | { } | |
1615 | ||
7b743c67 PP |
1616 | template<typename = __detail::__months_years_conversion_disambiguator> |
1617 | constexpr year_month_weekday& | |
1618 | operator+=(const months& __m) noexcept | |
1619 | { | |
1620 | *this = *this + __m; | |
1621 | return *this; | |
1622 | } | |
03d5044b | 1623 | |
7b743c67 PP |
1624 | template<typename = __detail::__months_years_conversion_disambiguator> |
1625 | constexpr year_month_weekday& | |
1626 | operator-=(const months& __m) noexcept | |
1627 | { | |
1628 | *this = *this - __m; | |
1629 | return *this; | |
1630 | } | |
03d5044b PP |
1631 | |
1632 | constexpr year_month_weekday& | |
1633 | operator+=(const years& __y) noexcept | |
1634 | { | |
1635 | *this = *this + __y; | |
1636 | return *this; | |
1637 | } | |
1638 | ||
1639 | constexpr year_month_weekday& | |
1640 | operator-=(const years& __y) noexcept | |
1641 | { | |
1642 | *this = *this - __y; | |
1643 | return *this; | |
1644 | } | |
1645 | ||
1646 | constexpr chrono::year | |
1647 | year() const noexcept | |
1648 | { return _M_y; } | |
1649 | ||
1650 | constexpr chrono::month | |
1651 | month() const noexcept | |
1652 | { return _M_m; } | |
1653 | ||
1654 | constexpr chrono::weekday | |
1655 | weekday() const noexcept | |
1656 | { return _M_wdi.weekday(); } | |
1657 | ||
1658 | constexpr unsigned | |
1659 | index() const noexcept | |
1660 | { return _M_wdi.index(); } | |
1661 | ||
1662 | constexpr chrono::weekday_indexed | |
1663 | weekday_indexed() const noexcept | |
1664 | { return _M_wdi; } | |
1665 | ||
1666 | constexpr | |
1667 | operator sys_days() const noexcept | |
1668 | { | |
1669 | auto __d = sys_days{year() / month() / 1}; | |
8572edc8 PP |
1670 | return __d + (weekday() - chrono::weekday(__d) |
1671 | + days{(static_cast<int>(index())-1)*7}); | |
03d5044b PP |
1672 | } |
1673 | ||
1674 | explicit constexpr | |
1675 | operator local_days() const noexcept | |
1676 | { return local_days{sys_days{*this}.time_since_epoch()}; } | |
1677 | ||
1678 | constexpr bool | |
1679 | ok() const noexcept | |
1680 | { | |
1681 | if (!_M_y.ok() || !_M_m.ok() || !_M_wdi.ok()) | |
1682 | return false; | |
1683 | if (_M_wdi.index() <= 4) | |
1684 | return true; | |
1685 | days __d = (_M_wdi.weekday() | |
1686 | - chrono::weekday{sys_days{_M_y / _M_m / 1}} | |
1687 | + days((_M_wdi.index()-1)*7 + 1)); | |
1007170d | 1688 | __glibcxx_assert(__d.count() >= 1); |
03d5044b PP |
1689 | return __d.count() <= unsigned{(_M_y / _M_m / last).day()}; |
1690 | } | |
1691 | ||
1692 | friend constexpr bool | |
1693 | operator==(const year_month_weekday& __x, | |
1694 | const year_month_weekday& __y) noexcept | |
1695 | { | |
1696 | return __x.year() == __y.year() | |
1697 | && __x.month() == __y.month() | |
0c5df67f | 1698 | && __x.weekday_indexed() == __y.weekday_indexed(); |
03d5044b PP |
1699 | } |
1700 | ||
7b743c67 PP |
1701 | template<typename = __detail::__months_years_conversion_disambiguator> |
1702 | friend constexpr year_month_weekday | |
1703 | operator+(const year_month_weekday& __ymwd, const months& __dm) noexcept | |
1704 | { | |
1705 | return ((__ymwd.year() / __ymwd.month() + __dm) | |
1706 | / __ymwd.weekday_indexed()); | |
1707 | } | |
03d5044b | 1708 | |
7b743c67 PP |
1709 | template<typename = __detail::__months_years_conversion_disambiguator> |
1710 | friend constexpr year_month_weekday | |
1711 | operator+(const months& __dm, const year_month_weekday& __ymwd) noexcept | |
1712 | { return __ymwd + __dm; } | |
03d5044b PP |
1713 | |
1714 | friend constexpr year_month_weekday | |
1715 | operator+(const year_month_weekday& __ymwd, const years& __dy) noexcept | |
1716 | { return {__ymwd.year() + __dy, __ymwd.month(), __ymwd.weekday_indexed()}; } | |
1717 | ||
1718 | friend constexpr year_month_weekday | |
1719 | operator+(const years& __dy, const year_month_weekday& __ymwd) noexcept | |
1720 | { return __ymwd + __dy; } | |
1721 | ||
7b743c67 PP |
1722 | template<typename = __detail::__months_years_conversion_disambiguator> |
1723 | friend constexpr year_month_weekday | |
1724 | operator-(const year_month_weekday& __ymwd, const months& __dm) noexcept | |
1725 | { return __ymwd + -__dm; } | |
03d5044b PP |
1726 | |
1727 | friend constexpr year_month_weekday | |
1728 | operator-(const year_month_weekday& __ymwd, const years& __dy) noexcept | |
1729 | { return __ymwd + -__dy; } | |
1730 | ||
1731 | friend constexpr year_month_weekday | |
1732 | operator/(const year_month& __ym, | |
1733 | const chrono::weekday_indexed& __wdi) noexcept | |
1734 | { return {__ym.year(), __ym.month(), __wdi}; } | |
1735 | ||
1736 | friend constexpr year_month_weekday | |
1737 | operator/(const chrono::year& __y, const month_weekday& __mwd) noexcept | |
1738 | { return {__y, __mwd.month(), __mwd.weekday_indexed()}; } | |
1739 | ||
1740 | friend constexpr year_month_weekday | |
1741 | operator/(int __y, const month_weekday& __mwd) noexcept | |
1742 | { return chrono::year(__y) / __mwd; } | |
1743 | ||
1744 | friend constexpr year_month_weekday | |
1745 | operator/(const month_weekday& __mwd, const chrono::year& __y) noexcept | |
1746 | { return __y / __mwd; } | |
1747 | ||
1748 | friend constexpr year_month_weekday | |
1749 | operator/(const month_weekday& __mwd, int __y) noexcept | |
1750 | { return chrono::year(__y) / __mwd; } | |
1751 | ||
1752 | // TODO: Implement operator<<. | |
1753 | }; | |
1754 | ||
1755 | // YEAR_MONTH_WEEKDAY_LAST | |
1756 | ||
1757 | class year_month_weekday_last | |
1758 | { | |
1759 | private: | |
1760 | chrono::year _M_y; | |
1761 | chrono::month _M_m; | |
1762 | chrono::weekday_last _M_wdl; | |
1763 | ||
1764 | public: | |
1765 | constexpr | |
1766 | year_month_weekday_last(const chrono::year& __y, const chrono::month& __m, | |
1767 | const chrono::weekday_last& __wdl) noexcept | |
1768 | : _M_y{__y}, _M_m{__m}, _M_wdl{__wdl} | |
1769 | { } | |
1770 | ||
7b743c67 PP |
1771 | template<typename = __detail::__months_years_conversion_disambiguator> |
1772 | constexpr year_month_weekday_last& | |
1773 | operator+=(const months& __m) noexcept | |
1774 | { | |
1775 | *this = *this + __m; | |
1776 | return *this; | |
1777 | } | |
03d5044b | 1778 | |
7b743c67 PP |
1779 | template<typename = __detail::__months_years_conversion_disambiguator> |
1780 | constexpr year_month_weekday_last& | |
1781 | operator-=(const months& __m) noexcept | |
1782 | { | |
1783 | *this = *this - __m; | |
1784 | return *this; | |
1785 | } | |
03d5044b PP |
1786 | |
1787 | constexpr year_month_weekday_last& | |
1788 | operator+=(const years& __y) noexcept | |
1789 | { | |
1790 | *this = *this + __y; | |
1791 | return *this; | |
1792 | } | |
1793 | ||
1794 | constexpr year_month_weekday_last& | |
1795 | operator-=(const years& __y) noexcept | |
1796 | { | |
1797 | *this = *this - __y; | |
1798 | return *this; | |
1799 | } | |
1800 | ||
1801 | constexpr chrono::year | |
1802 | year() const noexcept | |
1803 | { return _M_y; } | |
1804 | ||
1805 | constexpr chrono::month | |
1806 | month() const noexcept | |
1807 | { return _M_m; } | |
1808 | ||
1809 | constexpr chrono::weekday | |
1810 | weekday() const noexcept | |
1811 | { return _M_wdl.weekday(); } | |
1812 | ||
1813 | constexpr chrono::weekday_last | |
1814 | weekday_last() const noexcept | |
1815 | { return _M_wdl; } | |
1816 | ||
1817 | constexpr | |
1818 | operator sys_days() const noexcept | |
1819 | { | |
1820 | const auto __d = sys_days{_M_y / _M_m / last}; | |
1821 | return sys_days{(__d - (chrono::weekday{__d} | |
1822 | - _M_wdl.weekday())).time_since_epoch()}; | |
1823 | } | |
1824 | ||
1825 | explicit constexpr | |
1826 | operator local_days() const noexcept | |
1827 | { return local_days{sys_days{*this}.time_since_epoch()}; } | |
1828 | ||
1829 | constexpr bool | |
1830 | ok() const noexcept | |
1831 | { return _M_y.ok() && _M_m.ok() && _M_wdl.ok(); } | |
1832 | ||
1833 | friend constexpr bool | |
1834 | operator==(const year_month_weekday_last& __x, | |
1835 | const year_month_weekday_last& __y) noexcept | |
1836 | { | |
1837 | return __x.year() == __y.year() | |
1838 | && __x.month() == __y.month() | |
1839 | && __x.weekday_last() == __y.weekday_last(); | |
1840 | } | |
1841 | ||
7b743c67 PP |
1842 | template<typename = __detail::__months_years_conversion_disambiguator> |
1843 | friend constexpr year_month_weekday_last | |
1844 | operator+(const year_month_weekday_last& __ymwdl, | |
1845 | const months& __dm) noexcept | |
1846 | { | |
1847 | return ((__ymwdl.year() / __ymwdl.month() + __dm) | |
1848 | / __ymwdl.weekday_last()); | |
1849 | } | |
03d5044b | 1850 | |
7b743c67 PP |
1851 | template<typename = __detail::__months_years_conversion_disambiguator> |
1852 | friend constexpr year_month_weekday_last | |
1853 | operator+(const months& __dm, | |
1854 | const year_month_weekday_last& __ymwdl) noexcept | |
1855 | { return __ymwdl + __dm; } | |
03d5044b PP |
1856 | |
1857 | friend constexpr year_month_weekday_last | |
1858 | operator+(const year_month_weekday_last& __ymwdl, | |
1859 | const years& __dy) noexcept | |
1860 | { return {__ymwdl.year() + __dy, __ymwdl.month(), __ymwdl.weekday_last()}; } | |
1861 | ||
1862 | friend constexpr year_month_weekday_last | |
1863 | operator+(const years& __dy, | |
1864 | const year_month_weekday_last& __ymwdl) noexcept | |
1865 | { return __ymwdl + __dy; } | |
1866 | ||
7b743c67 PP |
1867 | template<typename = __detail::__months_years_conversion_disambiguator> |
1868 | friend constexpr year_month_weekday_last | |
1869 | operator-(const year_month_weekday_last& __ymwdl, | |
1870 | const months& __dm) noexcept | |
1871 | { return __ymwdl + -__dm; } | |
03d5044b PP |
1872 | |
1873 | friend constexpr year_month_weekday_last | |
1874 | operator-(const year_month_weekday_last& __ymwdl, | |
1875 | const years& __dy) noexcept | |
1876 | { return __ymwdl + -__dy; } | |
1877 | ||
1878 | friend constexpr year_month_weekday_last | |
1879 | operator/(const year_month& __ym, | |
1880 | const chrono::weekday_last& __wdl) noexcept | |
1881 | { return {__ym.year(), __ym.month(), __wdl}; } | |
1882 | ||
1883 | friend constexpr year_month_weekday_last | |
1884 | operator/(const chrono::year& __y, | |
1885 | const chrono::month_weekday_last& __mwdl) noexcept | |
1886 | { return {__y, __mwdl.month(), __mwdl.weekday_last()}; } | |
1887 | ||
1888 | friend constexpr year_month_weekday_last | |
1889 | operator/(int __y, const chrono::month_weekday_last& __mwdl) noexcept | |
1890 | { return chrono::year(__y) / __mwdl; } | |
1891 | ||
1892 | friend constexpr year_month_weekday_last | |
1893 | operator/(const chrono::month_weekday_last& __mwdl, | |
1894 | const chrono::year& __y) noexcept | |
1895 | { return __y / __mwdl; } | |
1896 | ||
1897 | friend constexpr year_month_weekday_last | |
1898 | operator/(const chrono::month_weekday_last& __mwdl, int __y) noexcept | |
1899 | { return chrono::year(__y) / __mwdl; } | |
1900 | ||
1901 | // TODO: Implement operator<<. | |
1902 | }; | |
1903 | ||
1904 | // HH_MM_SS | |
1905 | ||
1906 | namespace __detail | |
1907 | { | |
1908 | consteval long long | |
1909 | __pow10(unsigned __n) | |
1910 | { | |
1911 | long long __r = 1; | |
1912 | while (__n-- > 0) | |
1913 | __r *= 10; | |
1914 | return __r; | |
1915 | } | |
1916 | } | |
1917 | ||
1918 | template<typename _Duration> | |
1919 | class hh_mm_ss | |
1920 | { | |
1921 | private: | |
1922 | static constexpr int | |
1923 | _S_fractional_width() | |
1924 | { | |
1925 | int __multiplicity_2 = 0; | |
1926 | int __multiplicity_5 = 0; | |
1927 | auto __den = _Duration::period::den; | |
1928 | while ((__den % 2) == 0) | |
1929 | { | |
1930 | ++__multiplicity_2; | |
1931 | __den /= 2; | |
1932 | } | |
1933 | while ((__den % 5) == 0) | |
1934 | { | |
1935 | ++__multiplicity_5; | |
1936 | __den /= 5; | |
1937 | } | |
1938 | if (__den != 1) | |
1939 | return 6; | |
1940 | ||
1941 | int __width = (__multiplicity_2 > __multiplicity_5 | |
1942 | ? __multiplicity_2 : __multiplicity_5); | |
1943 | if (__width > 18) | |
1944 | __width = 18; | |
1945 | return __width; | |
1946 | } | |
1947 | ||
1948 | public: | |
1949 | static constexpr unsigned fractional_width = {_S_fractional_width()}; | |
1950 | ||
1951 | using precision | |
1952 | = duration<common_type_t<typename _Duration::rep, | |
1953 | chrono::seconds::rep>, | |
1954 | ratio<1, __detail::__pow10(fractional_width)>>; | |
1955 | ||
1956 | constexpr | |
1957 | hh_mm_ss() noexcept | |
1958 | : hh_mm_ss{_Duration::zero()} | |
1959 | { } | |
1960 | ||
1961 | constexpr explicit | |
1962 | hh_mm_ss(_Duration __d) noexcept | |
1963 | : _M_is_neg (__d < _Duration::zero()), | |
1964 | _M_h (duration_cast<chrono::hours>(abs(__d))), | |
1965 | _M_m (duration_cast<chrono::minutes>(abs(__d) - hours())), | |
1966 | _M_s (duration_cast<chrono::seconds>(abs(__d) - hours() - minutes())) | |
1967 | { | |
1968 | if constexpr (treat_as_floating_point_v<typename precision::rep>) | |
1969 | _M_ss = abs(__d) - hours() - minutes() - seconds(); | |
1970 | else | |
1971 | _M_ss = duration_cast<precision>(abs(__d) - hours() | |
1972 | - minutes() - seconds()); | |
1973 | } | |
1974 | ||
1975 | constexpr bool | |
1976 | is_negative() const noexcept | |
1977 | { return _M_is_neg; } | |
1978 | ||
1979 | constexpr chrono::hours | |
1980 | hours() const noexcept | |
1981 | { return _M_h; } | |
1982 | ||
1983 | constexpr chrono::minutes | |
1984 | minutes() const noexcept | |
1985 | { return _M_m; } | |
1986 | ||
1987 | constexpr chrono::seconds | |
1988 | seconds() const noexcept | |
1989 | { return _M_s; } | |
1990 | ||
1991 | constexpr precision | |
1992 | subseconds() const noexcept | |
1993 | { return _M_ss; } | |
1994 | ||
1995 | constexpr explicit | |
1996 | operator precision() const noexcept | |
1997 | { return to_duration(); } | |
1998 | ||
1999 | constexpr precision | |
2000 | to_duration() const noexcept | |
2001 | { | |
2002 | if (_M_is_neg) | |
2003 | return -(_M_h + _M_m + _M_s + _M_ss); | |
2004 | else | |
2005 | return _M_h + _M_m + _M_s + _M_ss; | |
2006 | } | |
2007 | ||
2008 | // TODO: Implement operator<<. | |
2009 | ||
2010 | private: | |
2011 | bool _M_is_neg; | |
2012 | chrono::hours _M_h; | |
2013 | chrono::minutes _M_m; | |
2014 | chrono::seconds _M_s; | |
2015 | precision _M_ss; | |
2016 | }; | |
f2ce64b5 | 2017 | |
03d5044b PP |
2018 | // 12/24 HOURS FUNCTIONS |
2019 | ||
2020 | constexpr bool | |
2021 | is_am(const hours& __h) noexcept | |
2022 | { return 0h <= __h && __h <= 11h; } | |
2023 | ||
2024 | constexpr bool | |
2025 | is_pm(const hours& __h) noexcept | |
2026 | { return 12h <= __h && __h <= 23h; } | |
2027 | ||
2028 | constexpr hours | |
2029 | make12(const hours& __h) noexcept | |
2030 | { | |
2031 | if (__h == 0h) | |
2032 | return 12h; | |
2033 | else if (__h > 12h) | |
2034 | return __h - 12h; | |
2035 | return __h; | |
2036 | } | |
2037 | ||
2038 | constexpr hours | |
2039 | make24(const hours& __h, bool __is_pm) noexcept | |
2040 | { | |
2041 | if (!__is_pm) | |
2042 | { | |
2043 | if (__h == 12h) | |
2044 | return 0h; | |
2045 | else | |
2046 | return __h; | |
2047 | } | |
2048 | else | |
2049 | { | |
2050 | if (__h == 12h) | |
2051 | return __h; | |
2052 | else | |
2053 | return __h + 12h; | |
2054 | } | |
2055 | } | |
f2ce64b5 | 2056 | /// @} group chrono |
7f78718b | 2057 | #endif // C++20 |
f2ce64b5 | 2058 | } // namespace chrono |
04f69fda | 2059 | |
7f78718b JW |
2060 | #if __cplusplus >= 202002L |
2061 | inline namespace literals | |
bf1fc37b | 2062 | { |
7f78718b JW |
2063 | inline namespace chrono_literals |
2064 | { | |
2065 | /// @addtogroup chrono | |
2066 | /// @{ | |
2067 | #pragma GCC diagnostic push | |
2068 | #pragma GCC diagnostic ignored "-Wliteral-suffix" | |
2069 | /// Literal suffix for creating chrono::day objects. | |
2070 | /// @since C++20 | |
2071 | constexpr chrono::day | |
2072 | operator""d(unsigned long long __d) noexcept | |
2073 | { return chrono::day{static_cast<unsigned>(__d)}; } | |
bf1fc37b | 2074 | |
7f78718b JW |
2075 | /// Literal suffix for creating chrono::year objects. |
2076 | /// @since C++20 | |
2077 | constexpr chrono::year | |
2078 | operator""y(unsigned long long __y) noexcept | |
2079 | { return chrono::year{static_cast<int>(__y)}; } | |
2080 | #pragma GCC diagnostic pop | |
2081 | /// @} | |
2082 | } // inline namespace chrono_literals | |
2083 | } // inline namespace literals | |
fcc13d6f JW |
2084 | |
2085 | namespace chrono | |
2086 | { | |
2087 | /// @addtogroup chrono | |
2088 | /// @{ | |
2089 | ||
2090 | /// @cond undocumented | |
2091 | namespace __detail | |
2092 | { | |
2093 | template<typename _Period> | |
2094 | const char* | |
2095 | __units_suffix_misc(char* __buf, size_t __n) noexcept | |
2096 | { | |
2097 | namespace __tc = std::__detail; | |
2098 | char* __p = __buf; | |
2099 | __p[0] = '['; | |
2100 | unsigned __nlen = __tc::__to_chars_len((uintmax_t)_Period::num); | |
2101 | __tc::__to_chars_10_impl(__p + 1, __nlen, (uintmax_t)_Period::num); | |
2102 | __p += 1 + __nlen; | |
2103 | if constexpr (_Period::den != 1) | |
2104 | { | |
2105 | __p[0] = '/'; | |
2106 | unsigned __dlen = __tc::__to_chars_len((uintmax_t)_Period::den); | |
2107 | __tc::__to_chars_10_impl(__p + 1, __dlen, (uintmax_t)_Period::den); | |
2108 | __p += 1 + __dlen; | |
2109 | } | |
2110 | __p[0] = ']'; | |
2111 | __p[1] = 's'; | |
2112 | __p[2] = '\0'; | |
2113 | return __buf; | |
2114 | } | |
2115 | ||
2116 | template<typename _Period, typename _CharT> | |
2117 | auto | |
2118 | __units_suffix(char* __buf, size_t __n) noexcept | |
2119 | { | |
2120 | #define _GLIBCXX_UNITS_SUFFIX(period, suffix) \ | |
2121 | if constexpr (is_same_v<_Period, period>) \ | |
2122 | { \ | |
2123 | if constexpr (is_same_v<_CharT, wchar_t>) \ | |
2124 | return L##suffix; \ | |
2125 | else \ | |
2126 | return suffix; \ | |
2127 | } \ | |
2128 | else | |
2129 | ||
2130 | _GLIBCXX_UNITS_SUFFIX(atto, "as") | |
2131 | _GLIBCXX_UNITS_SUFFIX(femto, "fs") | |
2132 | _GLIBCXX_UNITS_SUFFIX(pico, "ps") | |
2133 | _GLIBCXX_UNITS_SUFFIX(nano, "ns") | |
2134 | _GLIBCXX_UNITS_SUFFIX(micro, "\u00b5s") | |
2135 | _GLIBCXX_UNITS_SUFFIX(milli, "ms") | |
2136 | _GLIBCXX_UNITS_SUFFIX(centi, "cs") | |
2137 | _GLIBCXX_UNITS_SUFFIX(deci, "ds") | |
2138 | _GLIBCXX_UNITS_SUFFIX(ratio<1>, "s") | |
2139 | _GLIBCXX_UNITS_SUFFIX(deca, "das") | |
2140 | _GLIBCXX_UNITS_SUFFIX(hecto, "hs") | |
2141 | _GLIBCXX_UNITS_SUFFIX(kilo, "ks") | |
2142 | _GLIBCXX_UNITS_SUFFIX(mega, "Ms") | |
2143 | _GLIBCXX_UNITS_SUFFIX(giga, "Gs") | |
2144 | _GLIBCXX_UNITS_SUFFIX(tera, "Ts") | |
2145 | _GLIBCXX_UNITS_SUFFIX(tera, "Ts") | |
2146 | _GLIBCXX_UNITS_SUFFIX(peta, "Ps") | |
2147 | _GLIBCXX_UNITS_SUFFIX(exa, "Es") | |
2148 | _GLIBCXX_UNITS_SUFFIX(ratio<60>, "min") | |
2149 | _GLIBCXX_UNITS_SUFFIX(ratio<3600>, "h") | |
2150 | _GLIBCXX_UNITS_SUFFIX(ratio<86400>, "d") | |
2151 | #undef _GLIBCXX_UNITS_SUFFIX | |
2152 | return __detail::__units_suffix_misc<_Period>(__buf, __n); | |
2153 | } | |
2154 | } // namespace __detail | |
2155 | /// @endcond | |
2156 | ||
2157 | template<typename _CharT, typename _Traits, | |
2158 | typename _Rep, typename _Period> | |
2159 | inline basic_ostream<_CharT, _Traits>& | |
2160 | operator<<(std::basic_ostream<_CharT, _Traits>& __os, | |
2161 | const duration<_Rep, _Period>& __d) | |
2162 | { | |
2163 | using period = typename _Period::type; | |
2164 | char __buf[sizeof("[/]s") + 2 * numeric_limits<intmax_t>::digits10]; | |
2165 | std::basic_ostringstream<_CharT, _Traits> __s; | |
2166 | __s.flags(__os.flags()); | |
2167 | __s.imbue(__os.getloc()); | |
2168 | __s.precision(__os.precision()); | |
2169 | __s << __d.count(); | |
2170 | __s << __detail::__units_suffix<period, _CharT>(__buf, sizeof(__buf)); | |
2171 | __os << std::move(__s).str(); | |
2172 | return __os; | |
2173 | } | |
2174 | ||
2175 | // TODO: from_stream for duration | |
2176 | ||
2177 | /// @} group chrono | |
2178 | } // namespace chrono | |
7f78718b | 2179 | #endif // C++20 |
88c4d6b7 | 2180 | |
4a15d842 | 2181 | _GLIBCXX_END_NAMESPACE_VERSION |
1c9f675f ESR |
2182 | } // namespace std |
2183 | ||
88c4d6b7 | 2184 | #endif // C++11 |
1c9f675f | 2185 | |
15e38d0d | 2186 | #endif //_GLIBCXX_CHRONO |