1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef _LIBCPP___CHRONO_CALENDAR_H
11 #define _LIBCPP___CHRONO_CALENDAR_H
12 
13 #include <__chrono/duration.h>
14 #include <__chrono/system_clock.h>
15 #include <__chrono/time_point.h>
16 #include <__config>
17 #include <limits>
18 #include <ratio>
19 #include <type_traits>
20 
21 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22 #pragma GCC system_header
23 #endif
24 
25 _LIBCPP_PUSH_MACROS
26 #include <__undef_macros>
27 
28 #if _LIBCPP_STD_VER > 17
29 
30 _LIBCPP_BEGIN_NAMESPACE_STD
31 
32 namespace chrono
33 {
34 
35 struct local_t {};
36 template<class Duration>
37 using local_time  = time_point<local_t, Duration>;
38 using local_seconds = local_time<seconds>;
39 using local_days    = local_time<days>;
40 
41 struct last_spec { explicit last_spec() = default; };
42 
43 class day {
44 private:
45     unsigned char __d;
46 public:
47     day() = default;
48     explicit inline constexpr day(unsigned __val) noexcept : __d(static_cast<unsigned char>(__val)) {}
49     inline constexpr day& operator++()    noexcept { ++__d; return *this; }
50     inline constexpr day  operator++(int) noexcept { day __tmp = *this; ++(*this); return __tmp; }
51     inline constexpr day& operator--()    noexcept { --__d; return *this; }
52     inline constexpr day  operator--(int) noexcept { day __tmp = *this; --(*this); return __tmp; }
53            constexpr day& operator+=(const days& __dd) noexcept;
54            constexpr day& operator-=(const days& __dd) noexcept;
55     explicit inline constexpr operator unsigned() const noexcept { return __d; }
56     inline constexpr bool ok() const noexcept { return __d >= 1 && __d <= 31; }
57   };
58 
59 
60 inline constexpr
61 bool operator==(const day& __lhs, const day& __rhs) noexcept
62 { return static_cast<unsigned>(__lhs) == static_cast<unsigned>(__rhs); }
63 
64 inline constexpr
65 bool operator!=(const day& __lhs, const day& __rhs) noexcept
66 { return !(__lhs == __rhs); }
67 
68 inline constexpr
69 bool operator< (const day& __lhs, const day& __rhs) noexcept
70 { return static_cast<unsigned>(__lhs) <  static_cast<unsigned>(__rhs); }
71 
72 inline constexpr
73 bool operator> (const day& __lhs, const day& __rhs) noexcept
74 { return __rhs < __lhs; }
75 
76 inline constexpr
77 bool operator<=(const day& __lhs, const day& __rhs) noexcept
78 { return !(__rhs < __lhs);}
79 
80 inline constexpr
81 bool operator>=(const day& __lhs, const day& __rhs) noexcept
82 { return !(__lhs < __rhs); }
83 
84 inline constexpr
85 day operator+ (const day& __lhs, const days& __rhs) noexcept
86 { return day(static_cast<unsigned>(__lhs) + __rhs.count()); }
87 
88 inline constexpr
89 day operator+ (const days& __lhs, const day& __rhs) noexcept
90 { return __rhs + __lhs; }
91 
92 inline constexpr
93 day operator- (const day& __lhs, const days& __rhs) noexcept
94 { return __lhs + -__rhs; }
95 
96 inline constexpr
97 days operator-(const day& __lhs, const day& __rhs) noexcept
98 { return days(static_cast<int>(static_cast<unsigned>(__lhs)) -
99               static_cast<int>(static_cast<unsigned>(__rhs))); }
100 
101 inline constexpr day& day::operator+=(const days& __dd) noexcept
102 { *this = *this + __dd; return *this; }
103 
104 inline constexpr day& day::operator-=(const days& __dd) noexcept
105 { *this = *this - __dd; return *this; }
106 
107 
108 class month {
109 private:
110     unsigned char __m;
111 public:
112     month() = default;
113     explicit inline constexpr month(unsigned __val) noexcept : __m(static_cast<unsigned char>(__val)) {}
114     inline constexpr month& operator++()    noexcept { ++__m; return *this; }
115     inline constexpr month  operator++(int) noexcept { month __tmp = *this; ++(*this); return __tmp; }
116     inline constexpr month& operator--()    noexcept { --__m; return *this; }
117     inline constexpr month  operator--(int) noexcept { month __tmp = *this; --(*this); return __tmp; }
118            constexpr month& operator+=(const months& __m1) noexcept;
119            constexpr month& operator-=(const months& __m1) noexcept;
120     explicit inline constexpr operator unsigned() const noexcept { return __m; }
121     inline constexpr bool ok() const noexcept { return __m >= 1 && __m <= 12; }
122 };
123 
124 
125 inline constexpr
126 bool operator==(const month& __lhs, const month& __rhs) noexcept
127 { return static_cast<unsigned>(__lhs) == static_cast<unsigned>(__rhs); }
128 
129 inline constexpr
130 bool operator!=(const month& __lhs, const month& __rhs) noexcept
131 { return !(__lhs == __rhs); }
132 
133 inline constexpr
134 bool operator< (const month& __lhs, const month& __rhs) noexcept
135 { return static_cast<unsigned>(__lhs)  < static_cast<unsigned>(__rhs); }
136 
137 inline constexpr
138 bool operator> (const month& __lhs, const month& __rhs) noexcept
139 { return __rhs < __lhs; }
140 
141 inline constexpr
142 bool operator<=(const month& __lhs, const month& __rhs) noexcept
143 { return !(__rhs < __lhs); }
144 
145 inline constexpr
146 bool operator>=(const month& __lhs, const month& __rhs) noexcept
147 { return !(__lhs < __rhs); }
148 
149 inline constexpr
150 month operator+ (const month& __lhs, const months& __rhs) noexcept
151 {
152     auto const __mu = static_cast<long long>(static_cast<unsigned>(__lhs)) + (__rhs.count() - 1);
153     auto const __yr = (__mu >= 0 ? __mu : __mu - 11) / 12;
154     return month{static_cast<unsigned>(__mu - __yr * 12 + 1)};
155 }
156 
157 inline constexpr
158 month operator+ (const months& __lhs, const month& __rhs) noexcept
159 { return __rhs + __lhs; }
160 
161 inline constexpr
162 month operator- (const month& __lhs, const months& __rhs) noexcept
163 { return __lhs + -__rhs; }
164 
165 inline constexpr
166 months operator-(const month& __lhs, const month& __rhs) noexcept
167 {
168     auto const __dm = static_cast<unsigned>(__lhs) - static_cast<unsigned>(__rhs);
169     return months(__dm <= 11 ? __dm : __dm + 12);
170 }
171 
172 inline constexpr month& month::operator+=(const months& __dm) noexcept
173 { *this = *this + __dm; return *this; }
174 
175 inline constexpr month& month::operator-=(const months& __dm) noexcept
176 { *this = *this - __dm; return *this; }
177 
178 
179 class year {
180 private:
181     short __y;
182 public:
183     year() = default;
184     explicit inline constexpr year(int __val) noexcept : __y(static_cast<short>(__val)) {}
185 
186     inline constexpr year& operator++()    noexcept { ++__y; return *this; }
187     inline constexpr year  operator++(int) noexcept { year __tmp = *this; ++(*this); return __tmp; }
188     inline constexpr year& operator--()    noexcept { --__y; return *this; }
189     inline constexpr year  operator--(int) noexcept { year __tmp = *this; --(*this); return __tmp; }
190            constexpr year& operator+=(const years& __dy) noexcept;
191            constexpr year& operator-=(const years& __dy) noexcept;
192     inline constexpr year operator+() const noexcept { return *this; }
193     inline constexpr year operator-() const noexcept { return year{-__y}; }
194 
195     inline constexpr bool is_leap() const noexcept { return __y % 4 == 0 && (__y % 100 != 0 || __y % 400 == 0); }
196     explicit inline constexpr operator int() const noexcept { return __y; }
197            constexpr bool ok() const noexcept;
198     static inline constexpr year min() noexcept { return year{-32767}; }
199     static inline constexpr year max() noexcept { return year{ 32767}; }
200 };
201 
202 
203 inline constexpr
204 bool operator==(const year& __lhs, const year& __rhs) noexcept
205 { return static_cast<int>(__lhs) == static_cast<int>(__rhs); }
206 
207 inline constexpr
208 bool operator!=(const year& __lhs, const year& __rhs) noexcept
209 { return !(__lhs == __rhs); }
210 
211 inline constexpr
212 bool operator< (const year& __lhs, const year& __rhs) noexcept
213 { return static_cast<int>(__lhs)  < static_cast<int>(__rhs); }
214 
215 inline constexpr
216 bool operator> (const year& __lhs, const year& __rhs) noexcept
217 { return __rhs < __lhs; }
218 
219 inline constexpr
220 bool operator<=(const year& __lhs, const year& __rhs) noexcept
221 { return !(__rhs < __lhs); }
222 
223 inline constexpr
224 bool operator>=(const year& __lhs, const year& __rhs) noexcept
225 { return !(__lhs < __rhs); }
226 
227 inline constexpr
228 year operator+ (const year& __lhs, const years& __rhs) noexcept
229 { return year(static_cast<int>(__lhs) + __rhs.count()); }
230 
231 inline constexpr
232 year operator+ (const years& __lhs, const year& __rhs) noexcept
233 { return __rhs + __lhs; }
234 
235 inline constexpr
236 year operator- (const year& __lhs, const years& __rhs) noexcept
237 { return __lhs + -__rhs; }
238 
239 inline constexpr
240 years operator-(const year& __lhs, const year& __rhs) noexcept
241 { return years{static_cast<int>(__lhs) - static_cast<int>(__rhs)}; }
242 
243 
244 inline constexpr year& year::operator+=(const years& __dy) noexcept
245 { *this = *this + __dy; return *this; }
246 
247 inline constexpr year& year::operator-=(const years& __dy) noexcept
248 { *this = *this - __dy; return *this; }
249 
250 inline constexpr bool year::ok() const noexcept
251 { return static_cast<int>(min()) <= __y && __y <= static_cast<int>(max()); }
252 
253 class weekday_indexed;
254 class weekday_last;
255 
256 class weekday {
257 private:
258     unsigned char __wd;
259     static constexpr unsigned char __weekday_from_days(int __days) noexcept;
260 public:
261   weekday() = default;
262   inline explicit constexpr weekday(unsigned __val) noexcept : __wd(static_cast<unsigned char>(__val == 7 ? 0 : __val)) {}
263   inline constexpr          weekday(const sys_days& __sysd) noexcept
264           : __wd(__weekday_from_days(__sysd.time_since_epoch().count())) {}
265   inline explicit constexpr weekday(const local_days& __locd) noexcept
266           : __wd(__weekday_from_days(__locd.time_since_epoch().count())) {}
267 
268   inline constexpr weekday& operator++()    noexcept { __wd = (__wd == 6 ? 0 : __wd + 1); return *this; }
269   inline constexpr weekday  operator++(int) noexcept { weekday __tmp = *this; ++(*this); return __tmp; }
270   inline constexpr weekday& operator--()    noexcept { __wd = (__wd == 0 ? 6 : __wd - 1); return *this; }
271   inline constexpr weekday  operator--(int) noexcept { weekday __tmp = *this; --(*this); return __tmp; }
272          constexpr weekday& operator+=(const days& __dd) noexcept;
273          constexpr weekday& operator-=(const days& __dd) noexcept;
274   inline constexpr unsigned c_encoding()   const noexcept { return __wd; }
275   inline constexpr unsigned iso_encoding() const noexcept { return __wd == 0u ? 7 : __wd; }
276   inline constexpr bool ok() const noexcept { return __wd <= 6; }
277          constexpr weekday_indexed operator[](unsigned __index) const noexcept;
278          constexpr weekday_last    operator[](last_spec) const noexcept;
279 };
280 
281 
282 // https://howardhinnant.github.io/date_algorithms.html#weekday_from_days
283 inline constexpr
284 unsigned char weekday::__weekday_from_days(int __days) noexcept
285 {
286     return static_cast<unsigned char>(
287               static_cast<unsigned>(__days >= -4 ? (__days+4) % 7 : (__days+5) % 7 + 6)
288            );
289 }
290 
291 inline constexpr
292 bool operator==(const weekday& __lhs, const weekday& __rhs) noexcept
293 { return __lhs.c_encoding() == __rhs.c_encoding(); }
294 
295 inline constexpr
296 bool operator!=(const weekday& __lhs, const weekday& __rhs) noexcept
297 { return !(__lhs == __rhs); }
298 
299 inline constexpr
300 bool operator< (const weekday& __lhs, const weekday& __rhs) noexcept
301 { return __lhs.c_encoding() < __rhs.c_encoding(); }
302 
303 inline constexpr
304 bool operator> (const weekday& __lhs, const weekday& __rhs) noexcept
305 { return __rhs < __lhs; }
306 
307 inline constexpr
308 bool operator<=(const weekday& __lhs, const weekday& __rhs) noexcept
309 { return !(__rhs < __lhs);}
310 
311 inline constexpr
312 bool operator>=(const weekday& __lhs, const weekday& __rhs) noexcept
313 { return !(__lhs < __rhs); }
314 
315 constexpr weekday operator+(const weekday& __lhs, const days& __rhs) noexcept
316 {
317     auto const __mu = static_cast<long long>(__lhs.c_encoding()) + __rhs.count();
318     auto const __yr = (__mu >= 0 ? __mu : __mu - 6) / 7;
319     return weekday{static_cast<unsigned>(__mu - __yr * 7)};
320 }
321 
322 constexpr weekday operator+(const days& __lhs, const weekday& __rhs) noexcept
323 { return __rhs + __lhs; }
324 
325 constexpr weekday operator-(const weekday& __lhs, const days& __rhs) noexcept
326 { return __lhs + -__rhs; }
327 
328 constexpr days operator-(const weekday& __lhs, const weekday& __rhs) noexcept
329 {
330     const int __wdu = __lhs.c_encoding() - __rhs.c_encoding();
331     const int __wk = (__wdu >= 0 ? __wdu : __wdu-6) / 7;
332     return days{__wdu - __wk * 7};
333 }
334 
335 inline constexpr weekday& weekday::operator+=(const days& __dd) noexcept
336 { *this = *this + __dd; return *this; }
337 
338 inline constexpr weekday& weekday::operator-=(const days& __dd) noexcept
339 { *this = *this - __dd; return *this; }
340 
341 
342 class weekday_indexed {
343 private:
344     chrono::weekday __wd;
345     unsigned char          __idx;
346 public:
347     weekday_indexed() = default;
348     inline constexpr weekday_indexed(const chrono::weekday& __wdval, unsigned __idxval) noexcept
349         : __wd{__wdval}, __idx(__idxval) {}
350     inline constexpr chrono::weekday weekday() const noexcept { return __wd; }
351     inline constexpr unsigned                 index() const noexcept { return __idx; }
352     inline constexpr bool ok() const noexcept { return __wd.ok() && __idx >= 1 && __idx <= 5; }
353 };
354 
355 inline constexpr
356 bool operator==(const weekday_indexed& __lhs, const weekday_indexed& __rhs) noexcept
357 { return __lhs.weekday() == __rhs.weekday() && __lhs.index() == __rhs.index(); }
358 
359 inline constexpr
360 bool operator!=(const weekday_indexed& __lhs, const weekday_indexed& __rhs) noexcept
361 { return !(__lhs == __rhs); }
362 
363 
364 class weekday_last {
365 private:
366     chrono::weekday __wd;
367 public:
368     explicit constexpr weekday_last(const chrono::weekday& __val) noexcept
369         : __wd{__val} {}
370     constexpr chrono::weekday weekday() const noexcept { return __wd; }
371     constexpr bool ok() const noexcept { return __wd.ok(); }
372 };
373 
374 inline constexpr
375 bool operator==(const weekday_last& __lhs, const weekday_last& __rhs) noexcept
376 { return __lhs.weekday() == __rhs.weekday(); }
377 
378 inline constexpr
379 bool operator!=(const weekday_last& __lhs, const weekday_last& __rhs) noexcept
380 { return !(__lhs == __rhs); }
381 
382 inline constexpr
383 weekday_indexed weekday::operator[](unsigned __index) const noexcept { return weekday_indexed{*this, __index}; }
384 
385 inline constexpr
386 weekday_last    weekday::operator[](last_spec) const noexcept { return weekday_last{*this}; }
387 
388 
389 inline constexpr last_spec last{};
390 inline constexpr weekday   Sunday{0};
391 inline constexpr weekday   Monday{1};
392 inline constexpr weekday   Tuesday{2};
393 inline constexpr weekday   Wednesday{3};
394 inline constexpr weekday   Thursday{4};
395 inline constexpr weekday   Friday{5};
396 inline constexpr weekday   Saturday{6};
397 
398 inline constexpr month January{1};
399 inline constexpr month February{2};
400 inline constexpr month March{3};
401 inline constexpr month April{4};
402 inline constexpr month May{5};
403 inline constexpr month June{6};
404 inline constexpr month July{7};
405 inline constexpr month August{8};
406 inline constexpr month September{9};
407 inline constexpr month October{10};
408 inline constexpr month November{11};
409 inline constexpr month December{12};
410 
411 
412 class month_day {
413 private:
414    chrono::month __m;
415    chrono::day   __d;
416 public:
417     month_day() = default;
418     constexpr month_day(const chrono::month& __mval, const chrono::day& __dval) noexcept
419         : __m{__mval}, __d{__dval} {}
420     inline constexpr chrono::month month() const noexcept { return __m; }
421     inline constexpr chrono::day   day()   const noexcept { return __d; }
422     constexpr bool ok() const noexcept;
423 };
424 
425 inline constexpr
426 bool month_day::ok() const noexcept
427 {
428     if (!__m.ok()) return false;
429     const unsigned __dval = static_cast<unsigned>(__d);
430     if (__dval < 1 || __dval > 31) return false;
431     if (__dval <= 29) return true;
432 //  Now we've got either 30 or 31
433     const unsigned __mval = static_cast<unsigned>(__m);
434     if (__mval == 2) return false;
435     if (__mval == 4 || __mval == 6 || __mval == 9 || __mval == 11)
436         return __dval == 30;
437     return true;
438 }
439 
440 inline constexpr
441 bool operator==(const month_day& __lhs, const month_day& __rhs) noexcept
442 { return __lhs.month() == __rhs.month() && __lhs.day() == __rhs.day(); }
443 
444 inline constexpr
445 bool operator!=(const month_day& __lhs, const month_day& __rhs) noexcept
446 { return !(__lhs == __rhs); }
447 
448 inline constexpr
449 month_day operator/(const month& __lhs, const day& __rhs) noexcept
450 { return month_day{__lhs, __rhs}; }
451 
452 constexpr
453 month_day operator/(const day& __lhs, const month& __rhs) noexcept
454 { return __rhs / __lhs; }
455 
456 inline constexpr
457 month_day operator/(const month& __lhs, int __rhs) noexcept
458 { return __lhs / day(__rhs); }
459 
460 constexpr
461 month_day operator/(int __lhs, const day& __rhs) noexcept
462 { return month(__lhs) / __rhs; }
463 
464 constexpr
465 month_day operator/(const day& __lhs, int __rhs) noexcept
466 { return month(__rhs) / __lhs; }
467 
468 
469 inline constexpr
470 bool operator< (const month_day& __lhs, const month_day& __rhs) noexcept
471 { return __lhs.month() != __rhs.month() ? __lhs.month() < __rhs.month() : __lhs.day() < __rhs.day(); }
472 
473 inline constexpr
474 bool operator> (const month_day& __lhs, const month_day& __rhs) noexcept
475 { return __rhs < __lhs; }
476 
477 inline constexpr
478 bool operator<=(const month_day& __lhs, const month_day& __rhs) noexcept
479 { return !(__rhs < __lhs);}
480 
481 inline constexpr
482 bool operator>=(const month_day& __lhs, const month_day& __rhs) noexcept
483 { return !(__lhs < __rhs); }
484 
485 
486 
487 class month_day_last {
488 private:
489     chrono::month __m;
490 public:
491     explicit constexpr month_day_last(const chrono::month& __val) noexcept
492         : __m{__val} {}
493     inline constexpr chrono::month month() const noexcept { return __m; }
494     inline constexpr bool ok() const noexcept { return __m.ok(); }
495 };
496 
497 inline constexpr
498 bool operator==(const month_day_last& __lhs, const month_day_last& __rhs) noexcept
499 { return __lhs.month() == __rhs.month(); }
500 
501 inline constexpr
502 bool operator!=(const month_day_last& __lhs, const month_day_last& __rhs) noexcept
503 { return !(__lhs == __rhs); }
504 
505 inline constexpr
506 bool operator< (const month_day_last& __lhs, const month_day_last& __rhs) noexcept
507 { return __lhs.month() < __rhs.month(); }
508 
509 inline constexpr
510 bool operator> (const month_day_last& __lhs, const month_day_last& __rhs) noexcept
511 { return __rhs < __lhs; }
512 
513 inline constexpr
514 bool operator<=(const month_day_last& __lhs, const month_day_last& __rhs) noexcept
515 { return !(__rhs < __lhs);}
516 
517 inline constexpr
518 bool operator>=(const month_day_last& __lhs, const month_day_last& __rhs) noexcept
519 { return !(__lhs < __rhs); }
520 
521 inline constexpr
522 month_day_last operator/(const month& __lhs, last_spec) noexcept
523 { return month_day_last{__lhs}; }
524 
525 inline constexpr
526 month_day_last operator/(last_spec, const month& __rhs) noexcept
527 { return month_day_last{__rhs}; }
528 
529 inline constexpr
530 month_day_last operator/(int __lhs, last_spec) noexcept
531 { return month_day_last{month(__lhs)}; }
532 
533 inline constexpr
534 month_day_last operator/(last_spec, int __rhs) noexcept
535 { return month_day_last{month(__rhs)}; }
536 
537 
538 class month_weekday {
539 private:
540     chrono::month __m;
541     chrono::weekday_indexed __wdi;
542 public:
543     constexpr month_weekday(const chrono::month& __mval, const chrono::weekday_indexed& __wdival) noexcept
544         : __m{__mval}, __wdi{__wdival} {}
545     inline constexpr chrono::month                     month() const noexcept { return __m; }
546     inline constexpr chrono::weekday_indexed weekday_indexed() const noexcept { return __wdi; }
547     inline constexpr bool                                 ok() const noexcept { return __m.ok() && __wdi.ok(); }
548 };
549 
550 inline constexpr
551 bool operator==(const month_weekday& __lhs, const month_weekday& __rhs) noexcept
552 { return __lhs.month() == __rhs.month() && __lhs.weekday_indexed() == __rhs.weekday_indexed(); }
553 
554 inline constexpr
555 bool operator!=(const month_weekday& __lhs, const month_weekday& __rhs) noexcept
556 { return !(__lhs == __rhs); }
557 
558 inline constexpr
559 month_weekday operator/(const month& __lhs, const weekday_indexed& __rhs) noexcept
560 { return month_weekday{__lhs, __rhs}; }
561 
562 inline constexpr
563 month_weekday operator/(int __lhs, const weekday_indexed& __rhs) noexcept
564 { return month_weekday{month(__lhs), __rhs}; }
565 
566 inline constexpr
567 month_weekday operator/(const weekday_indexed& __lhs, const month& __rhs) noexcept
568 { return month_weekday{__rhs, __lhs}; }
569 
570 inline constexpr
571 month_weekday operator/(const weekday_indexed& __lhs, int __rhs) noexcept
572 { return month_weekday{month(__rhs), __lhs}; }
573 
574 
575 class month_weekday_last {
576     chrono::month        __m;
577     chrono::weekday_last __wdl;
578   public:
579     constexpr month_weekday_last(const chrono::month& __mval, const chrono::weekday_last& __wdlval) noexcept
580         : __m{__mval}, __wdl{__wdlval} {}
581     inline constexpr chrono::month               month() const noexcept { return __m; }
582     inline constexpr chrono::weekday_last weekday_last() const noexcept { return __wdl; }
583     inline constexpr bool                           ok() const noexcept { return __m.ok() && __wdl.ok(); }
584 };
585 
586 inline constexpr
587 bool operator==(const month_weekday_last& __lhs, const month_weekday_last& __rhs) noexcept
588 { return __lhs.month() == __rhs.month() && __lhs.weekday_last() == __rhs.weekday_last(); }
589 
590 inline constexpr
591 bool operator!=(const month_weekday_last& __lhs, const month_weekday_last& __rhs) noexcept
592 { return !(__lhs == __rhs); }
593 
594 
595 inline constexpr
596 month_weekday_last operator/(const month& __lhs, const weekday_last& __rhs) noexcept
597 { return month_weekday_last{__lhs, __rhs}; }
598 
599 inline constexpr
600 month_weekday_last operator/(int __lhs, const weekday_last& __rhs) noexcept
601 { return month_weekday_last{month(__lhs), __rhs}; }
602 
603 inline constexpr
604 month_weekday_last operator/(const weekday_last& __lhs, const month& __rhs) noexcept
605 { return month_weekday_last{__rhs, __lhs}; }
606 
607 inline constexpr
608 month_weekday_last operator/(const weekday_last& __lhs, int __rhs) noexcept
609 { return month_weekday_last{month(__rhs), __lhs}; }
610 
611 
612 class year_month {
613     chrono::year  __y;
614     chrono::month __m;
615 public:
616     year_month() = default;
617     constexpr year_month(const chrono::year& __yval, const chrono::month& __mval) noexcept
618         : __y{__yval}, __m{__mval} {}
619     inline constexpr chrono::year  year()  const noexcept { return __y; }
620     inline constexpr chrono::month month() const noexcept { return __m; }
621     inline constexpr year_month& operator+=(const months& __dm) noexcept { this->__m += __dm; return *this; }
622     inline constexpr year_month& operator-=(const months& __dm) noexcept { this->__m -= __dm; return *this; }
623     inline constexpr year_month& operator+=(const years& __dy)  noexcept { this->__y += __dy; return *this; }
624     inline constexpr year_month& operator-=(const years& __dy)  noexcept { this->__y -= __dy; return *this; }
625     inline constexpr bool ok() const noexcept { return __y.ok() && __m.ok(); }
626 };
627 
628 inline constexpr
629 year_month operator/(const year& __y, const month& __m) noexcept { return year_month{__y, __m}; }
630 
631 inline constexpr
632 year_month operator/(const year& __y, int __m) noexcept { return year_month{__y, month(__m)}; }
633 
634 inline constexpr
635 bool operator==(const year_month& __lhs, const year_month& __rhs) noexcept
636 { return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month(); }
637 
638 inline constexpr
639 bool operator!=(const year_month& __lhs, const year_month& __rhs) noexcept
640 { return !(__lhs == __rhs); }
641 
642 inline constexpr
643 bool operator< (const year_month& __lhs, const year_month& __rhs) noexcept
644 { return __lhs.year() != __rhs.year() ? __lhs.year() < __rhs.year() : __lhs.month() < __rhs.month(); }
645 
646 inline constexpr
647 bool operator> (const year_month& __lhs, const year_month& __rhs) noexcept
648 { return __rhs < __lhs; }
649 
650 inline constexpr
651 bool operator<=(const year_month& __lhs, const year_month& __rhs) noexcept
652 { return !(__rhs < __lhs);}
653 
654 inline constexpr
655 bool operator>=(const year_month& __lhs, const year_month& __rhs) noexcept
656 { return !(__lhs < __rhs); }
657 
658 constexpr year_month operator+(const year_month& __lhs, const months& __rhs) noexcept
659 {
660     int __dmi = static_cast<int>(static_cast<unsigned>(__lhs.month())) - 1 + __rhs.count();
661     const int __dy = (__dmi >= 0 ? __dmi : __dmi-11) / 12;
662     __dmi = __dmi - __dy * 12 + 1;
663     return (__lhs.year() + years(__dy)) / month(static_cast<unsigned>(__dmi));
664 }
665 
666 constexpr year_month operator+(const months& __lhs, const year_month& __rhs) noexcept
667 { return __rhs + __lhs; }
668 
669 constexpr year_month operator+(const year_month& __lhs, const years& __rhs) noexcept
670 { return (__lhs.year() + __rhs) / __lhs.month(); }
671 
672 constexpr year_month operator+(const years& __lhs, const year_month& __rhs) noexcept
673 { return __rhs + __lhs; }
674 
675 constexpr months     operator-(const year_month& __lhs, const year_month& __rhs) noexcept
676 { return (__lhs.year() - __rhs.year()) + months(static_cast<unsigned>(__lhs.month()) - static_cast<unsigned>(__rhs.month())); }
677 
678 constexpr year_month operator-(const year_month& __lhs, const months& __rhs) noexcept
679 { return __lhs + -__rhs; }
680 
681 constexpr year_month operator-(const year_month& __lhs, const years& __rhs) noexcept
682 { return __lhs + -__rhs; }
683 
684 class year_month_day_last;
685 
686 class year_month_day {
687 private:
688     chrono::year  __y;
689     chrono::month __m;
690     chrono::day   __d;
691 public:
692      year_month_day() = default;
693      inline constexpr year_month_day(
694             const chrono::year& __yval, const chrono::month& __mval, const chrono::day& __dval) noexcept
695             : __y{__yval}, __m{__mval}, __d{__dval} {}
696             constexpr year_month_day(const year_month_day_last& __ymdl) noexcept;
697      inline constexpr year_month_day(const sys_days& __sysd) noexcept
698             : year_month_day(__from_days(__sysd.time_since_epoch())) {}
699      inline explicit constexpr year_month_day(const local_days& __locd) noexcept
700             : year_month_day(__from_days(__locd.time_since_epoch())) {}
701 
702             constexpr year_month_day& operator+=(const months& __dm) noexcept;
703             constexpr year_month_day& operator-=(const months& __dm) noexcept;
704             constexpr year_month_day& operator+=(const years& __dy)  noexcept;
705             constexpr year_month_day& operator-=(const years& __dy)  noexcept;
706 
707      inline constexpr chrono::year   year() const noexcept { return __y; }
708      inline constexpr chrono::month month() const noexcept { return __m; }
709      inline constexpr chrono::day     day() const noexcept { return __d; }
710      inline constexpr operator   sys_days() const noexcept          { return   sys_days{__to_days()}; }
711      inline explicit constexpr operator local_days() const noexcept { return local_days{__to_days()}; }
712 
713             constexpr bool             ok() const noexcept;
714 
715      static constexpr year_month_day __from_days(days __d) noexcept;
716      constexpr days __to_days() const noexcept;
717 };
718 
719 
720 // https://howardhinnant.github.io/date_algorithms.html#civil_from_days
721 inline constexpr
722 year_month_day
723 year_month_day::__from_days(days __d) noexcept
724 {
725     static_assert(numeric_limits<unsigned>::digits >= 18, "");
726     static_assert(numeric_limits<int>::digits >= 20     , "");
727     const int      __z = __d.count() + 719468;
728     const int      __era = (__z >= 0 ? __z : __z - 146096) / 146097;
729     const unsigned __doe = static_cast<unsigned>(__z - __era * 146097);              // [0, 146096]
730     const unsigned __yoe = (__doe - __doe/1460 + __doe/36524 - __doe/146096) / 365;  // [0, 399]
731     const int      __yr = static_cast<int>(__yoe) + __era * 400;
732     const unsigned __doy = __doe - (365 * __yoe + __yoe/4 - __yoe/100);              // [0, 365]
733     const unsigned __mp = (5 * __doy + 2)/153;                                       // [0, 11]
734     const unsigned __dy = __doy - (153 * __mp + 2)/5 + 1;                            // [1, 31]
735     const unsigned __mth = __mp + (__mp < 10 ? 3 : -9);                              // [1, 12]
736     return year_month_day{chrono::year{__yr + (__mth <= 2)}, chrono::month{__mth}, chrono::day{__dy}};
737 }
738 
739 // https://howardhinnant.github.io/date_algorithms.html#days_from_civil
740 inline constexpr days year_month_day::__to_days() const noexcept
741 {
742     static_assert(numeric_limits<unsigned>::digits >= 18, "");
743     static_assert(numeric_limits<int>::digits >= 20     , "");
744 
745     const int      __yr  = static_cast<int>(__y) - (__m <= February);
746     const unsigned __mth = static_cast<unsigned>(__m);
747     const unsigned __dy  = static_cast<unsigned>(__d);
748 
749     const int      __era = (__yr >= 0 ? __yr : __yr - 399) / 400;
750     const unsigned __yoe = static_cast<unsigned>(__yr - __era * 400);                // [0, 399]
751     const unsigned __doy = (153 * (__mth + (__mth > 2 ? -3 : 9)) + 2) / 5 + __dy-1;  // [0, 365]
752     const unsigned __doe = __yoe * 365 + __yoe/4 - __yoe/100 + __doy;                // [0, 146096]
753     return days{__era * 146097 + static_cast<int>(__doe) - 719468};
754 }
755 
756 inline constexpr
757 bool operator==(const year_month_day& __lhs, const year_month_day& __rhs) noexcept
758 { return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.day() == __rhs.day(); }
759 
760 inline constexpr
761 bool operator!=(const year_month_day& __lhs, const year_month_day& __rhs) noexcept
762 { return !(__lhs == __rhs); }
763 
764 inline constexpr
765 bool operator< (const year_month_day& __lhs, const year_month_day& __rhs) noexcept
766 {
767     if (__lhs.year() < __rhs.year()) return true;
768     if (__lhs.year() > __rhs.year()) return false;
769     if (__lhs.month() < __rhs.month()) return true;
770     if (__lhs.month() > __rhs.month()) return false;
771     return __lhs.day() < __rhs.day();
772 }
773 
774 inline constexpr
775 bool operator> (const year_month_day& __lhs, const year_month_day& __rhs) noexcept
776 { return __rhs < __lhs; }
777 
778 inline constexpr
779 bool operator<=(const year_month_day& __lhs, const year_month_day& __rhs) noexcept
780 { return !(__rhs < __lhs);}
781 
782 inline constexpr
783 bool operator>=(const year_month_day& __lhs, const year_month_day& __rhs) noexcept
784 { return !(__lhs < __rhs); }
785 
786 inline constexpr
787 year_month_day operator/(const year_month& __lhs, const day& __rhs) noexcept
788 { return year_month_day{__lhs.year(), __lhs.month(), __rhs}; }
789 
790 inline constexpr
791 year_month_day operator/(const year_month& __lhs, int __rhs) noexcept
792 { return __lhs / day(__rhs); }
793 
794 inline constexpr
795 year_month_day operator/(const year& __lhs, const month_day& __rhs) noexcept
796 { return __lhs / __rhs.month() / __rhs.day(); }
797 
798 inline constexpr
799 year_month_day operator/(int __lhs, const month_day& __rhs) noexcept
800 { return year(__lhs) / __rhs; }
801 
802 inline constexpr
803 year_month_day operator/(const month_day& __lhs, const year& __rhs) noexcept
804 { return __rhs / __lhs; }
805 
806 inline constexpr
807 year_month_day operator/(const month_day& __lhs, int __rhs) noexcept
808 { return year(__rhs) / __lhs; }
809 
810 
811 inline constexpr
812 year_month_day operator+(const year_month_day& __lhs, const months& __rhs) noexcept
813 { return (__lhs.year()/__lhs.month() + __rhs)/__lhs.day(); }
814 
815 inline constexpr
816 year_month_day operator+(const months& __lhs, const year_month_day& __rhs) noexcept
817 { return __rhs + __lhs; }
818 
819 inline constexpr
820 year_month_day operator-(const year_month_day& __lhs, const months& __rhs) noexcept
821 { return __lhs + -__rhs; }
822 
823 inline constexpr
824 year_month_day operator+(const year_month_day& __lhs, const years& __rhs) noexcept
825 { return (__lhs.year() + __rhs) / __lhs.month() / __lhs.day(); }
826 
827 inline constexpr
828 year_month_day operator+(const years& __lhs, const year_month_day& __rhs) noexcept
829 { return __rhs + __lhs; }
830 
831 inline constexpr
832 year_month_day operator-(const year_month_day& __lhs, const years& __rhs) noexcept
833 { return __lhs + -__rhs; }
834 
835 inline constexpr year_month_day& year_month_day::operator+=(const months& __dm) noexcept { *this = *this + __dm; return *this; }
836 inline constexpr year_month_day& year_month_day::operator-=(const months& __dm) noexcept { *this = *this - __dm; return *this; }
837 inline constexpr year_month_day& year_month_day::operator+=(const years& __dy)  noexcept { *this = *this + __dy; return *this; }
838 inline constexpr year_month_day& year_month_day::operator-=(const years& __dy)  noexcept { *this = *this - __dy; return *this; }
839 
840 class year_month_day_last {
841 private:
842     chrono::year           __y;
843     chrono::month_day_last __mdl;
844 public:
845      constexpr year_month_day_last(const year& __yval, const month_day_last& __mdlval) noexcept
846         : __y{__yval}, __mdl{__mdlval} {}
847 
848      constexpr year_month_day_last& operator+=(const months& __m) noexcept;
849      constexpr year_month_day_last& operator-=(const months& __m) noexcept;
850      constexpr year_month_day_last& operator+=(const years& __y)  noexcept;
851      constexpr year_month_day_last& operator-=(const years& __y)  noexcept;
852 
853      inline constexpr chrono::year                     year() const noexcept { return __y; }
854      inline constexpr chrono::month                   month() const noexcept { return __mdl.month(); }
855      inline constexpr chrono::month_day_last month_day_last() const noexcept { return __mdl; }
856             constexpr chrono::day                       day() const noexcept;
857      inline constexpr operator                     sys_days() const noexcept { return   sys_days{year()/month()/day()}; }
858      inline explicit constexpr operator          local_days() const noexcept { return local_days{year()/month()/day()}; }
859      inline constexpr bool                               ok() const noexcept { return __y.ok() && __mdl.ok(); }
860 };
861 
862 inline constexpr
863 chrono::day year_month_day_last::day() const noexcept
864 {
865     constexpr chrono::day __d[] =
866     {
867         chrono::day(31), chrono::day(28), chrono::day(31),
868         chrono::day(30), chrono::day(31), chrono::day(30),
869         chrono::day(31), chrono::day(31), chrono::day(30),
870         chrono::day(31), chrono::day(30), chrono::day(31)
871     };
872     return (month() != February || !__y.is_leap()) && month().ok() ?
873         __d[static_cast<unsigned>(month()) - 1] : chrono::day{29};
874 }
875 
876 inline constexpr
877 bool operator==(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept
878 { return __lhs.year() == __rhs.year() && __lhs.month_day_last() == __rhs.month_day_last(); }
879 
880 inline constexpr
881 bool operator!=(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept
882 { return !(__lhs == __rhs); }
883 
884 inline constexpr
885 bool operator< (const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept
886 {
887     if (__lhs.year() < __rhs.year()) return true;
888     if (__lhs.year() > __rhs.year()) return false;
889     return __lhs.month_day_last() < __rhs.month_day_last();
890 }
891 
892 inline constexpr
893 bool operator> (const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept
894 { return __rhs < __lhs; }
895 
896 inline constexpr
897 bool operator<=(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept
898 { return !(__rhs < __lhs);}
899 
900 inline constexpr
901 bool operator>=(const year_month_day_last& __lhs, const year_month_day_last& __rhs) noexcept
902 { return !(__lhs < __rhs); }
903 
904 inline constexpr year_month_day_last operator/(const year_month& __lhs, last_spec) noexcept
905 { return year_month_day_last{__lhs.year(), month_day_last{__lhs.month()}}; }
906 
907 inline constexpr year_month_day_last operator/(const year& __lhs, const month_day_last& __rhs) noexcept
908 { return year_month_day_last{__lhs, __rhs}; }
909 
910 inline constexpr year_month_day_last operator/(int __lhs, const month_day_last& __rhs) noexcept
911 { return year_month_day_last{year{__lhs}, __rhs}; }
912 
913 inline constexpr year_month_day_last operator/(const month_day_last& __lhs, const year& __rhs) noexcept
914 { return __rhs / __lhs; }
915 
916 inline constexpr year_month_day_last operator/(const month_day_last& __lhs, int __rhs) noexcept
917 { return year{__rhs} / __lhs; }
918 
919 
920 inline constexpr
921 year_month_day_last operator+(const year_month_day_last& __lhs, const months& __rhs) noexcept
922 { return (__lhs.year() / __lhs.month() + __rhs) / last; }
923 
924 inline constexpr
925 year_month_day_last operator+(const months& __lhs, const year_month_day_last& __rhs) noexcept
926 { return __rhs + __lhs; }
927 
928 inline constexpr
929 year_month_day_last operator-(const year_month_day_last& __lhs, const months& __rhs) noexcept
930 { return __lhs + (-__rhs); }
931 
932 inline constexpr
933 year_month_day_last operator+(const year_month_day_last& __lhs, const years& __rhs) noexcept
934 { return year_month_day_last{__lhs.year() + __rhs, __lhs.month_day_last()}; }
935 
936 inline constexpr
937 year_month_day_last operator+(const years& __lhs, const year_month_day_last& __rhs) noexcept
938 { return __rhs + __lhs; }
939 
940 inline constexpr
941 year_month_day_last operator-(const year_month_day_last& __lhs, const years& __rhs) noexcept
942 { return __lhs + (-__rhs); }
943 
944 inline constexpr year_month_day_last& year_month_day_last::operator+=(const months& __dm) noexcept { *this = *this + __dm; return *this; }
945 inline constexpr year_month_day_last& year_month_day_last::operator-=(const months& __dm) noexcept { *this = *this - __dm; return *this; }
946 inline constexpr year_month_day_last& year_month_day_last::operator+=(const years& __dy)  noexcept { *this = *this + __dy; return *this; }
947 inline constexpr year_month_day_last& year_month_day_last::operator-=(const years& __dy)  noexcept { *this = *this - __dy; return *this; }
948 
949 inline constexpr year_month_day::year_month_day(const year_month_day_last& __ymdl) noexcept
950     : __y{__ymdl.year()}, __m{__ymdl.month()}, __d{__ymdl.day()} {}
951 
952 inline constexpr bool year_month_day::ok() const noexcept
953 {
954     if (!__y.ok() || !__m.ok()) return false;
955     return chrono::day{1} <= __d && __d <= (__y / __m / last).day();
956 }
957 
958 class year_month_weekday {
959     chrono::year            __y;
960     chrono::month           __m;
961     chrono::weekday_indexed __wdi;
962 public:
963     year_month_weekday() = default;
964     constexpr year_month_weekday(const chrono::year& __yval, const chrono::month& __mval,
965                                const chrono::weekday_indexed& __wdival) noexcept
966         : __y{__yval}, __m{__mval}, __wdi{__wdival} {}
967     constexpr year_month_weekday(const sys_days& __sysd) noexcept
968             : year_month_weekday(__from_days(__sysd.time_since_epoch())) {}
969     inline explicit constexpr year_month_weekday(const local_days& __locd) noexcept
970             : year_month_weekday(__from_days(__locd.time_since_epoch())) {}
971     constexpr year_month_weekday& operator+=(const months& m) noexcept;
972     constexpr year_month_weekday& operator-=(const months& m) noexcept;
973     constexpr year_month_weekday& operator+=(const years& y)  noexcept;
974     constexpr year_month_weekday& operator-=(const years& y)  noexcept;
975 
976     inline constexpr chrono::year                       year() const noexcept { return __y; }
977     inline constexpr chrono::month                     month() const noexcept { return __m; }
978     inline constexpr chrono::weekday                 weekday() const noexcept { return __wdi.weekday(); }
979     inline constexpr unsigned                          index() const noexcept { return __wdi.index(); }
980     inline constexpr chrono::weekday_indexed weekday_indexed() const noexcept { return __wdi; }
981 
982     inline constexpr                       operator sys_days() const noexcept { return   sys_days{__to_days()}; }
983     inline explicit constexpr operator            local_days() const noexcept { return local_days{__to_days()}; }
984     inline constexpr bool ok() const noexcept
985     {
986         if (!__y.ok() || !__m.ok() || !__wdi.ok()) return false;
987         if (__wdi.index() <= 4) return true;
988         auto __nth_weekday_day =
989             __wdi.weekday() -
990             chrono::weekday{static_cast<sys_days>(__y / __m / 1)} +
991             days{(__wdi.index() - 1) * 7 + 1};
992         return static_cast<unsigned>(__nth_weekday_day.count()) <=
993                static_cast<unsigned>((__y / __m / last).day());
994     }
995 
996     static constexpr year_month_weekday __from_days(days __d) noexcept;
997     constexpr days __to_days() const noexcept;
998 };
999 
1000 inline constexpr
1001 year_month_weekday year_month_weekday::__from_days(days __d) noexcept
1002 {
1003     const sys_days      __sysd{__d};
1004     const chrono::weekday __wd = chrono::weekday(__sysd);
1005     const year_month_day __ymd = year_month_day(__sysd);
1006     return year_month_weekday{__ymd.year(), __ymd.month(),
1007                               __wd[(static_cast<unsigned>(__ymd.day())-1)/7+1]};
1008 }
1009 
1010 inline constexpr
1011 days year_month_weekday::__to_days() const noexcept
1012 {
1013     const sys_days __sysd = sys_days(__y/__m/1);
1014     return (__sysd + (__wdi.weekday() - chrono::weekday(__sysd) + days{(__wdi.index()-1)*7}))
1015                 .time_since_epoch();
1016 }
1017 
1018 inline constexpr
1019 bool operator==(const year_month_weekday& __lhs, const year_month_weekday& __rhs) noexcept
1020 { return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.weekday_indexed() == __rhs.weekday_indexed(); }
1021 
1022 inline constexpr
1023 bool operator!=(const year_month_weekday& __lhs, const year_month_weekday& __rhs) noexcept
1024 { return !(__lhs == __rhs); }
1025 
1026 inline constexpr
1027 year_month_weekday operator/(const year_month& __lhs, const weekday_indexed& __rhs) noexcept
1028 { return year_month_weekday{__lhs.year(), __lhs.month(), __rhs}; }
1029 
1030 inline constexpr
1031 year_month_weekday operator/(const year& __lhs, const month_weekday& __rhs) noexcept
1032 { return year_month_weekday{__lhs, __rhs.month(), __rhs.weekday_indexed()}; }
1033 
1034 inline constexpr
1035 year_month_weekday operator/(int __lhs, const month_weekday& __rhs) noexcept
1036 { return year(__lhs) / __rhs; }
1037 
1038 inline constexpr
1039 year_month_weekday operator/(const month_weekday& __lhs, const year& __rhs) noexcept
1040 { return __rhs / __lhs; }
1041 
1042 inline constexpr
1043 year_month_weekday operator/(const month_weekday& __lhs, int __rhs) noexcept
1044 { return year(__rhs) / __lhs; }
1045 
1046 
1047 inline constexpr
1048 year_month_weekday operator+(const year_month_weekday& __lhs, const months& __rhs) noexcept
1049 { return (__lhs.year() / __lhs.month() + __rhs) / __lhs.weekday_indexed(); }
1050 
1051 inline constexpr
1052 year_month_weekday operator+(const months& __lhs, const year_month_weekday& __rhs) noexcept
1053 { return __rhs + __lhs; }
1054 
1055 inline constexpr
1056 year_month_weekday operator-(const year_month_weekday& __lhs, const months& __rhs) noexcept
1057 { return __lhs + (-__rhs); }
1058 
1059 inline constexpr
1060 year_month_weekday operator+(const year_month_weekday& __lhs, const years& __rhs) noexcept
1061 { return year_month_weekday{__lhs.year() + __rhs, __lhs.month(), __lhs.weekday_indexed()}; }
1062 
1063 inline constexpr
1064 year_month_weekday operator+(const years& __lhs, const year_month_weekday& __rhs) noexcept
1065 { return __rhs + __lhs; }
1066 
1067 inline constexpr
1068 year_month_weekday operator-(const year_month_weekday& __lhs, const years& __rhs) noexcept
1069 { return __lhs + (-__rhs); }
1070 
1071 
1072 inline constexpr year_month_weekday& year_month_weekday::operator+=(const months& __dm) noexcept { *this = *this + __dm; return *this; }
1073 inline constexpr year_month_weekday& year_month_weekday::operator-=(const months& __dm) noexcept { *this = *this - __dm; return *this; }
1074 inline constexpr year_month_weekday& year_month_weekday::operator+=(const years& __dy)  noexcept { *this = *this + __dy; return *this; }
1075 inline constexpr year_month_weekday& year_month_weekday::operator-=(const years& __dy)  noexcept { *this = *this - __dy; return *this; }
1076 
1077 class year_month_weekday_last {
1078 private:
1079     chrono::year         __y;
1080     chrono::month        __m;
1081     chrono::weekday_last __wdl;
1082 public:
1083     constexpr year_month_weekday_last(const chrono::year& __yval, const chrono::month& __mval,
1084                                       const chrono::weekday_last& __wdlval) noexcept
1085                 : __y{__yval}, __m{__mval}, __wdl{__wdlval} {}
1086     constexpr year_month_weekday_last& operator+=(const months& __dm) noexcept;
1087     constexpr year_month_weekday_last& operator-=(const months& __dm) noexcept;
1088     constexpr year_month_weekday_last& operator+=(const years& __dy)  noexcept;
1089     constexpr year_month_weekday_last& operator-=(const years& __dy)  noexcept;
1090 
1091     inline constexpr chrono::year                 year() const noexcept { return __y; }
1092     inline constexpr chrono::month               month() const noexcept { return __m; }
1093     inline constexpr chrono::weekday           weekday() const noexcept { return __wdl.weekday(); }
1094     inline constexpr chrono::weekday_last weekday_last() const noexcept { return __wdl; }
1095     inline constexpr operator                 sys_days() const noexcept { return   sys_days{__to_days()}; }
1096     inline explicit constexpr operator      local_days() const noexcept { return local_days{__to_days()}; }
1097     inline constexpr bool ok() const noexcept { return __y.ok() && __m.ok() && __wdl.ok(); }
1098 
1099     constexpr days __to_days() const noexcept;
1100 
1101 };
1102 
1103 inline constexpr
1104 days year_month_weekday_last::__to_days() const noexcept
1105 {
1106     const sys_days __last = sys_days{__y/__m/last};
1107     return (__last - (chrono::weekday{__last} - __wdl.weekday())).time_since_epoch();
1108 
1109 }
1110 
1111 inline constexpr
1112 bool operator==(const year_month_weekday_last& __lhs, const year_month_weekday_last& __rhs) noexcept
1113 { return __lhs.year() == __rhs.year() && __lhs.month() == __rhs.month() && __lhs.weekday_last() == __rhs.weekday_last(); }
1114 
1115 inline constexpr
1116 bool operator!=(const year_month_weekday_last& __lhs, const year_month_weekday_last& __rhs) noexcept
1117 { return !(__lhs == __rhs); }
1118 
1119 
1120 inline constexpr
1121 year_month_weekday_last operator/(const year_month& __lhs, const weekday_last& __rhs) noexcept
1122 { return year_month_weekday_last{__lhs.year(), __lhs.month(), __rhs}; }
1123 
1124 inline constexpr
1125 year_month_weekday_last operator/(const year& __lhs, const month_weekday_last& __rhs) noexcept
1126 { return year_month_weekday_last{__lhs, __rhs.month(), __rhs.weekday_last()}; }
1127 
1128 inline constexpr
1129 year_month_weekday_last operator/(int __lhs, const month_weekday_last& __rhs) noexcept
1130 { return year(__lhs) / __rhs; }
1131 
1132 inline constexpr
1133 year_month_weekday_last operator/(const month_weekday_last& __lhs, const year& __rhs) noexcept
1134 { return __rhs / __lhs; }
1135 
1136 inline constexpr
1137 year_month_weekday_last operator/(const month_weekday_last& __lhs, int __rhs) noexcept
1138 { return year(__rhs) / __lhs; }
1139 
1140 
1141 inline constexpr
1142 year_month_weekday_last operator+(const year_month_weekday_last& __lhs, const months& __rhs) noexcept
1143 { return (__lhs.year() / __lhs.month() + __rhs) / __lhs.weekday_last(); }
1144 
1145 inline constexpr
1146 year_month_weekday_last operator+(const months& __lhs, const year_month_weekday_last& __rhs) noexcept
1147 { return __rhs + __lhs; }
1148 
1149 inline constexpr
1150 year_month_weekday_last operator-(const year_month_weekday_last& __lhs, const months& __rhs) noexcept
1151 { return __lhs + (-__rhs); }
1152 
1153 inline constexpr
1154 year_month_weekday_last operator+(const year_month_weekday_last& __lhs, const years& __rhs) noexcept
1155 { return year_month_weekday_last{__lhs.year() + __rhs, __lhs.month(), __lhs.weekday_last()}; }
1156 
1157 inline constexpr
1158 year_month_weekday_last operator+(const years& __lhs, const year_month_weekday_last& __rhs) noexcept
1159 { return __rhs + __lhs; }
1160 
1161 inline constexpr
1162 year_month_weekday_last operator-(const year_month_weekday_last& __lhs, const years& __rhs) noexcept
1163 { return __lhs + (-__rhs); }
1164 
1165 inline constexpr year_month_weekday_last& year_month_weekday_last::operator+=(const months& __dm) noexcept { *this = *this + __dm; return *this; }
1166 inline constexpr year_month_weekday_last& year_month_weekday_last::operator-=(const months& __dm) noexcept { *this = *this - __dm; return *this; }
1167 inline constexpr year_month_weekday_last& year_month_weekday_last::operator+=(const years& __dy)  noexcept { *this = *this + __dy; return *this; }
1168 inline constexpr year_month_weekday_last& year_month_weekday_last::operator-=(const years& __dy)  noexcept { *this = *this - __dy; return *this; }
1169 
1170 
1171 template <class _Duration>
1172 class hh_mm_ss
1173 {
1174 private:
1175     static_assert(__is_duration<_Duration>::value, "template parameter of hh_mm_ss must be a std::chrono::duration");
1176     using __CommonType = common_type_t<_Duration, chrono::seconds>;
1177 
1178     static constexpr uint64_t __pow10(unsigned __exp)
1179     {
1180         uint64_t __ret = 1;
1181         for (unsigned __i = 0; __i < __exp; ++__i)
1182             __ret *= 10U;
1183         return __ret;
1184     }
1185 
1186     static constexpr unsigned __width(uint64_t __n, uint64_t __d = 10, unsigned __w = 0)
1187     {
1188         if (__n >= 2 && __d != 0 && __w < 19)
1189             return 1 + __width(__n, __d % __n * 10, __w+1);
1190         return 0;
1191     }
1192 
1193 public:
1194     static unsigned constexpr fractional_width = __width(__CommonType::period::den) < 19 ?
1195                                                  __width(__CommonType::period::den) : 6u;
1196     using precision = duration<typename __CommonType::rep, ratio<1, __pow10(fractional_width)>>;
1197 
1198     constexpr hh_mm_ss() noexcept : hh_mm_ss{_Duration::zero()} {}
1199 
1200     constexpr explicit hh_mm_ss(_Duration __d) noexcept :
1201         __is_neg(__d < _Duration(0)),
1202         __h(duration_cast<chrono::hours>  (abs(__d))),
1203         __m(duration_cast<chrono::minutes>(abs(__d) - hours())),
1204         __s(duration_cast<chrono::seconds>(abs(__d) - hours() - minutes())),
1205         __f(duration_cast<precision>      (abs(__d) - hours() - minutes() - seconds()))
1206         {}
1207 
1208     constexpr bool is_negative()        const noexcept { return __is_neg; }
1209     constexpr chrono::hours hours()     const noexcept { return __h; }
1210     constexpr chrono::minutes minutes() const noexcept { return __m; }
1211     constexpr chrono::seconds seconds() const noexcept { return __s; }
1212     constexpr precision subseconds()    const noexcept { return __f; }
1213 
1214     constexpr precision to_duration() const noexcept
1215     {
1216         auto __dur = __h + __m + __s + __f;
1217         return __is_neg ? -__dur : __dur;
1218     }
1219 
1220     constexpr explicit operator precision() const noexcept { return to_duration(); }
1221 
1222 private:
1223     bool            __is_neg;
1224     chrono::hours   __h;
1225     chrono::minutes __m;
1226     chrono::seconds __s;
1227     precision       __f;
1228 };
1229 
1230 constexpr bool is_am(const hours& __h) noexcept { return __h >= hours( 0) && __h < hours(12); }
1231 constexpr bool is_pm(const hours& __h) noexcept { return __h >= hours(12) && __h < hours(24); }
1232 
1233 constexpr hours make12(const hours& __h) noexcept
1234 {
1235     if      (__h == hours( 0)) return hours(12);
1236     else if (__h <= hours(12)) return __h;
1237     else                       return __h - hours(12);
1238 }
1239 
1240 constexpr hours make24(const hours& __h, bool __is_pm) noexcept
1241 {
1242     if (__is_pm)
1243         return __h == hours(12) ? __h : __h + hours(12);
1244     else
1245         return __h == hours(12) ? hours(0) : __h;
1246 }
1247 
1248 } // namespace chrono
1249 
1250 inline namespace literals
1251 {
1252   inline namespace chrono_literals
1253   {
1254     constexpr chrono::day operator ""d(unsigned long long __d) noexcept
1255     {
1256         return chrono::day(static_cast<unsigned>(__d));
1257     }
1258 
1259     constexpr chrono::year operator ""y(unsigned long long __y) noexcept
1260     {
1261         return chrono::year(static_cast<int>(__y));
1262     }
1263 } // namespace chrono_literals
1264 } // namespace literals
1265 
1266 namespace chrono { // hoist the literals into namespace std::chrono
1267    using namespace literals::chrono_literals;
1268 } // namespace chrono
1269 
1270 _LIBCPP_END_NAMESPACE_STD
1271 
1272 #endif // _LIBCPP_STD_VER > 17
1273 
1274 _LIBCPP_POP_MACROS
1275 
1276 #endif // _LIBCPP___CHRONO_CALENDAR_H
1277