comparison common/date/date.h @ 0:a4671277546c tip

created the repository for the thymian project
author ferencd
date Tue, 17 Aug 2021 11:19:54 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:a4671277546c
1 #ifndef DATE_H
2 #define DATE_H
3
4 // The MIT License (MIT)
5 //
6 // Copyright (c) 2015, 2016, 2017 Howard Hinnant
7 // Copyright (c) 2016 Adrian Colomitchi
8 // Copyright (c) 2017 Florian Dang
9 // Copyright (c) 2017 Paul Thompson
10 // Copyright (c) 2018, 2019 Tomasz KamiƄski
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
13 // of this software and associated documentation files (the "Software"), to deal
14 // in the Software without restriction, including without limitation the rights
15 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 // copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
18 //
19 // The above copyright notice and this permission notice shall be included in all
20 // copies or substantial portions of the Software.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 // SOFTWARE.
29 //
30 // Our apologies. When the previous paragraph was written, lowercase had not yet
31 // been invented (that would involve another several millennia of evolution).
32 // We did not mean to shout.
33
34 #ifndef HAS_STRING_VIEW
35 # if __cplusplus >= 201703 || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
36 # define HAS_STRING_VIEW 1
37 # else
38 # define HAS_STRING_VIEW 0
39 # endif
40 #endif // HAS_STRING_VIEW
41
42 #include <cassert>
43 #include <algorithm>
44 #include <cctype>
45 #include <chrono>
46 #include <climits>
47 #if !(__cplusplus >= 201402)
48 # include <cmath>
49 #endif
50 #include <cstddef>
51 #include <cstdint>
52 #include <cstdlib>
53 #include <ctime>
54 #include <ios>
55 #include <istream>
56 #include <iterator>
57 #include <limits>
58 #include <locale>
59 #include <memory>
60 #include <ostream>
61 #include <ratio>
62 #include <sstream>
63 #include <stdexcept>
64 #include <string>
65 #if HAS_STRING_VIEW
66 # include <string_view>
67 #endif
68 #include <utility>
69 #include <type_traits>
70
71 #ifdef __GNUC__
72 # pragma GCC diagnostic push
73 # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR > 7)
74 # pragma GCC diagnostic ignored "-Wpedantic"
75 # endif
76 # if __GNUC__ < 5
77 // GCC 4.9 Bug 61489 Wrong warning with -Wmissing-field-initializers
78 # pragma GCC diagnostic ignored "-Wmissing-field-initializers"
79 # endif
80 #endif
81
82 #ifdef _MSC_VER
83 # pragma warning(push)
84 // warning C4127: conditional expression is constant
85 # pragma warning(disable : 4127)
86 #endif
87
88 namespace date
89 {
90
91 //---------------+
92 // Configuration |
93 //---------------+
94
95 #ifndef ONLY_C_LOCALE
96 # define ONLY_C_LOCALE 0
97 #endif
98
99 #if defined(_MSC_VER) && (!defined(__clang__) || (_MSC_VER < 1910))
100 // MSVC
101 # ifndef _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING
102 # define _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING
103 # endif
104 # if _MSC_VER < 1910
105 // before VS2017
106 # define CONSTDATA const
107 # define CONSTCD11
108 # define CONSTCD14
109 # define NOEXCEPT _NOEXCEPT
110 # else
111 // VS2017 and later
112 # define CONSTDATA constexpr const
113 # define CONSTCD11 constexpr
114 # define CONSTCD14 constexpr
115 # define NOEXCEPT noexcept
116 # endif
117
118 #elif defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x5150
119 // Oracle Developer Studio 12.6 and earlier
120 # define CONSTDATA constexpr const
121 # define CONSTCD11 constexpr
122 # define CONSTCD14
123 # define NOEXCEPT noexcept
124
125 #elif __cplusplus >= 201402
126 // C++14
127 # define CONSTDATA constexpr const
128 # define CONSTCD11 constexpr
129 # define CONSTCD14 constexpr
130 # define NOEXCEPT noexcept
131 #else
132 // C++11
133 # define CONSTDATA constexpr const
134 # define CONSTCD11 constexpr
135 # define CONSTCD14
136 # define NOEXCEPT noexcept
137 #endif
138
139 #ifndef HAS_UNCAUGHT_EXCEPTIONS
140 # if __cplusplus > 201703 || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L)
141 # define HAS_UNCAUGHT_EXCEPTIONS 1
142 # else
143 # define HAS_UNCAUGHT_EXCEPTIONS 0
144 # endif
145 #endif // HAS_UNCAUGHT_EXCEPTIONS
146
147 #ifndef HAS_VOID_T
148 # if __cplusplus >= 201703 || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
149 # define HAS_VOID_T 1
150 # else
151 # define HAS_VOID_T 0
152 # endif
153 #endif // HAS_VOID_T
154
155 // Protect from Oracle sun macro
156 #ifdef sun
157 # undef sun
158 #endif
159
160 //-----------+
161 // Interface |
162 //-----------+
163
164 // durations
165
166 using days = std::chrono::duration
167 <int, std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>::type>;
168
169 using weeks = std::chrono::duration
170 <int, std::ratio_multiply<std::ratio<7>, days::period>::type>;
171
172 using years = std::chrono::duration
173 <int, std::ratio_multiply<std::ratio<146097, 400>, days::period>::type>;
174
175 using months = std::chrono::duration
176 <int, std::ratio_divide<years::period, std::ratio<12>>::type>;
177
178 // time_point
179
180 template <class Duration>
181 using sys_time = std::chrono::time_point<std::chrono::system_clock, Duration>;
182
183 using sys_days = sys_time<days>;
184 using sys_seconds = sys_time<std::chrono::seconds>;
185
186 struct local_t {};
187
188 template <class Duration>
189 using local_time = std::chrono::time_point<local_t, Duration>;
190
191 using local_seconds = local_time<std::chrono::seconds>;
192 using local_days = local_time<days>;
193
194 // types
195
196 struct last_spec
197 {
198 explicit last_spec() = default;
199 };
200
201 class day;
202 class month;
203 class year;
204
205 class weekday;
206 class weekday_indexed;
207 class weekday_last;
208
209 class month_day;
210 class month_day_last;
211 class month_weekday;
212 class month_weekday_last;
213
214 class year_month;
215
216 class year_month_day;
217 class year_month_day_last;
218 class year_month_weekday;
219 class year_month_weekday_last;
220
221 // date composition operators
222
223 CONSTCD11 year_month operator/(const year& y, const month& m) NOEXCEPT;
224 CONSTCD11 year_month operator/(const year& y, int m) NOEXCEPT;
225
226 CONSTCD11 month_day operator/(const day& d, const month& m) NOEXCEPT;
227 CONSTCD11 month_day operator/(const day& d, int m) NOEXCEPT;
228 CONSTCD11 month_day operator/(const month& m, const day& d) NOEXCEPT;
229 CONSTCD11 month_day operator/(const month& m, int d) NOEXCEPT;
230 CONSTCD11 month_day operator/(int m, const day& d) NOEXCEPT;
231
232 CONSTCD11 month_day_last operator/(const month& m, last_spec) NOEXCEPT;
233 CONSTCD11 month_day_last operator/(int m, last_spec) NOEXCEPT;
234 CONSTCD11 month_day_last operator/(last_spec, const month& m) NOEXCEPT;
235 CONSTCD11 month_day_last operator/(last_spec, int m) NOEXCEPT;
236
237 CONSTCD11 month_weekday operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT;
238 CONSTCD11 month_weekday operator/(int m, const weekday_indexed& wdi) NOEXCEPT;
239 CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT;
240 CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, int m) NOEXCEPT;
241
242 CONSTCD11 month_weekday_last operator/(const month& m, const weekday_last& wdl) NOEXCEPT;
243 CONSTCD11 month_weekday_last operator/(int m, const weekday_last& wdl) NOEXCEPT;
244 CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, const month& m) NOEXCEPT;
245 CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, int m) NOEXCEPT;
246
247 CONSTCD11 year_month_day operator/(const year_month& ym, const day& d) NOEXCEPT;
248 CONSTCD11 year_month_day operator/(const year_month& ym, int d) NOEXCEPT;
249 CONSTCD11 year_month_day operator/(const year& y, const month_day& md) NOEXCEPT;
250 CONSTCD11 year_month_day operator/(int y, const month_day& md) NOEXCEPT;
251 CONSTCD11 year_month_day operator/(const month_day& md, const year& y) NOEXCEPT;
252 CONSTCD11 year_month_day operator/(const month_day& md, int y) NOEXCEPT;
253
254 CONSTCD11
255 year_month_day_last operator/(const year_month& ym, last_spec) NOEXCEPT;
256 CONSTCD11
257 year_month_day_last operator/(const year& y, const month_day_last& mdl) NOEXCEPT;
258 CONSTCD11
259 year_month_day_last operator/(int y, const month_day_last& mdl) NOEXCEPT;
260 CONSTCD11
261 year_month_day_last operator/(const month_day_last& mdl, const year& y) NOEXCEPT;
262 CONSTCD11
263 year_month_day_last operator/(const month_day_last& mdl, int y) NOEXCEPT;
264
265 CONSTCD11
266 year_month_weekday
267 operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT;
268
269 CONSTCD11
270 year_month_weekday
271 operator/(const year& y, const month_weekday& mwd) NOEXCEPT;
272
273 CONSTCD11
274 year_month_weekday
275 operator/(int y, const month_weekday& mwd) NOEXCEPT;
276
277 CONSTCD11
278 year_month_weekday
279 operator/(const month_weekday& mwd, const year& y) NOEXCEPT;
280
281 CONSTCD11
282 year_month_weekday
283 operator/(const month_weekday& mwd, int y) NOEXCEPT;
284
285 CONSTCD11
286 year_month_weekday_last
287 operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT;
288
289 CONSTCD11
290 year_month_weekday_last
291 operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT;
292
293 CONSTCD11
294 year_month_weekday_last
295 operator/(int y, const month_weekday_last& mwdl) NOEXCEPT;
296
297 CONSTCD11
298 year_month_weekday_last
299 operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT;
300
301 CONSTCD11
302 year_month_weekday_last
303 operator/(const month_weekday_last& mwdl, int y) NOEXCEPT;
304
305 // Detailed interface
306
307 // day
308
309 class day
310 {
311 unsigned char d_;
312
313 public:
314 day() = default;
315 explicit CONSTCD11 day(unsigned d) NOEXCEPT;
316
317 CONSTCD14 day& operator++() NOEXCEPT;
318 CONSTCD14 day operator++(int) NOEXCEPT;
319 CONSTCD14 day& operator--() NOEXCEPT;
320 CONSTCD14 day operator--(int) NOEXCEPT;
321
322 CONSTCD14 day& operator+=(const days& d) NOEXCEPT;
323 CONSTCD14 day& operator-=(const days& d) NOEXCEPT;
324
325 CONSTCD11 explicit operator unsigned() const NOEXCEPT;
326 CONSTCD11 bool ok() const NOEXCEPT;
327 };
328
329 CONSTCD11 bool operator==(const day& x, const day& y) NOEXCEPT;
330 CONSTCD11 bool operator!=(const day& x, const day& y) NOEXCEPT;
331 CONSTCD11 bool operator< (const day& x, const day& y) NOEXCEPT;
332 CONSTCD11 bool operator> (const day& x, const day& y) NOEXCEPT;
333 CONSTCD11 bool operator<=(const day& x, const day& y) NOEXCEPT;
334 CONSTCD11 bool operator>=(const day& x, const day& y) NOEXCEPT;
335
336 CONSTCD11 day operator+(const day& x, const days& y) NOEXCEPT;
337 CONSTCD11 day operator+(const days& x, const day& y) NOEXCEPT;
338 CONSTCD11 day operator-(const day& x, const days& y) NOEXCEPT;
339 CONSTCD11 days operator-(const day& x, const day& y) NOEXCEPT;
340
341 template<class CharT, class Traits>
342 std::basic_ostream<CharT, Traits>&
343 operator<<(std::basic_ostream<CharT, Traits>& os, const day& d);
344
345 // month
346
347 class month
348 {
349 unsigned char m_;
350
351 public:
352 month() = default;
353 explicit CONSTCD11 month(unsigned m) NOEXCEPT;
354
355 CONSTCD14 month& operator++() NOEXCEPT;
356 CONSTCD14 month operator++(int) NOEXCEPT;
357 CONSTCD14 month& operator--() NOEXCEPT;
358 CONSTCD14 month operator--(int) NOEXCEPT;
359
360 CONSTCD14 month& operator+=(const months& m) NOEXCEPT;
361 CONSTCD14 month& operator-=(const months& m) NOEXCEPT;
362
363 CONSTCD11 explicit operator unsigned() const NOEXCEPT;
364 CONSTCD11 bool ok() const NOEXCEPT;
365 };
366
367 CONSTCD11 bool operator==(const month& x, const month& y) NOEXCEPT;
368 CONSTCD11 bool operator!=(const month& x, const month& y) NOEXCEPT;
369 CONSTCD11 bool operator< (const month& x, const month& y) NOEXCEPT;
370 CONSTCD11 bool operator> (const month& x, const month& y) NOEXCEPT;
371 CONSTCD11 bool operator<=(const month& x, const month& y) NOEXCEPT;
372 CONSTCD11 bool operator>=(const month& x, const month& y) NOEXCEPT;
373
374 CONSTCD14 month operator+(const month& x, const months& y) NOEXCEPT;
375 CONSTCD14 month operator+(const months& x, const month& y) NOEXCEPT;
376 CONSTCD14 month operator-(const month& x, const months& y) NOEXCEPT;
377 CONSTCD14 months operator-(const month& x, const month& y) NOEXCEPT;
378
379 template<class CharT, class Traits>
380 std::basic_ostream<CharT, Traits>&
381 operator<<(std::basic_ostream<CharT, Traits>& os, const month& m);
382
383 // year
384
385 class year
386 {
387 short y_;
388
389 public:
390 year() = default;
391 explicit CONSTCD11 year(int y) NOEXCEPT;
392
393 CONSTCD14 year& operator++() NOEXCEPT;
394 CONSTCD14 year operator++(int) NOEXCEPT;
395 CONSTCD14 year& operator--() NOEXCEPT;
396 CONSTCD14 year operator--(int) NOEXCEPT;
397
398 CONSTCD14 year& operator+=(const years& y) NOEXCEPT;
399 CONSTCD14 year& operator-=(const years& y) NOEXCEPT;
400
401 CONSTCD11 year operator-() const NOEXCEPT;
402 CONSTCD11 year operator+() const NOEXCEPT;
403
404 CONSTCD11 bool is_leap() const NOEXCEPT;
405
406 CONSTCD11 explicit operator int() const NOEXCEPT;
407 CONSTCD11 bool ok() const NOEXCEPT;
408
409 static CONSTCD11 year min() NOEXCEPT { return year{-32767}; }
410 static CONSTCD11 year max() NOEXCEPT { return year{32767}; }
411 };
412
413 CONSTCD11 bool operator==(const year& x, const year& y) NOEXCEPT;
414 CONSTCD11 bool operator!=(const year& x, const year& y) NOEXCEPT;
415 CONSTCD11 bool operator< (const year& x, const year& y) NOEXCEPT;
416 CONSTCD11 bool operator> (const year& x, const year& y) NOEXCEPT;
417 CONSTCD11 bool operator<=(const year& x, const year& y) NOEXCEPT;
418 CONSTCD11 bool operator>=(const year& x, const year& y) NOEXCEPT;
419
420 CONSTCD11 year operator+(const year& x, const years& y) NOEXCEPT;
421 CONSTCD11 year operator+(const years& x, const year& y) NOEXCEPT;
422 CONSTCD11 year operator-(const year& x, const years& y) NOEXCEPT;
423 CONSTCD11 years operator-(const year& x, const year& y) NOEXCEPT;
424
425 template<class CharT, class Traits>
426 std::basic_ostream<CharT, Traits>&
427 operator<<(std::basic_ostream<CharT, Traits>& os, const year& y);
428
429 // weekday
430
431 class weekday
432 {
433 unsigned char wd_;
434 public:
435 weekday() = default;
436 explicit CONSTCD11 weekday(unsigned wd) NOEXCEPT;
437 CONSTCD14 weekday(const sys_days& dp) NOEXCEPT;
438 CONSTCD14 explicit weekday(const local_days& dp) NOEXCEPT;
439
440 CONSTCD14 weekday& operator++() NOEXCEPT;
441 CONSTCD14 weekday operator++(int) NOEXCEPT;
442 CONSTCD14 weekday& operator--() NOEXCEPT;
443 CONSTCD14 weekday operator--(int) NOEXCEPT;
444
445 CONSTCD14 weekday& operator+=(const days& d) NOEXCEPT;
446 CONSTCD14 weekday& operator-=(const days& d) NOEXCEPT;
447
448 CONSTCD11 bool ok() const NOEXCEPT;
449
450 CONSTCD11 unsigned c_encoding() const NOEXCEPT;
451 CONSTCD11 unsigned iso_encoding() const NOEXCEPT;
452
453 CONSTCD11 weekday_indexed operator[](unsigned index) const NOEXCEPT;
454 CONSTCD11 weekday_last operator[](last_spec) const NOEXCEPT;
455
456 private:
457 static CONSTCD14 unsigned char weekday_from_days(int z) NOEXCEPT;
458
459 friend CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT;
460 friend CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT;
461 friend CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT;
462 template<class CharT, class Traits>
463 friend std::basic_ostream<CharT, Traits>&
464 operator<<(std::basic_ostream<CharT, Traits>& os, const weekday& wd);
465 friend class weekday_indexed;
466 };
467
468 CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT;
469 CONSTCD11 bool operator!=(const weekday& x, const weekday& y) NOEXCEPT;
470
471 CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT;
472 CONSTCD14 weekday operator+(const days& x, const weekday& y) NOEXCEPT;
473 CONSTCD14 weekday operator-(const weekday& x, const days& y) NOEXCEPT;
474 CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT;
475
476 template<class CharT, class Traits>
477 std::basic_ostream<CharT, Traits>&
478 operator<<(std::basic_ostream<CharT, Traits>& os, const weekday& wd);
479
480 // weekday_indexed
481
482 class weekday_indexed
483 {
484 unsigned char wd_ : 4;
485 unsigned char index_ : 4;
486
487 public:
488 weekday_indexed() = default;
489 CONSTCD11 weekday_indexed(const date::weekday& wd, unsigned index) NOEXCEPT;
490
491 CONSTCD11 date::weekday weekday() const NOEXCEPT;
492 CONSTCD11 unsigned index() const NOEXCEPT;
493 CONSTCD11 bool ok() const NOEXCEPT;
494 };
495
496 CONSTCD11 bool operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT;
497 CONSTCD11 bool operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT;
498
499 template<class CharT, class Traits>
500 std::basic_ostream<CharT, Traits>&
501 operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_indexed& wdi);
502
503 // weekday_last
504
505 class weekday_last
506 {
507 date::weekday wd_;
508
509 public:
510 explicit CONSTCD11 weekday_last(const date::weekday& wd) NOEXCEPT;
511
512 CONSTCD11 date::weekday weekday() const NOEXCEPT;
513 CONSTCD11 bool ok() const NOEXCEPT;
514 };
515
516 CONSTCD11 bool operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT;
517 CONSTCD11 bool operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT;
518
519 template<class CharT, class Traits>
520 std::basic_ostream<CharT, Traits>&
521 operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_last& wdl);
522
523 namespace detail
524 {
525
526 struct unspecified_month_disambiguator {};
527
528 } // namespace detail
529
530 // year_month
531
532 class year_month
533 {
534 date::year y_;
535 date::month m_;
536
537 public:
538 year_month() = default;
539 CONSTCD11 year_month(const date::year& y, const date::month& m) NOEXCEPT;
540
541 CONSTCD11 date::year year() const NOEXCEPT;
542 CONSTCD11 date::month month() const NOEXCEPT;
543
544 template<class = detail::unspecified_month_disambiguator>
545 CONSTCD14 year_month& operator+=(const months& dm) NOEXCEPT;
546 template<class = detail::unspecified_month_disambiguator>
547 CONSTCD14 year_month& operator-=(const months& dm) NOEXCEPT;
548 CONSTCD14 year_month& operator+=(const years& dy) NOEXCEPT;
549 CONSTCD14 year_month& operator-=(const years& dy) NOEXCEPT;
550
551 CONSTCD11 bool ok() const NOEXCEPT;
552 };
553
554 CONSTCD11 bool operator==(const year_month& x, const year_month& y) NOEXCEPT;
555 CONSTCD11 bool operator!=(const year_month& x, const year_month& y) NOEXCEPT;
556 CONSTCD11 bool operator< (const year_month& x, const year_month& y) NOEXCEPT;
557 CONSTCD11 bool operator> (const year_month& x, const year_month& y) NOEXCEPT;
558 CONSTCD11 bool operator<=(const year_month& x, const year_month& y) NOEXCEPT;
559 CONSTCD11 bool operator>=(const year_month& x, const year_month& y) NOEXCEPT;
560
561 template<class = detail::unspecified_month_disambiguator>
562 CONSTCD14 year_month operator+(const year_month& ym, const months& dm) NOEXCEPT;
563 template<class = detail::unspecified_month_disambiguator>
564 CONSTCD14 year_month operator+(const months& dm, const year_month& ym) NOEXCEPT;
565 template<class = detail::unspecified_month_disambiguator>
566 CONSTCD14 year_month operator-(const year_month& ym, const months& dm) NOEXCEPT;
567
568 CONSTCD11 months operator-(const year_month& x, const year_month& y) NOEXCEPT;
569 CONSTCD11 year_month operator+(const year_month& ym, const years& dy) NOEXCEPT;
570 CONSTCD11 year_month operator+(const years& dy, const year_month& ym) NOEXCEPT;
571 CONSTCD11 year_month operator-(const year_month& ym, const years& dy) NOEXCEPT;
572
573 template<class CharT, class Traits>
574 std::basic_ostream<CharT, Traits>&
575 operator<<(std::basic_ostream<CharT, Traits>& os, const year_month& ym);
576
577 // month_day
578
579 class month_day
580 {
581 date::month m_;
582 date::day d_;
583
584 public:
585 month_day() = default;
586 CONSTCD11 month_day(const date::month& m, const date::day& d) NOEXCEPT;
587
588 CONSTCD11 date::month month() const NOEXCEPT;
589 CONSTCD11 date::day day() const NOEXCEPT;
590
591 CONSTCD14 bool ok() const NOEXCEPT;
592 };
593
594 CONSTCD11 bool operator==(const month_day& x, const month_day& y) NOEXCEPT;
595 CONSTCD11 bool operator!=(const month_day& x, const month_day& y) NOEXCEPT;
596 CONSTCD11 bool operator< (const month_day& x, const month_day& y) NOEXCEPT;
597 CONSTCD11 bool operator> (const month_day& x, const month_day& y) NOEXCEPT;
598 CONSTCD11 bool operator<=(const month_day& x, const month_day& y) NOEXCEPT;
599 CONSTCD11 bool operator>=(const month_day& x, const month_day& y) NOEXCEPT;
600
601 template<class CharT, class Traits>
602 std::basic_ostream<CharT, Traits>&
603 operator<<(std::basic_ostream<CharT, Traits>& os, const month_day& md);
604
605 // month_day_last
606
607 class month_day_last
608 {
609 date::month m_;
610
611 public:
612 CONSTCD11 explicit month_day_last(const date::month& m) NOEXCEPT;
613
614 CONSTCD11 date::month month() const NOEXCEPT;
615 CONSTCD11 bool ok() const NOEXCEPT;
616 };
617
618 CONSTCD11 bool operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT;
619 CONSTCD11 bool operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT;
620 CONSTCD11 bool operator< (const month_day_last& x, const month_day_last& y) NOEXCEPT;
621 CONSTCD11 bool operator> (const month_day_last& x, const month_day_last& y) NOEXCEPT;
622 CONSTCD11 bool operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT;
623 CONSTCD11 bool operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT;
624
625 template<class CharT, class Traits>
626 std::basic_ostream<CharT, Traits>&
627 operator<<(std::basic_ostream<CharT, Traits>& os, const month_day_last& mdl);
628
629 // month_weekday
630
631 class month_weekday
632 {
633 date::month m_;
634 date::weekday_indexed wdi_;
635 public:
636 CONSTCD11 month_weekday(const date::month& m,
637 const date::weekday_indexed& wdi) NOEXCEPT;
638
639 CONSTCD11 date::month month() const NOEXCEPT;
640 CONSTCD11 date::weekday_indexed weekday_indexed() const NOEXCEPT;
641
642 CONSTCD11 bool ok() const NOEXCEPT;
643 };
644
645 CONSTCD11 bool operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT;
646 CONSTCD11 bool operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT;
647
648 template<class CharT, class Traits>
649 std::basic_ostream<CharT, Traits>&
650 operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday& mwd);
651
652 // month_weekday_last
653
654 class month_weekday_last
655 {
656 date::month m_;
657 date::weekday_last wdl_;
658
659 public:
660 CONSTCD11 month_weekday_last(const date::month& m,
661 const date::weekday_last& wd) NOEXCEPT;
662
663 CONSTCD11 date::month month() const NOEXCEPT;
664 CONSTCD11 date::weekday_last weekday_last() const NOEXCEPT;
665
666 CONSTCD11 bool ok() const NOEXCEPT;
667 };
668
669 CONSTCD11
670 bool operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT;
671 CONSTCD11
672 bool operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT;
673
674 template<class CharT, class Traits>
675 std::basic_ostream<CharT, Traits>&
676 operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday_last& mwdl);
677
678 // class year_month_day
679
680 class year_month_day
681 {
682 date::year y_;
683 date::month m_;
684 date::day d_;
685
686 public:
687 year_month_day() = default;
688 CONSTCD11 year_month_day(const date::year& y, const date::month& m,
689 const date::day& d) NOEXCEPT;
690 CONSTCD14 year_month_day(const year_month_day_last& ymdl) NOEXCEPT;
691
692 CONSTCD14 year_month_day(sys_days dp) NOEXCEPT;
693 CONSTCD14 explicit year_month_day(local_days dp) NOEXCEPT;
694
695 template<class = detail::unspecified_month_disambiguator>
696 CONSTCD14 year_month_day& operator+=(const months& m) NOEXCEPT;
697 template<class = detail::unspecified_month_disambiguator>
698 CONSTCD14 year_month_day& operator-=(const months& m) NOEXCEPT;
699 CONSTCD14 year_month_day& operator+=(const years& y) NOEXCEPT;
700 CONSTCD14 year_month_day& operator-=(const years& y) NOEXCEPT;
701
702 CONSTCD11 date::year year() const NOEXCEPT;
703 CONSTCD11 date::month month() const NOEXCEPT;
704 CONSTCD11 date::day day() const NOEXCEPT;
705
706 CONSTCD14 operator sys_days() const NOEXCEPT;
707 CONSTCD14 explicit operator local_days() const NOEXCEPT;
708 CONSTCD14 bool ok() const NOEXCEPT;
709
710 private:
711 static CONSTCD14 year_month_day from_days(days dp) NOEXCEPT;
712 CONSTCD14 days to_days() const NOEXCEPT;
713 };
714
715 CONSTCD11 bool operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT;
716 CONSTCD11 bool operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT;
717 CONSTCD11 bool operator< (const year_month_day& x, const year_month_day& y) NOEXCEPT;
718 CONSTCD11 bool operator> (const year_month_day& x, const year_month_day& y) NOEXCEPT;
719 CONSTCD11 bool operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT;
720 CONSTCD11 bool operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT;
721
722 template<class = detail::unspecified_month_disambiguator>
723 CONSTCD14 year_month_day operator+(const year_month_day& ymd, const months& dm) NOEXCEPT;
724 template<class = detail::unspecified_month_disambiguator>
725 CONSTCD14 year_month_day operator+(const months& dm, const year_month_day& ymd) NOEXCEPT;
726 template<class = detail::unspecified_month_disambiguator>
727 CONSTCD14 year_month_day operator-(const year_month_day& ymd, const months& dm) NOEXCEPT;
728 CONSTCD11 year_month_day operator+(const year_month_day& ymd, const years& dy) NOEXCEPT;
729 CONSTCD11 year_month_day operator+(const years& dy, const year_month_day& ymd) NOEXCEPT;
730 CONSTCD11 year_month_day operator-(const year_month_day& ymd, const years& dy) NOEXCEPT;
731
732 template<class CharT, class Traits>
733 std::basic_ostream<CharT, Traits>&
734 operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day& ymd);
735
736 // year_month_day_last
737
738 class year_month_day_last
739 {
740 date::year y_;
741 date::month_day_last mdl_;
742
743 public:
744 CONSTCD11 year_month_day_last(const date::year& y,
745 const date::month_day_last& mdl) NOEXCEPT;
746
747 template<class = detail::unspecified_month_disambiguator>
748 CONSTCD14 year_month_day_last& operator+=(const months& m) NOEXCEPT;
749 template<class = detail::unspecified_month_disambiguator>
750 CONSTCD14 year_month_day_last& operator-=(const months& m) NOEXCEPT;
751 CONSTCD14 year_month_day_last& operator+=(const years& y) NOEXCEPT;
752 CONSTCD14 year_month_day_last& operator-=(const years& y) NOEXCEPT;
753
754 CONSTCD11 date::year year() const NOEXCEPT;
755 CONSTCD11 date::month month() const NOEXCEPT;
756 CONSTCD11 date::month_day_last month_day_last() const NOEXCEPT;
757 CONSTCD14 date::day day() const NOEXCEPT;
758
759 CONSTCD14 operator sys_days() const NOEXCEPT;
760 CONSTCD14 explicit operator local_days() const NOEXCEPT;
761 CONSTCD11 bool ok() const NOEXCEPT;
762 };
763
764 CONSTCD11
765 bool operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
766 CONSTCD11
767 bool operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
768 CONSTCD11
769 bool operator< (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
770 CONSTCD11
771 bool operator> (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
772 CONSTCD11
773 bool operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
774 CONSTCD11
775 bool operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
776
777 template<class = detail::unspecified_month_disambiguator>
778 CONSTCD14
779 year_month_day_last
780 operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT;
781
782 template<class = detail::unspecified_month_disambiguator>
783 CONSTCD14
784 year_month_day_last
785 operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT;
786
787 CONSTCD11
788 year_month_day_last
789 operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT;
790
791 CONSTCD11
792 year_month_day_last
793 operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT;
794
795 template<class = detail::unspecified_month_disambiguator>
796 CONSTCD14
797 year_month_day_last
798 operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT;
799
800 CONSTCD11
801 year_month_day_last
802 operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT;
803
804 template<class CharT, class Traits>
805 std::basic_ostream<CharT, Traits>&
806 operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day_last& ymdl);
807
808 // year_month_weekday
809
810 class year_month_weekday
811 {
812 date::year y_;
813 date::month m_;
814 date::weekday_indexed wdi_;
815
816 public:
817 year_month_weekday() = default;
818 CONSTCD11 year_month_weekday(const date::year& y, const date::month& m,
819 const date::weekday_indexed& wdi) NOEXCEPT;
820 CONSTCD14 year_month_weekday(const sys_days& dp) NOEXCEPT;
821 CONSTCD14 explicit year_month_weekday(const local_days& dp) NOEXCEPT;
822
823 template<class = detail::unspecified_month_disambiguator>
824 CONSTCD14 year_month_weekday& operator+=(const months& m) NOEXCEPT;
825 template<class = detail::unspecified_month_disambiguator>
826 CONSTCD14 year_month_weekday& operator-=(const months& m) NOEXCEPT;
827 CONSTCD14 year_month_weekday& operator+=(const years& y) NOEXCEPT;
828 CONSTCD14 year_month_weekday& operator-=(const years& y) NOEXCEPT;
829
830 CONSTCD11 date::year year() const NOEXCEPT;
831 CONSTCD11 date::month month() const NOEXCEPT;
832 CONSTCD11 date::weekday weekday() const NOEXCEPT;
833 CONSTCD11 unsigned index() const NOEXCEPT;
834 CONSTCD11 date::weekday_indexed weekday_indexed() const NOEXCEPT;
835
836 CONSTCD14 operator sys_days() const NOEXCEPT;
837 CONSTCD14 explicit operator local_days() const NOEXCEPT;
838 CONSTCD14 bool ok() const NOEXCEPT;
839
840 private:
841 static CONSTCD14 year_month_weekday from_days(days dp) NOEXCEPT;
842 CONSTCD14 days to_days() const NOEXCEPT;
843 };
844
845 CONSTCD11
846 bool operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT;
847 CONSTCD11
848 bool operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT;
849
850 template<class = detail::unspecified_month_disambiguator>
851 CONSTCD14
852 year_month_weekday
853 operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT;
854
855 template<class = detail::unspecified_month_disambiguator>
856 CONSTCD14
857 year_month_weekday
858 operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT;
859
860 CONSTCD11
861 year_month_weekday
862 operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT;
863
864 CONSTCD11
865 year_month_weekday
866 operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT;
867
868 template<class = detail::unspecified_month_disambiguator>
869 CONSTCD14
870 year_month_weekday
871 operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT;
872
873 CONSTCD11
874 year_month_weekday
875 operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT;
876
877 template<class CharT, class Traits>
878 std::basic_ostream<CharT, Traits>&
879 operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday& ymwdi);
880
881 // year_month_weekday_last
882
883 class year_month_weekday_last
884 {
885 date::year y_;
886 date::month m_;
887 date::weekday_last wdl_;
888
889 public:
890 CONSTCD11 year_month_weekday_last(const date::year& y, const date::month& m,
891 const date::weekday_last& wdl) NOEXCEPT;
892
893 template<class = detail::unspecified_month_disambiguator>
894 CONSTCD14 year_month_weekday_last& operator+=(const months& m) NOEXCEPT;
895 template<class = detail::unspecified_month_disambiguator>
896 CONSTCD14 year_month_weekday_last& operator-=(const months& m) NOEXCEPT;
897 CONSTCD14 year_month_weekday_last& operator+=(const years& y) NOEXCEPT;
898 CONSTCD14 year_month_weekday_last& operator-=(const years& y) NOEXCEPT;
899
900 CONSTCD11 date::year year() const NOEXCEPT;
901 CONSTCD11 date::month month() const NOEXCEPT;
902 CONSTCD11 date::weekday weekday() const NOEXCEPT;
903 CONSTCD11 date::weekday_last weekday_last() const NOEXCEPT;
904
905 CONSTCD14 operator sys_days() const NOEXCEPT;
906 CONSTCD14 explicit operator local_days() const NOEXCEPT;
907 CONSTCD11 bool ok() const NOEXCEPT;
908
909 private:
910 CONSTCD14 days to_days() const NOEXCEPT;
911 };
912
913 CONSTCD11
914 bool
915 operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT;
916
917 CONSTCD11
918 bool
919 operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT;
920
921 template<class = detail::unspecified_month_disambiguator>
922 CONSTCD14
923 year_month_weekday_last
924 operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT;
925
926 template<class = detail::unspecified_month_disambiguator>
927 CONSTCD14
928 year_month_weekday_last
929 operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT;
930
931 CONSTCD11
932 year_month_weekday_last
933 operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT;
934
935 CONSTCD11
936 year_month_weekday_last
937 operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT;
938
939 template<class = detail::unspecified_month_disambiguator>
940 CONSTCD14
941 year_month_weekday_last
942 operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT;
943
944 CONSTCD11
945 year_month_weekday_last
946 operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT;
947
948 template<class CharT, class Traits>
949 std::basic_ostream<CharT, Traits>&
950 operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last& ymwdl);
951
952 #if !defined(_MSC_VER) || (_MSC_VER >= 1900)
953 inline namespace literals
954 {
955
956 CONSTCD11 date::day operator "" _d(unsigned long long d) NOEXCEPT;
957 CONSTCD11 date::year operator "" _y(unsigned long long y) NOEXCEPT;
958
959 } // inline namespace literals
960 #endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
961
962 // CONSTDATA date::month January{1};
963 // CONSTDATA date::month February{2};
964 // CONSTDATA date::month March{3};
965 // CONSTDATA date::month April{4};
966 // CONSTDATA date::month May{5};
967 // CONSTDATA date::month June{6};
968 // CONSTDATA date::month July{7};
969 // CONSTDATA date::month August{8};
970 // CONSTDATA date::month September{9};
971 // CONSTDATA date::month October{10};
972 // CONSTDATA date::month November{11};
973 // CONSTDATA date::month December{12};
974 //
975 // CONSTDATA date::weekday Sunday{0u};
976 // CONSTDATA date::weekday Monday{1u};
977 // CONSTDATA date::weekday Tuesday{2u};
978 // CONSTDATA date::weekday Wednesday{3u};
979 // CONSTDATA date::weekday Thursday{4u};
980 // CONSTDATA date::weekday Friday{5u};
981 // CONSTDATA date::weekday Saturday{6u};
982
983 #if HAS_VOID_T
984
985 template <class T, class = std::void_t<>>
986 struct is_clock
987 : std::false_type
988 {};
989
990 template <class T>
991 struct is_clock<T, std::void_t<decltype(T::now()), typename T::rep, typename T::period,
992 typename T::duration, typename T::time_point,
993 decltype(T::is_steady)>>
994 : std::true_type
995 {};
996
997 #endif // HAS_VOID_T
998
999 //----------------+
1000 // Implementation |
1001 //----------------+
1002
1003 // utilities
1004 namespace detail {
1005
1006 template<class CharT, class Traits = std::char_traits<CharT>>
1007 class save_istream
1008 {
1009 protected:
1010 std::basic_ios<CharT, Traits>& is_;
1011 CharT fill_;
1012 std::ios::fmtflags flags_;
1013 std::streamsize width_;
1014 std::basic_ostream<CharT, Traits>* tie_;
1015 std::locale loc_;
1016
1017 public:
1018 ~save_istream()
1019 {
1020 is_.fill(fill_);
1021 is_.flags(flags_);
1022 is_.width(width_);
1023 is_.imbue(loc_);
1024 is_.tie(tie_);
1025 }
1026
1027 save_istream(const save_istream&) = delete;
1028 save_istream& operator=(const save_istream&) = delete;
1029
1030 explicit save_istream(std::basic_ios<CharT, Traits>& is)
1031 : is_(is)
1032 , fill_(is.fill())
1033 , flags_(is.flags())
1034 , width_(is.width(0))
1035 , tie_(is.tie(nullptr))
1036 , loc_(is.getloc())
1037 {
1038 if (tie_ != nullptr)
1039 tie_->flush();
1040 }
1041 };
1042
1043 template<class CharT, class Traits = std::char_traits<CharT>>
1044 class save_ostream
1045 : private save_istream<CharT, Traits>
1046 {
1047 public:
1048 ~save_ostream()
1049 {
1050 if ((this->flags_ & std::ios::unitbuf) &&
1051 #if HAS_UNCAUGHT_EXCEPTIONS
1052 std::uncaught_exceptions() == 0 &&
1053 #else
1054 !std::uncaught_exception() &&
1055 #endif
1056 this->is_.good())
1057 this->is_.rdbuf()->pubsync();
1058 }
1059
1060 save_ostream(const save_ostream&) = delete;
1061 save_ostream& operator=(const save_ostream&) = delete;
1062
1063 explicit save_ostream(std::basic_ios<CharT, Traits>& os)
1064 : save_istream<CharT, Traits>(os)
1065 {
1066 }
1067 };
1068
1069 template <class T>
1070 struct choose_trunc_type
1071 {
1072 static const int digits = std::numeric_limits<T>::digits;
1073 using type = typename std::conditional
1074 <
1075 digits < 32,
1076 std::int32_t,
1077 typename std::conditional
1078 <
1079 digits < 64,
1080 std::int64_t,
1081 #ifdef __SIZEOF_INT128__
1082 __int128
1083 #else
1084 std::int64_t
1085 #endif
1086 >::type
1087 >::type;
1088 };
1089
1090 template <class T>
1091 CONSTCD11
1092 inline
1093 typename std::enable_if
1094 <
1095 !std::chrono::treat_as_floating_point<T>::value,
1096 T
1097 >::type
1098 trunc(T t) NOEXCEPT
1099 {
1100 return t;
1101 }
1102
1103 template <class T>
1104 CONSTCD14
1105 inline
1106 typename std::enable_if
1107 <
1108 std::chrono::treat_as_floating_point<T>::value,
1109 T
1110 >::type
1111 trunc(T t) NOEXCEPT
1112 {
1113 using std::numeric_limits;
1114 using I = typename choose_trunc_type<T>::type;
1115 CONSTDATA auto digits = numeric_limits<T>::digits;
1116 static_assert(digits < numeric_limits<I>::digits, "");
1117 CONSTDATA auto max = I{1} << (digits-1);
1118 CONSTDATA auto min = -max;
1119 const auto negative = t < T{0};
1120 if (min <= t && t <= max && t != 0 && t == t)
1121 {
1122 t = static_cast<T>(static_cast<I>(t));
1123 if (t == 0 && negative)
1124 t = -t;
1125 }
1126 return t;
1127 }
1128
1129 template <std::intmax_t Xp, std::intmax_t Yp>
1130 struct static_gcd
1131 {
1132 static const std::intmax_t value = static_gcd<Yp, Xp % Yp>::value;
1133 };
1134
1135 template <std::intmax_t Xp>
1136 struct static_gcd<Xp, 0>
1137 {
1138 static const std::intmax_t value = Xp;
1139 };
1140
1141 template <>
1142 struct static_gcd<0, 0>
1143 {
1144 static const std::intmax_t value = 1;
1145 };
1146
1147 template <class R1, class R2>
1148 struct no_overflow
1149 {
1150 private:
1151 static const std::intmax_t gcd_n1_n2 = static_gcd<R1::num, R2::num>::value;
1152 static const std::intmax_t gcd_d1_d2 = static_gcd<R1::den, R2::den>::value;
1153 static const std::intmax_t n1 = R1::num / gcd_n1_n2;
1154 static const std::intmax_t d1 = R1::den / gcd_d1_d2;
1155 static const std::intmax_t n2 = R2::num / gcd_n1_n2;
1156 static const std::intmax_t d2 = R2::den / gcd_d1_d2;
1157 static const std::intmax_t max = INTMAX_MAX;
1158
1159 template <std::intmax_t Xp, std::intmax_t Yp, bool overflow>
1160 struct mul // overflow == false
1161 {
1162 static const std::intmax_t value = Xp * Yp;
1163 };
1164
1165 template <std::intmax_t Xp, std::intmax_t Yp>
1166 struct mul<Xp, Yp, true>
1167 {
1168 static const std::intmax_t value = 1;
1169 };
1170
1171 public:
1172 static const bool value = (n1 <= max / d2) && (n2 <= max / d1);
1173 typedef std::ratio<mul<n1, d2, !value>::value,
1174 mul<n2, d1, !value>::value> type;
1175 };
1176
1177 } // detail
1178
1179 // trunc towards zero
1180 template <class To, class Rep, class Period>
1181 CONSTCD11
1182 inline
1183 typename std::enable_if
1184 <
1185 detail::no_overflow<Period, typename To::period>::value,
1186 To
1187 >::type
1188 trunc(const std::chrono::duration<Rep, Period>& d)
1189 {
1190 return To{detail::trunc(std::chrono::duration_cast<To>(d).count())};
1191 }
1192
1193 template <class To, class Rep, class Period>
1194 CONSTCD11
1195 inline
1196 typename std::enable_if
1197 <
1198 !detail::no_overflow<Period, typename To::period>::value,
1199 To
1200 >::type
1201 trunc(const std::chrono::duration<Rep, Period>& d)
1202 {
1203 using std::chrono::duration_cast;
1204 using std::chrono::duration;
1205 using rep = typename std::common_type<Rep, typename To::rep>::type;
1206 return To{detail::trunc(duration_cast<To>(duration_cast<duration<rep>>(d)).count())};
1207 }
1208
1209 #ifndef HAS_CHRONO_ROUNDING
1210 # if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023918 || (_MSC_FULL_VER >= 190000000 && defined (__clang__)))
1211 # define HAS_CHRONO_ROUNDING 1
1212 # elif defined(__cpp_lib_chrono) && __cplusplus > 201402 && __cpp_lib_chrono >= 201510
1213 # define HAS_CHRONO_ROUNDING 1
1214 # elif defined(_LIBCPP_VERSION) && __cplusplus > 201402 && _LIBCPP_VERSION >= 3800
1215 # define HAS_CHRONO_ROUNDING 1
1216 # else
1217 # define HAS_CHRONO_ROUNDING 0
1218 # endif
1219 #endif // HAS_CHRONO_ROUNDING
1220
1221 #if HAS_CHRONO_ROUNDING == 0
1222
1223 // round down
1224 template <class To, class Rep, class Period>
1225 CONSTCD14
1226 inline
1227 typename std::enable_if
1228 <
1229 detail::no_overflow<Period, typename To::period>::value,
1230 To
1231 >::type
1232 floor(const std::chrono::duration<Rep, Period>& d)
1233 {
1234 auto t = trunc<To>(d);
1235 if (t > d)
1236 return t - To{1};
1237 return t;
1238 }
1239
1240 template <class To, class Rep, class Period>
1241 CONSTCD14
1242 inline
1243 typename std::enable_if
1244 <
1245 !detail::no_overflow<Period, typename To::period>::value,
1246 To
1247 >::type
1248 floor(const std::chrono::duration<Rep, Period>& d)
1249 {
1250 using rep = typename std::common_type<Rep, typename To::rep>::type;
1251 return floor<To>(floor<std::chrono::duration<rep>>(d));
1252 }
1253
1254 // round to nearest, to even on tie
1255 template <class To, class Rep, class Period>
1256 CONSTCD14
1257 inline
1258 To
1259 round(const std::chrono::duration<Rep, Period>& d)
1260 {
1261 auto t0 = floor<To>(d);
1262 auto t1 = t0 + To{1};
1263 if (t1 == To{0} && t0 < To{0})
1264 t1 = -t1;
1265 auto diff0 = d - t0;
1266 auto diff1 = t1 - d;
1267 if (diff0 == diff1)
1268 {
1269 if (t0 - trunc<To>(t0/2)*2 == To{0})
1270 return t0;
1271 return t1;
1272 }
1273 if (diff0 < diff1)
1274 return t0;
1275 return t1;
1276 }
1277
1278 // round up
1279 template <class To, class Rep, class Period>
1280 CONSTCD14
1281 inline
1282 To
1283 ceil(const std::chrono::duration<Rep, Period>& d)
1284 {
1285 auto t = trunc<To>(d);
1286 if (t < d)
1287 return t + To{1};
1288 return t;
1289 }
1290
1291 template <class Rep, class Period,
1292 class = typename std::enable_if
1293 <
1294 std::numeric_limits<Rep>::is_signed
1295 >::type>
1296 CONSTCD11
1297 std::chrono::duration<Rep, Period>
1298 abs(std::chrono::duration<Rep, Period> d)
1299 {
1300 return d >= d.zero() ? d : -d;
1301 }
1302
1303 // round down
1304 template <class To, class Clock, class FromDuration>
1305 CONSTCD11
1306 inline
1307 std::chrono::time_point<Clock, To>
1308 floor(const std::chrono::time_point<Clock, FromDuration>& tp)
1309 {
1310 using std::chrono::time_point;
1311 return time_point<Clock, To>{date::floor<To>(tp.time_since_epoch())};
1312 }
1313
1314 // round to nearest, to even on tie
1315 template <class To, class Clock, class FromDuration>
1316 CONSTCD11
1317 inline
1318 std::chrono::time_point<Clock, To>
1319 round(const std::chrono::time_point<Clock, FromDuration>& tp)
1320 {
1321 using std::chrono::time_point;
1322 return time_point<Clock, To>{round<To>(tp.time_since_epoch())};
1323 }
1324
1325 // round up
1326 template <class To, class Clock, class FromDuration>
1327 CONSTCD11
1328 inline
1329 std::chrono::time_point<Clock, To>
1330 ceil(const std::chrono::time_point<Clock, FromDuration>& tp)
1331 {
1332 using std::chrono::time_point;
1333 return time_point<Clock, To>{ceil<To>(tp.time_since_epoch())};
1334 }
1335
1336 #else // HAS_CHRONO_ROUNDING == 1
1337
1338 using std::chrono::floor;
1339 using std::chrono::ceil;
1340 using std::chrono::round;
1341 using std::chrono::abs;
1342
1343 #endif // HAS_CHRONO_ROUNDING
1344
1345 // trunc towards zero
1346 template <class To, class Clock, class FromDuration>
1347 CONSTCD11
1348 inline
1349 std::chrono::time_point<Clock, To>
1350 trunc(const std::chrono::time_point<Clock, FromDuration>& tp)
1351 {
1352 using std::chrono::time_point;
1353 return time_point<Clock, To>{trunc<To>(tp.time_since_epoch())};
1354 }
1355
1356 // day
1357
1358 CONSTCD11 inline day::day(unsigned d) NOEXCEPT : d_(static_cast<unsigned char>(d)) {}
1359 CONSTCD14 inline day& day::operator++() NOEXCEPT {++d_; return *this;}
1360 CONSTCD14 inline day day::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
1361 CONSTCD14 inline day& day::operator--() NOEXCEPT {--d_; return *this;}
1362 CONSTCD14 inline day day::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
1363 CONSTCD14 inline day& day::operator+=(const days& d) NOEXCEPT {*this = *this + d; return *this;}
1364 CONSTCD14 inline day& day::operator-=(const days& d) NOEXCEPT {*this = *this - d; return *this;}
1365 CONSTCD11 inline day::operator unsigned() const NOEXCEPT {return d_;}
1366 CONSTCD11 inline bool day::ok() const NOEXCEPT {return 1 <= d_ && d_ <= 31;}
1367
1368 CONSTCD11
1369 inline
1370 bool
1371 operator==(const day& x, const day& y) NOEXCEPT
1372 {
1373 return static_cast<unsigned>(x) == static_cast<unsigned>(y);
1374 }
1375
1376 CONSTCD11
1377 inline
1378 bool
1379 operator!=(const day& x, const day& y) NOEXCEPT
1380 {
1381 return !(x == y);
1382 }
1383
1384 CONSTCD11
1385 inline
1386 bool
1387 operator<(const day& x, const day& y) NOEXCEPT
1388 {
1389 return static_cast<unsigned>(x) < static_cast<unsigned>(y);
1390 }
1391
1392 CONSTCD11
1393 inline
1394 bool
1395 operator>(const day& x, const day& y) NOEXCEPT
1396 {
1397 return y < x;
1398 }
1399
1400 CONSTCD11
1401 inline
1402 bool
1403 operator<=(const day& x, const day& y) NOEXCEPT
1404 {
1405 return !(y < x);
1406 }
1407
1408 CONSTCD11
1409 inline
1410 bool
1411 operator>=(const day& x, const day& y) NOEXCEPT
1412 {
1413 return !(x < y);
1414 }
1415
1416 CONSTCD11
1417 inline
1418 days
1419 operator-(const day& x, const day& y) NOEXCEPT
1420 {
1421 return days{static_cast<days::rep>(static_cast<unsigned>(x)
1422 - static_cast<unsigned>(y))};
1423 }
1424
1425 CONSTCD11
1426 inline
1427 day
1428 operator+(const day& x, const days& y) NOEXCEPT
1429 {
1430 return day{static_cast<unsigned>(x) + static_cast<unsigned>(y.count())};
1431 }
1432
1433 CONSTCD11
1434 inline
1435 day
1436 operator+(const days& x, const day& y) NOEXCEPT
1437 {
1438 return y + x;
1439 }
1440
1441 CONSTCD11
1442 inline
1443 day
1444 operator-(const day& x, const days& y) NOEXCEPT
1445 {
1446 return x + -y;
1447 }
1448
1449 template<class CharT, class Traits>
1450 inline
1451 std::basic_ostream<CharT, Traits>&
1452 operator<<(std::basic_ostream<CharT, Traits>& os, const day& d)
1453 {
1454 detail::save_ostream<CharT, Traits> _(os);
1455 os.fill('0');
1456 os.flags(std::ios::dec | std::ios::right);
1457 os.width(2);
1458 os << static_cast<unsigned>(d);
1459 if (!d.ok())
1460 os << " is not a valid day";
1461 return os;
1462 }
1463
1464 // month
1465
1466 CONSTCD11 inline month::month(unsigned m) NOEXCEPT : m_(static_cast<decltype(m_)>(m)) {}
1467 CONSTCD14 inline month& month::operator++() NOEXCEPT {*this += months{1}; return *this;}
1468 CONSTCD14 inline month month::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
1469 CONSTCD14 inline month& month::operator--() NOEXCEPT {*this -= months{1}; return *this;}
1470 CONSTCD14 inline month month::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
1471
1472 CONSTCD14
1473 inline
1474 month&
1475 month::operator+=(const months& m) NOEXCEPT
1476 {
1477 *this = *this + m;
1478 return *this;
1479 }
1480
1481 CONSTCD14
1482 inline
1483 month&
1484 month::operator-=(const months& m) NOEXCEPT
1485 {
1486 *this = *this - m;
1487 return *this;
1488 }
1489
1490 CONSTCD11 inline month::operator unsigned() const NOEXCEPT {return m_;}
1491 CONSTCD11 inline bool month::ok() const NOEXCEPT {return 1 <= m_ && m_ <= 12;}
1492
1493 CONSTCD11
1494 inline
1495 bool
1496 operator==(const month& x, const month& y) NOEXCEPT
1497 {
1498 return static_cast<unsigned>(x) == static_cast<unsigned>(y);
1499 }
1500
1501 CONSTCD11
1502 inline
1503 bool
1504 operator!=(const month& x, const month& y) NOEXCEPT
1505 {
1506 return !(x == y);
1507 }
1508
1509 CONSTCD11
1510 inline
1511 bool
1512 operator<(const month& x, const month& y) NOEXCEPT
1513 {
1514 return static_cast<unsigned>(x) < static_cast<unsigned>(y);
1515 }
1516
1517 CONSTCD11
1518 inline
1519 bool
1520 operator>(const month& x, const month& y) NOEXCEPT
1521 {
1522 return y < x;
1523 }
1524
1525 CONSTCD11
1526 inline
1527 bool
1528 operator<=(const month& x, const month& y) NOEXCEPT
1529 {
1530 return !(y < x);
1531 }
1532
1533 CONSTCD11
1534 inline
1535 bool
1536 operator>=(const month& x, const month& y) NOEXCEPT
1537 {
1538 return !(x < y);
1539 }
1540
1541 CONSTCD14
1542 inline
1543 months
1544 operator-(const month& x, const month& y) NOEXCEPT
1545 {
1546 auto const d = static_cast<unsigned>(x) - static_cast<unsigned>(y);
1547 return months(d <= 11 ? d : d + 12);
1548 }
1549
1550 CONSTCD14
1551 inline
1552 month
1553 operator+(const month& x, const months& y) NOEXCEPT
1554 {
1555 auto const mu = static_cast<long long>(static_cast<unsigned>(x)) + (y.count() - 1);
1556 auto const yr = (mu >= 0 ? mu : mu-11) / 12;
1557 return month{static_cast<unsigned>(mu - yr * 12 + 1)};
1558 }
1559
1560 CONSTCD14
1561 inline
1562 month
1563 operator+(const months& x, const month& y) NOEXCEPT
1564 {
1565 return y + x;
1566 }
1567
1568 CONSTCD14
1569 inline
1570 month
1571 operator-(const month& x, const months& y) NOEXCEPT
1572 {
1573 return x + -y;
1574 }
1575
1576 template<class CharT, class Traits>
1577 inline
1578 std::basic_ostream<CharT, Traits>&
1579 operator<<(std::basic_ostream<CharT, Traits>& os, const month& m)
1580 {
1581 if (m.ok())
1582 {
1583 CharT fmt[] = {'%', 'b', 0};
1584 os << format(os.getloc(), fmt, m);
1585 }
1586 else
1587 os << static_cast<unsigned>(m) << " is not a valid month";
1588 return os;
1589 }
1590
1591 // year
1592
1593 CONSTCD11 inline year::year(int y) NOEXCEPT : y_(static_cast<decltype(y_)>(y)) {}
1594 CONSTCD14 inline year& year::operator++() NOEXCEPT {++y_; return *this;}
1595 CONSTCD14 inline year year::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
1596 CONSTCD14 inline year& year::operator--() NOEXCEPT {--y_; return *this;}
1597 CONSTCD14 inline year year::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
1598 CONSTCD14 inline year& year::operator+=(const years& y) NOEXCEPT {*this = *this + y; return *this;}
1599 CONSTCD14 inline year& year::operator-=(const years& y) NOEXCEPT {*this = *this - y; return *this;}
1600 CONSTCD11 inline year year::operator-() const NOEXCEPT {return year{-y_};}
1601 CONSTCD11 inline year year::operator+() const NOEXCEPT {return *this;}
1602
1603 CONSTCD11
1604 inline
1605 bool
1606 year::is_leap() const NOEXCEPT
1607 {
1608 return y_ % 4 == 0 && (y_ % 100 != 0 || y_ % 400 == 0);
1609 }
1610
1611 CONSTCD11 inline year::operator int() const NOEXCEPT {return y_;}
1612
1613 CONSTCD11
1614 inline
1615 bool
1616 year::ok() const NOEXCEPT
1617 {
1618 return y_ != std::numeric_limits<short>::min();
1619 }
1620
1621 CONSTCD11
1622 inline
1623 bool
1624 operator==(const year& x, const year& y) NOEXCEPT
1625 {
1626 return static_cast<int>(x) == static_cast<int>(y);
1627 }
1628
1629 CONSTCD11
1630 inline
1631 bool
1632 operator!=(const year& x, const year& y) NOEXCEPT
1633 {
1634 return !(x == y);
1635 }
1636
1637 CONSTCD11
1638 inline
1639 bool
1640 operator<(const year& x, const year& y) NOEXCEPT
1641 {
1642 return static_cast<int>(x) < static_cast<int>(y);
1643 }
1644
1645 CONSTCD11
1646 inline
1647 bool
1648 operator>(const year& x, const year& y) NOEXCEPT
1649 {
1650 return y < x;
1651 }
1652
1653 CONSTCD11
1654 inline
1655 bool
1656 operator<=(const year& x, const year& y) NOEXCEPT
1657 {
1658 return !(y < x);
1659 }
1660
1661 CONSTCD11
1662 inline
1663 bool
1664 operator>=(const year& x, const year& y) NOEXCEPT
1665 {
1666 return !(x < y);
1667 }
1668
1669 CONSTCD11
1670 inline
1671 years
1672 operator-(const year& x, const year& y) NOEXCEPT
1673 {
1674 return years{static_cast<int>(x) - static_cast<int>(y)};
1675 }
1676
1677 CONSTCD11
1678 inline
1679 year
1680 operator+(const year& x, const years& y) NOEXCEPT
1681 {
1682 return year{static_cast<int>(x) + y.count()};
1683 }
1684
1685 CONSTCD11
1686 inline
1687 year
1688 operator+(const years& x, const year& y) NOEXCEPT
1689 {
1690 return y + x;
1691 }
1692
1693 CONSTCD11
1694 inline
1695 year
1696 operator-(const year& x, const years& y) NOEXCEPT
1697 {
1698 return year{static_cast<int>(x) - y.count()};
1699 }
1700
1701 template<class CharT, class Traits>
1702 inline
1703 std::basic_ostream<CharT, Traits>&
1704 operator<<(std::basic_ostream<CharT, Traits>& os, const year& y)
1705 {
1706 detail::save_ostream<CharT, Traits> _(os);
1707 os.fill('0');
1708 os.flags(std::ios::dec | std::ios::internal);
1709 os.width(4 + (y < year{0}));
1710 os.imbue(std::locale::classic());
1711 os << static_cast<int>(y);
1712 if (!y.ok())
1713 os << " is not a valid year";
1714 return os;
1715 }
1716
1717 // weekday
1718
1719 CONSTCD14
1720 inline
1721 unsigned char
1722 weekday::weekday_from_days(int z) NOEXCEPT
1723 {
1724 auto u = static_cast<unsigned>(z);
1725 return static_cast<unsigned char>(z >= -4 ? (u+4) % 7 : u % 7);
1726 }
1727
1728 CONSTCD11
1729 inline
1730 weekday::weekday(unsigned wd) NOEXCEPT
1731 : wd_(static_cast<decltype(wd_)>(wd != 7 ? wd : 0))
1732 {}
1733
1734 CONSTCD14
1735 inline
1736 weekday::weekday(const sys_days& dp) NOEXCEPT
1737 : wd_(weekday_from_days(dp.time_since_epoch().count()))
1738 {}
1739
1740 CONSTCD14
1741 inline
1742 weekday::weekday(const local_days& dp) NOEXCEPT
1743 : wd_(weekday_from_days(dp.time_since_epoch().count()))
1744 {}
1745
1746 CONSTCD14 inline weekday& weekday::operator++() NOEXCEPT {*this += days{1}; return *this;}
1747 CONSTCD14 inline weekday weekday::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
1748 CONSTCD14 inline weekday& weekday::operator--() NOEXCEPT {*this -= days{1}; return *this;}
1749 CONSTCD14 inline weekday weekday::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
1750
1751 CONSTCD14
1752 inline
1753 weekday&
1754 weekday::operator+=(const days& d) NOEXCEPT
1755 {
1756 *this = *this + d;
1757 return *this;
1758 }
1759
1760 CONSTCD14
1761 inline
1762 weekday&
1763 weekday::operator-=(const days& d) NOEXCEPT
1764 {
1765 *this = *this - d;
1766 return *this;
1767 }
1768
1769 CONSTCD11 inline bool weekday::ok() const NOEXCEPT {return wd_ <= 6;}
1770
1771 CONSTCD11
1772 inline
1773 unsigned weekday::c_encoding() const NOEXCEPT
1774 {
1775 return unsigned{wd_};
1776 }
1777
1778 CONSTCD11
1779 inline
1780 unsigned weekday::iso_encoding() const NOEXCEPT
1781 {
1782 return unsigned{((wd_ == 0u) ? 7u : wd_)};
1783 }
1784
1785 CONSTCD11
1786 inline
1787 bool
1788 operator==(const weekday& x, const weekday& y) NOEXCEPT
1789 {
1790 return x.wd_ == y.wd_;
1791 }
1792
1793 CONSTCD11
1794 inline
1795 bool
1796 operator!=(const weekday& x, const weekday& y) NOEXCEPT
1797 {
1798 return !(x == y);
1799 }
1800
1801 CONSTCD14
1802 inline
1803 days
1804 operator-(const weekday& x, const weekday& y) NOEXCEPT
1805 {
1806 auto const wdu = x.wd_ - y.wd_;
1807 auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7;
1808 return days{wdu - wk * 7};
1809 }
1810
1811 CONSTCD14
1812 inline
1813 weekday
1814 operator+(const weekday& x, const days& y) NOEXCEPT
1815 {
1816 auto const wdu = static_cast<long long>(static_cast<unsigned>(x.wd_)) + y.count();
1817 auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7;
1818 return weekday{static_cast<unsigned>(wdu - wk * 7)};
1819 }
1820
1821 CONSTCD14
1822 inline
1823 weekday
1824 operator+(const days& x, const weekday& y) NOEXCEPT
1825 {
1826 return y + x;
1827 }
1828
1829 CONSTCD14
1830 inline
1831 weekday
1832 operator-(const weekday& x, const days& y) NOEXCEPT
1833 {
1834 return x + -y;
1835 }
1836
1837 template<class CharT, class Traits>
1838 inline
1839 std::basic_ostream<CharT, Traits>&
1840 operator<<(std::basic_ostream<CharT, Traits>& os, const weekday& wd)
1841 {
1842 if (wd.ok())
1843 {
1844 CharT fmt[] = {'%', 'a', 0};
1845 os << format(fmt, wd);
1846 }
1847 else
1848 os << static_cast<unsigned>(wd.wd_) << " is not a valid weekday";
1849 return os;
1850 }
1851
1852 #if !defined(_MSC_VER) || (_MSC_VER >= 1900)
1853 inline namespace literals
1854 {
1855
1856 CONSTCD11
1857 inline
1858 date::day
1859 operator "" _d(unsigned long long d) NOEXCEPT
1860 {
1861 return date::day{static_cast<unsigned>(d)};
1862 }
1863
1864 CONSTCD11
1865 inline
1866 date::year
1867 operator "" _y(unsigned long long y) NOEXCEPT
1868 {
1869 return date::year(static_cast<int>(y));
1870 }
1871 #endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
1872
1873 CONSTDATA date::last_spec last{};
1874
1875 CONSTDATA date::month jan{1};
1876 CONSTDATA date::month feb{2};
1877 CONSTDATA date::month mar{3};
1878 CONSTDATA date::month apr{4};
1879 CONSTDATA date::month may{5};
1880 CONSTDATA date::month jun{6};
1881 CONSTDATA date::month jul{7};
1882 CONSTDATA date::month aug{8};
1883 CONSTDATA date::month sep{9};
1884 CONSTDATA date::month oct{10};
1885 CONSTDATA date::month nov{11};
1886 CONSTDATA date::month dec{12};
1887
1888 CONSTDATA date::weekday sun{0u};
1889 CONSTDATA date::weekday mon{1u};
1890 CONSTDATA date::weekday tue{2u};
1891 CONSTDATA date::weekday wed{3u};
1892 CONSTDATA date::weekday thu{4u};
1893 CONSTDATA date::weekday fri{5u};
1894 CONSTDATA date::weekday sat{6u};
1895
1896 #if !defined(_MSC_VER) || (_MSC_VER >= 1900)
1897 } // inline namespace literals
1898 #endif
1899
1900 CONSTDATA date::month January{1};
1901 CONSTDATA date::month February{2};
1902 CONSTDATA date::month March{3};
1903 CONSTDATA date::month April{4};
1904 CONSTDATA date::month May{5};
1905 CONSTDATA date::month June{6};
1906 CONSTDATA date::month July{7};
1907 CONSTDATA date::month August{8};
1908 CONSTDATA date::month September{9};
1909 CONSTDATA date::month October{10};
1910 CONSTDATA date::month November{11};
1911 CONSTDATA date::month December{12};
1912
1913 CONSTDATA date::weekday Monday{1};
1914 CONSTDATA date::weekday Tuesday{2};
1915 CONSTDATA date::weekday Wednesday{3};
1916 CONSTDATA date::weekday Thursday{4};
1917 CONSTDATA date::weekday Friday{5};
1918 CONSTDATA date::weekday Saturday{6};
1919 CONSTDATA date::weekday Sunday{7};
1920
1921 // weekday_indexed
1922
1923 CONSTCD11
1924 inline
1925 weekday
1926 weekday_indexed::weekday() const NOEXCEPT
1927 {
1928 return date::weekday{static_cast<unsigned>(wd_)};
1929 }
1930
1931 CONSTCD11 inline unsigned weekday_indexed::index() const NOEXCEPT {return index_;}
1932
1933 CONSTCD11
1934 inline
1935 bool
1936 weekday_indexed::ok() const NOEXCEPT
1937 {
1938 return weekday().ok() && 1 <= index_ && index_ <= 5;
1939 }
1940
1941 #ifdef __GNUC__
1942 # pragma GCC diagnostic push
1943 # pragma GCC diagnostic ignored "-Wconversion"
1944 #endif // __GNUC__
1945
1946 CONSTCD11
1947 inline
1948 weekday_indexed::weekday_indexed(const date::weekday& wd, unsigned index) NOEXCEPT
1949 : wd_(static_cast<decltype(wd_)>(static_cast<unsigned>(wd.wd_)))
1950 , index_(static_cast<decltype(index_)>(index))
1951 {}
1952
1953 #ifdef __GNUC__
1954 # pragma GCC diagnostic pop
1955 #endif // __GNUC__
1956
1957 template<class CharT, class Traits>
1958 inline
1959 std::basic_ostream<CharT, Traits>&
1960 operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_indexed& wdi)
1961 {
1962 os << wdi.weekday() << '[' << wdi.index();
1963 if (!(1 <= wdi.index() && wdi.index() <= 5))
1964 os << " is not a valid index";
1965 os << ']';
1966 return os;
1967 }
1968
1969 CONSTCD11
1970 inline
1971 weekday_indexed
1972 weekday::operator[](unsigned index) const NOEXCEPT
1973 {
1974 return {*this, index};
1975 }
1976
1977 CONSTCD11
1978 inline
1979 bool
1980 operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT
1981 {
1982 return x.weekday() == y.weekday() && x.index() == y.index();
1983 }
1984
1985 CONSTCD11
1986 inline
1987 bool
1988 operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT
1989 {
1990 return !(x == y);
1991 }
1992
1993 // weekday_last
1994
1995 CONSTCD11 inline date::weekday weekday_last::weekday() const NOEXCEPT {return wd_;}
1996 CONSTCD11 inline bool weekday_last::ok() const NOEXCEPT {return wd_.ok();}
1997 CONSTCD11 inline weekday_last::weekday_last(const date::weekday& wd) NOEXCEPT : wd_(wd) {}
1998
1999 CONSTCD11
2000 inline
2001 bool
2002 operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT
2003 {
2004 return x.weekday() == y.weekday();
2005 }
2006
2007 CONSTCD11
2008 inline
2009 bool
2010 operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT
2011 {
2012 return !(x == y);
2013 }
2014
2015 template<class CharT, class Traits>
2016 inline
2017 std::basic_ostream<CharT, Traits>&
2018 operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_last& wdl)
2019 {
2020 return os << wdl.weekday() << "[last]";
2021 }
2022
2023 CONSTCD11
2024 inline
2025 weekday_last
2026 weekday::operator[](last_spec) const NOEXCEPT
2027 {
2028 return weekday_last{*this};
2029 }
2030
2031 // year_month
2032
2033 CONSTCD11
2034 inline
2035 year_month::year_month(const date::year& y, const date::month& m) NOEXCEPT
2036 : y_(y)
2037 , m_(m)
2038 {}
2039
2040 CONSTCD11 inline year year_month::year() const NOEXCEPT {return y_;}
2041 CONSTCD11 inline month year_month::month() const NOEXCEPT {return m_;}
2042 CONSTCD11 inline bool year_month::ok() const NOEXCEPT {return y_.ok() && m_.ok();}
2043
2044 template<class>
2045 CONSTCD14
2046 inline
2047 year_month&
2048 year_month::operator+=(const months& dm) NOEXCEPT
2049 {
2050 *this = *this + dm;
2051 return *this;
2052 }
2053
2054 template<class>
2055 CONSTCD14
2056 inline
2057 year_month&
2058 year_month::operator-=(const months& dm) NOEXCEPT
2059 {
2060 *this = *this - dm;
2061 return *this;
2062 }
2063
2064 CONSTCD14
2065 inline
2066 year_month&
2067 year_month::operator+=(const years& dy) NOEXCEPT
2068 {
2069 *this = *this + dy;
2070 return *this;
2071 }
2072
2073 CONSTCD14
2074 inline
2075 year_month&
2076 year_month::operator-=(const years& dy) NOEXCEPT
2077 {
2078 *this = *this - dy;
2079 return *this;
2080 }
2081
2082 CONSTCD11
2083 inline
2084 bool
2085 operator==(const year_month& x, const year_month& y) NOEXCEPT
2086 {
2087 return x.year() == y.year() && x.month() == y.month();
2088 }
2089
2090 CONSTCD11
2091 inline
2092 bool
2093 operator!=(const year_month& x, const year_month& y) NOEXCEPT
2094 {
2095 return !(x == y);
2096 }
2097
2098 CONSTCD11
2099 inline
2100 bool
2101 operator<(const year_month& x, const year_month& y) NOEXCEPT
2102 {
2103 return x.year() < y.year() ? true
2104 : (x.year() > y.year() ? false
2105 : (x.month() < y.month()));
2106 }
2107
2108 CONSTCD11
2109 inline
2110 bool
2111 operator>(const year_month& x, const year_month& y) NOEXCEPT
2112 {
2113 return y < x;
2114 }
2115
2116 CONSTCD11
2117 inline
2118 bool
2119 operator<=(const year_month& x, const year_month& y) NOEXCEPT
2120 {
2121 return !(y < x);
2122 }
2123
2124 CONSTCD11
2125 inline
2126 bool
2127 operator>=(const year_month& x, const year_month& y) NOEXCEPT
2128 {
2129 return !(x < y);
2130 }
2131
2132 template<class>
2133 CONSTCD14
2134 inline
2135 year_month
2136 operator+(const year_month& ym, const months& dm) NOEXCEPT
2137 {
2138 auto dmi = static_cast<int>(static_cast<unsigned>(ym.month())) - 1 + dm.count();
2139 auto dy = (dmi >= 0 ? dmi : dmi-11) / 12;
2140 dmi = dmi - dy * 12 + 1;
2141 return (ym.year() + years(dy)) / month(static_cast<unsigned>(dmi));
2142 }
2143
2144 template<class>
2145 CONSTCD14
2146 inline
2147 year_month
2148 operator+(const months& dm, const year_month& ym) NOEXCEPT
2149 {
2150 return ym + dm;
2151 }
2152
2153 template<class>
2154 CONSTCD14
2155 inline
2156 year_month
2157 operator-(const year_month& ym, const months& dm) NOEXCEPT
2158 {
2159 return ym + -dm;
2160 }
2161
2162 CONSTCD11
2163 inline
2164 months
2165 operator-(const year_month& x, const year_month& y) NOEXCEPT
2166 {
2167 return (x.year() - y.year()) +
2168 months(static_cast<unsigned>(x.month()) - static_cast<unsigned>(y.month()));
2169 }
2170
2171 CONSTCD11
2172 inline
2173 year_month
2174 operator+(const year_month& ym, const years& dy) NOEXCEPT
2175 {
2176 return (ym.year() + dy) / ym.month();
2177 }
2178
2179 CONSTCD11
2180 inline
2181 year_month
2182 operator+(const years& dy, const year_month& ym) NOEXCEPT
2183 {
2184 return ym + dy;
2185 }
2186
2187 CONSTCD11
2188 inline
2189 year_month
2190 operator-(const year_month& ym, const years& dy) NOEXCEPT
2191 {
2192 return ym + -dy;
2193 }
2194
2195 template<class CharT, class Traits>
2196 inline
2197 std::basic_ostream<CharT, Traits>&
2198 operator<<(std::basic_ostream<CharT, Traits>& os, const year_month& ym)
2199 {
2200 return os << ym.year() << '/' << ym.month();
2201 }
2202
2203 // month_day
2204
2205 CONSTCD11
2206 inline
2207 month_day::month_day(const date::month& m, const date::day& d) NOEXCEPT
2208 : m_(m)
2209 , d_(d)
2210 {}
2211
2212 CONSTCD11 inline date::month month_day::month() const NOEXCEPT {return m_;}
2213 CONSTCD11 inline date::day month_day::day() const NOEXCEPT {return d_;}
2214
2215 CONSTCD14
2216 inline
2217 bool
2218 month_day::ok() const NOEXCEPT
2219 {
2220 CONSTDATA date::day d[] =
2221 {
2222 date::day(31), date::day(29), date::day(31),
2223 date::day(30), date::day(31), date::day(30),
2224 date::day(31), date::day(31), date::day(30),
2225 date::day(31), date::day(30), date::day(31)
2226 };
2227 return m_.ok() && date::day{1} <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
2228 }
2229
2230 CONSTCD11
2231 inline
2232 bool
2233 operator==(const month_day& x, const month_day& y) NOEXCEPT
2234 {
2235 return x.month() == y.month() && x.day() == y.day();
2236 }
2237
2238 CONSTCD11
2239 inline
2240 bool
2241 operator!=(const month_day& x, const month_day& y) NOEXCEPT
2242 {
2243 return !(x == y);
2244 }
2245
2246 CONSTCD11
2247 inline
2248 bool
2249 operator<(const month_day& x, const month_day& y) NOEXCEPT
2250 {
2251 return x.month() < y.month() ? true
2252 : (x.month() > y.month() ? false
2253 : (x.day() < y.day()));
2254 }
2255
2256 CONSTCD11
2257 inline
2258 bool
2259 operator>(const month_day& x, const month_day& y) NOEXCEPT
2260 {
2261 return y < x;
2262 }
2263
2264 CONSTCD11
2265 inline
2266 bool
2267 operator<=(const month_day& x, const month_day& y) NOEXCEPT
2268 {
2269 return !(y < x);
2270 }
2271
2272 CONSTCD11
2273 inline
2274 bool
2275 operator>=(const month_day& x, const month_day& y) NOEXCEPT
2276 {
2277 return !(x < y);
2278 }
2279
2280 template<class CharT, class Traits>
2281 inline
2282 std::basic_ostream<CharT, Traits>&
2283 operator<<(std::basic_ostream<CharT, Traits>& os, const month_day& md)
2284 {
2285 return os << md.month() << '/' << md.day();
2286 }
2287
2288 // month_day_last
2289
2290 CONSTCD11 inline month month_day_last::month() const NOEXCEPT {return m_;}
2291 CONSTCD11 inline bool month_day_last::ok() const NOEXCEPT {return m_.ok();}
2292 CONSTCD11 inline month_day_last::month_day_last(const date::month& m) NOEXCEPT : m_(m) {}
2293
2294 CONSTCD11
2295 inline
2296 bool
2297 operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT
2298 {
2299 return x.month() == y.month();
2300 }
2301
2302 CONSTCD11
2303 inline
2304 bool
2305 operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT
2306 {
2307 return !(x == y);
2308 }
2309
2310 CONSTCD11
2311 inline
2312 bool
2313 operator<(const month_day_last& x, const month_day_last& y) NOEXCEPT
2314 {
2315 return x.month() < y.month();
2316 }
2317
2318 CONSTCD11
2319 inline
2320 bool
2321 operator>(const month_day_last& x, const month_day_last& y) NOEXCEPT
2322 {
2323 return y < x;
2324 }
2325
2326 CONSTCD11
2327 inline
2328 bool
2329 operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT
2330 {
2331 return !(y < x);
2332 }
2333
2334 CONSTCD11
2335 inline
2336 bool
2337 operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT
2338 {
2339 return !(x < y);
2340 }
2341
2342 template<class CharT, class Traits>
2343 inline
2344 std::basic_ostream<CharT, Traits>&
2345 operator<<(std::basic_ostream<CharT, Traits>& os, const month_day_last& mdl)
2346 {
2347 return os << mdl.month() << "/last";
2348 }
2349
2350 // month_weekday
2351
2352 CONSTCD11
2353 inline
2354 month_weekday::month_weekday(const date::month& m,
2355 const date::weekday_indexed& wdi) NOEXCEPT
2356 : m_(m)
2357 , wdi_(wdi)
2358 {}
2359
2360 CONSTCD11 inline month month_weekday::month() const NOEXCEPT {return m_;}
2361
2362 CONSTCD11
2363 inline
2364 weekday_indexed
2365 month_weekday::weekday_indexed() const NOEXCEPT
2366 {
2367 return wdi_;
2368 }
2369
2370 CONSTCD11
2371 inline
2372 bool
2373 month_weekday::ok() const NOEXCEPT
2374 {
2375 return m_.ok() && wdi_.ok();
2376 }
2377
2378 CONSTCD11
2379 inline
2380 bool
2381 operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT
2382 {
2383 return x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed();
2384 }
2385
2386 CONSTCD11
2387 inline
2388 bool
2389 operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT
2390 {
2391 return !(x == y);
2392 }
2393
2394 template<class CharT, class Traits>
2395 inline
2396 std::basic_ostream<CharT, Traits>&
2397 operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday& mwd)
2398 {
2399 return os << mwd.month() << '/' << mwd.weekday_indexed();
2400 }
2401
2402 // month_weekday_last
2403
2404 CONSTCD11
2405 inline
2406 month_weekday_last::month_weekday_last(const date::month& m,
2407 const date::weekday_last& wdl) NOEXCEPT
2408 : m_(m)
2409 , wdl_(wdl)
2410 {}
2411
2412 CONSTCD11 inline month month_weekday_last::month() const NOEXCEPT {return m_;}
2413
2414 CONSTCD11
2415 inline
2416 weekday_last
2417 month_weekday_last::weekday_last() const NOEXCEPT
2418 {
2419 return wdl_;
2420 }
2421
2422 CONSTCD11
2423 inline
2424 bool
2425 month_weekday_last::ok() const NOEXCEPT
2426 {
2427 return m_.ok() && wdl_.ok();
2428 }
2429
2430 CONSTCD11
2431 inline
2432 bool
2433 operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT
2434 {
2435 return x.month() == y.month() && x.weekday_last() == y.weekday_last();
2436 }
2437
2438 CONSTCD11
2439 inline
2440 bool
2441 operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT
2442 {
2443 return !(x == y);
2444 }
2445
2446 template<class CharT, class Traits>
2447 inline
2448 std::basic_ostream<CharT, Traits>&
2449 operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday_last& mwdl)
2450 {
2451 return os << mwdl.month() << '/' << mwdl.weekday_last();
2452 }
2453
2454 // year_month_day_last
2455
2456 CONSTCD11
2457 inline
2458 year_month_day_last::year_month_day_last(const date::year& y,
2459 const date::month_day_last& mdl) NOEXCEPT
2460 : y_(y)
2461 , mdl_(mdl)
2462 {}
2463
2464 template<class>
2465 CONSTCD14
2466 inline
2467 year_month_day_last&
2468 year_month_day_last::operator+=(const months& m) NOEXCEPT
2469 {
2470 *this = *this + m;
2471 return *this;
2472 }
2473
2474 template<class>
2475 CONSTCD14
2476 inline
2477 year_month_day_last&
2478 year_month_day_last::operator-=(const months& m) NOEXCEPT
2479 {
2480 *this = *this - m;
2481 return *this;
2482 }
2483
2484 CONSTCD14
2485 inline
2486 year_month_day_last&
2487 year_month_day_last::operator+=(const years& y) NOEXCEPT
2488 {
2489 *this = *this + y;
2490 return *this;
2491 }
2492
2493 CONSTCD14
2494 inline
2495 year_month_day_last&
2496 year_month_day_last::operator-=(const years& y) NOEXCEPT
2497 {
2498 *this = *this - y;
2499 return *this;
2500 }
2501
2502 CONSTCD11 inline year year_month_day_last::year() const NOEXCEPT {return y_;}
2503 CONSTCD11 inline month year_month_day_last::month() const NOEXCEPT {return mdl_.month();}
2504
2505 CONSTCD11
2506 inline
2507 month_day_last
2508 year_month_day_last::month_day_last() const NOEXCEPT
2509 {
2510 return mdl_;
2511 }
2512
2513 CONSTCD14
2514 inline
2515 day
2516 year_month_day_last::day() const NOEXCEPT
2517 {
2518 CONSTDATA date::day d[] =
2519 {
2520 date::day(31), date::day(28), date::day(31),
2521 date::day(30), date::day(31), date::day(30),
2522 date::day(31), date::day(31), date::day(30),
2523 date::day(31), date::day(30), date::day(31)
2524 };
2525 return (month() != February || !y_.is_leap()) && mdl_.ok() ?
2526 d[static_cast<unsigned>(month()) - 1] : date::day{29};
2527 }
2528
2529 CONSTCD14
2530 inline
2531 year_month_day_last::operator sys_days() const NOEXCEPT
2532 {
2533 return sys_days(year()/month()/day());
2534 }
2535
2536 CONSTCD14
2537 inline
2538 year_month_day_last::operator local_days() const NOEXCEPT
2539 {
2540 return local_days(year()/month()/day());
2541 }
2542
2543 CONSTCD11
2544 inline
2545 bool
2546 year_month_day_last::ok() const NOEXCEPT
2547 {
2548 return y_.ok() && mdl_.ok();
2549 }
2550
2551 CONSTCD11
2552 inline
2553 bool
2554 operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
2555 {
2556 return x.year() == y.year() && x.month_day_last() == y.month_day_last();
2557 }
2558
2559 CONSTCD11
2560 inline
2561 bool
2562 operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
2563 {
2564 return !(x == y);
2565 }
2566
2567 CONSTCD11
2568 inline
2569 bool
2570 operator<(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
2571 {
2572 return x.year() < y.year() ? true
2573 : (x.year() > y.year() ? false
2574 : (x.month_day_last() < y.month_day_last()));
2575 }
2576
2577 CONSTCD11
2578 inline
2579 bool
2580 operator>(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
2581 {
2582 return y < x;
2583 }
2584
2585 CONSTCD11
2586 inline
2587 bool
2588 operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
2589 {
2590 return !(y < x);
2591 }
2592
2593 CONSTCD11
2594 inline
2595 bool
2596 operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
2597 {
2598 return !(x < y);
2599 }
2600
2601 template<class CharT, class Traits>
2602 inline
2603 std::basic_ostream<CharT, Traits>&
2604 operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day_last& ymdl)
2605 {
2606 return os << ymdl.year() << '/' << ymdl.month_day_last();
2607 }
2608
2609 template<class>
2610 CONSTCD14
2611 inline
2612 year_month_day_last
2613 operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT
2614 {
2615 return (ymdl.year() / ymdl.month() + dm) / last;
2616 }
2617
2618 template<class>
2619 CONSTCD14
2620 inline
2621 year_month_day_last
2622 operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT
2623 {
2624 return ymdl + dm;
2625 }
2626
2627 template<class>
2628 CONSTCD14
2629 inline
2630 year_month_day_last
2631 operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT
2632 {
2633 return ymdl + (-dm);
2634 }
2635
2636 CONSTCD11
2637 inline
2638 year_month_day_last
2639 operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT
2640 {
2641 return {ymdl.year()+dy, ymdl.month_day_last()};
2642 }
2643
2644 CONSTCD11
2645 inline
2646 year_month_day_last
2647 operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT
2648 {
2649 return ymdl + dy;
2650 }
2651
2652 CONSTCD11
2653 inline
2654 year_month_day_last
2655 operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT
2656 {
2657 return ymdl + (-dy);
2658 }
2659
2660 // year_month_day
2661
2662 CONSTCD11
2663 inline
2664 year_month_day::year_month_day(const date::year& y, const date::month& m,
2665 const date::day& d) NOEXCEPT
2666 : y_(y)
2667 , m_(m)
2668 , d_(d)
2669 {}
2670
2671 CONSTCD14
2672 inline
2673 year_month_day::year_month_day(const year_month_day_last& ymdl) NOEXCEPT
2674 : y_(ymdl.year())
2675 , m_(ymdl.month())
2676 , d_(ymdl.day())
2677 {}
2678
2679 CONSTCD14
2680 inline
2681 year_month_day::year_month_day(sys_days dp) NOEXCEPT
2682 : year_month_day(from_days(dp.time_since_epoch()))
2683 {}
2684
2685 CONSTCD14
2686 inline
2687 year_month_day::year_month_day(local_days dp) NOEXCEPT
2688 : year_month_day(from_days(dp.time_since_epoch()))
2689 {}
2690
2691 CONSTCD11 inline year year_month_day::year() const NOEXCEPT {return y_;}
2692 CONSTCD11 inline month year_month_day::month() const NOEXCEPT {return m_;}
2693 CONSTCD11 inline day year_month_day::day() const NOEXCEPT {return d_;}
2694
2695 template<class>
2696 CONSTCD14
2697 inline
2698 year_month_day&
2699 year_month_day::operator+=(const months& m) NOEXCEPT
2700 {
2701 *this = *this + m;
2702 return *this;
2703 }
2704
2705 template<class>
2706 CONSTCD14
2707 inline
2708 year_month_day&
2709 year_month_day::operator-=(const months& m) NOEXCEPT
2710 {
2711 *this = *this - m;
2712 return *this;
2713 }
2714
2715 CONSTCD14
2716 inline
2717 year_month_day&
2718 year_month_day::operator+=(const years& y) NOEXCEPT
2719 {
2720 *this = *this + y;
2721 return *this;
2722 }
2723
2724 CONSTCD14
2725 inline
2726 year_month_day&
2727 year_month_day::operator-=(const years& y) NOEXCEPT
2728 {
2729 *this = *this - y;
2730 return *this;
2731 }
2732
2733 CONSTCD14
2734 inline
2735 days
2736 year_month_day::to_days() const NOEXCEPT
2737 {
2738 static_assert(std::numeric_limits<unsigned>::digits >= 18,
2739 "This algorithm has not been ported to a 16 bit unsigned integer");
2740 static_assert(std::numeric_limits<int>::digits >= 20,
2741 "This algorithm has not been ported to a 16 bit signed integer");
2742 auto const y = static_cast<int>(y_) - (m_ <= February);
2743 auto const m = static_cast<unsigned>(m_);
2744 auto const d = static_cast<unsigned>(d_);
2745 auto const era = (y >= 0 ? y : y-399) / 400;
2746 auto const yoe = static_cast<unsigned>(y - era * 400); // [0, 399]
2747 auto const doy = (153*(m > 2 ? m-3 : m+9) + 2)/5 + d-1; // [0, 365]
2748 auto const doe = yoe * 365 + yoe/4 - yoe/100 + doy; // [0, 146096]
2749 return days{era * 146097 + static_cast<int>(doe) - 719468};
2750 }
2751
2752 CONSTCD14
2753 inline
2754 year_month_day::operator sys_days() const NOEXCEPT
2755 {
2756 return sys_days{to_days()};
2757 }
2758
2759 CONSTCD14
2760 inline
2761 year_month_day::operator local_days() const NOEXCEPT
2762 {
2763 return local_days{to_days()};
2764 }
2765
2766 CONSTCD14
2767 inline
2768 bool
2769 year_month_day::ok() const NOEXCEPT
2770 {
2771 if (!(y_.ok() && m_.ok()))
2772 return false;
2773 return date::day{1} <= d_ && d_ <= (y_ / m_ / last).day();
2774 }
2775
2776 CONSTCD11
2777 inline
2778 bool
2779 operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT
2780 {
2781 return x.year() == y.year() && x.month() == y.month() && x.day() == y.day();
2782 }
2783
2784 CONSTCD11
2785 inline
2786 bool
2787 operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT
2788 {
2789 return !(x == y);
2790 }
2791
2792 CONSTCD11
2793 inline
2794 bool
2795 operator<(const year_month_day& x, const year_month_day& y) NOEXCEPT
2796 {
2797 return x.year() < y.year() ? true
2798 : (x.year() > y.year() ? false
2799 : (x.month() < y.month() ? true
2800 : (x.month() > y.month() ? false
2801 : (x.day() < y.day()))));
2802 }
2803
2804 CONSTCD11
2805 inline
2806 bool
2807 operator>(const year_month_day& x, const year_month_day& y) NOEXCEPT
2808 {
2809 return y < x;
2810 }
2811
2812 CONSTCD11
2813 inline
2814 bool
2815 operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT
2816 {
2817 return !(y < x);
2818 }
2819
2820 CONSTCD11
2821 inline
2822 bool
2823 operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT
2824 {
2825 return !(x < y);
2826 }
2827
2828 template<class CharT, class Traits>
2829 inline
2830 std::basic_ostream<CharT, Traits>&
2831 operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day& ymd)
2832 {
2833 detail::save_ostream<CharT, Traits> _(os);
2834 os.fill('0');
2835 os.flags(std::ios::dec | std::ios::right);
2836 os << ymd.year() << '-';
2837 os.width(2);
2838 os << static_cast<unsigned>(ymd.month()) << '-';
2839 os << ymd.day();
2840 if (!ymd.ok())
2841 os << " is not a valid date";
2842 return os;
2843 }
2844
2845 CONSTCD14
2846 inline
2847 year_month_day
2848 year_month_day::from_days(days dp) NOEXCEPT
2849 {
2850 static_assert(std::numeric_limits<unsigned>::digits >= 18,
2851 "This algorithm has not been ported to a 16 bit unsigned integer");
2852 static_assert(std::numeric_limits<int>::digits >= 20,
2853 "This algorithm has not been ported to a 16 bit signed integer");
2854 auto const z = dp.count() + 719468;
2855 auto const era = (z >= 0 ? z : z - 146096) / 146097;
2856 auto const doe = static_cast<unsigned>(z - era * 146097); // [0, 146096]
2857 auto const yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365; // [0, 399]
2858 auto const y = static_cast<days::rep>(yoe) + era * 400;
2859 auto const doy = doe - (365*yoe + yoe/4 - yoe/100); // [0, 365]
2860 auto const mp = (5*doy + 2)/153; // [0, 11]
2861 auto const d = doy - (153*mp+2)/5 + 1; // [1, 31]
2862 auto const m = mp < 10 ? mp+3 : mp-9; // [1, 12]
2863 return year_month_day{date::year{y + (m <= 2)}, date::month(m), date::day(d)};
2864 }
2865
2866 template<class>
2867 CONSTCD14
2868 inline
2869 year_month_day
2870 operator+(const year_month_day& ymd, const months& dm) NOEXCEPT
2871 {
2872 return (ymd.year() / ymd.month() + dm) / ymd.day();
2873 }
2874
2875 template<class>
2876 CONSTCD14
2877 inline
2878 year_month_day
2879 operator+(const months& dm, const year_month_day& ymd) NOEXCEPT
2880 {
2881 return ymd + dm;
2882 }
2883
2884 template<class>
2885 CONSTCD14
2886 inline
2887 year_month_day
2888 operator-(const year_month_day& ymd, const months& dm) NOEXCEPT
2889 {
2890 return ymd + (-dm);
2891 }
2892
2893 CONSTCD11
2894 inline
2895 year_month_day
2896 operator+(const year_month_day& ymd, const years& dy) NOEXCEPT
2897 {
2898 return (ymd.year() + dy) / ymd.month() / ymd.day();
2899 }
2900
2901 CONSTCD11
2902 inline
2903 year_month_day
2904 operator+(const years& dy, const year_month_day& ymd) NOEXCEPT
2905 {
2906 return ymd + dy;
2907 }
2908
2909 CONSTCD11
2910 inline
2911 year_month_day
2912 operator-(const year_month_day& ymd, const years& dy) NOEXCEPT
2913 {
2914 return ymd + (-dy);
2915 }
2916
2917 // year_month_weekday
2918
2919 CONSTCD11
2920 inline
2921 year_month_weekday::year_month_weekday(const date::year& y, const date::month& m,
2922 const date::weekday_indexed& wdi)
2923 NOEXCEPT
2924 : y_(y)
2925 , m_(m)
2926 , wdi_(wdi)
2927 {}
2928
2929 CONSTCD14
2930 inline
2931 year_month_weekday::year_month_weekday(const sys_days& dp) NOEXCEPT
2932 : year_month_weekday(from_days(dp.time_since_epoch()))
2933 {}
2934
2935 CONSTCD14
2936 inline
2937 year_month_weekday::year_month_weekday(const local_days& dp) NOEXCEPT
2938 : year_month_weekday(from_days(dp.time_since_epoch()))
2939 {}
2940
2941 template<class>
2942 CONSTCD14
2943 inline
2944 year_month_weekday&
2945 year_month_weekday::operator+=(const months& m) NOEXCEPT
2946 {
2947 *this = *this + m;
2948 return *this;
2949 }
2950
2951 template<class>
2952 CONSTCD14
2953 inline
2954 year_month_weekday&
2955 year_month_weekday::operator-=(const months& m) NOEXCEPT
2956 {
2957 *this = *this - m;
2958 return *this;
2959 }
2960
2961 CONSTCD14
2962 inline
2963 year_month_weekday&
2964 year_month_weekday::operator+=(const years& y) NOEXCEPT
2965 {
2966 *this = *this + y;
2967 return *this;
2968 }
2969
2970 CONSTCD14
2971 inline
2972 year_month_weekday&
2973 year_month_weekday::operator-=(const years& y) NOEXCEPT
2974 {
2975 *this = *this - y;
2976 return *this;
2977 }
2978
2979 CONSTCD11 inline year year_month_weekday::year() const NOEXCEPT {return y_;}
2980 CONSTCD11 inline month year_month_weekday::month() const NOEXCEPT {return m_;}
2981
2982 CONSTCD11
2983 inline
2984 weekday
2985 year_month_weekday::weekday() const NOEXCEPT
2986 {
2987 return wdi_.weekday();
2988 }
2989
2990 CONSTCD11
2991 inline
2992 unsigned
2993 year_month_weekday::index() const NOEXCEPT
2994 {
2995 return wdi_.index();
2996 }
2997
2998 CONSTCD11
2999 inline
3000 weekday_indexed
3001 year_month_weekday::weekday_indexed() const NOEXCEPT
3002 {
3003 return wdi_;
3004 }
3005
3006 CONSTCD14
3007 inline
3008 year_month_weekday::operator sys_days() const NOEXCEPT
3009 {
3010 return sys_days{to_days()};
3011 }
3012
3013 CONSTCD14
3014 inline
3015 year_month_weekday::operator local_days() const NOEXCEPT
3016 {
3017 return local_days{to_days()};
3018 }
3019
3020 CONSTCD14
3021 inline
3022 bool
3023 year_month_weekday::ok() const NOEXCEPT
3024 {
3025 if (!y_.ok() || !m_.ok() || !wdi_.weekday().ok() || wdi_.index() < 1)
3026 return false;
3027 if (wdi_.index() <= 4)
3028 return true;
3029 auto d2 = wdi_.weekday() - date::weekday(static_cast<sys_days>(y_/m_/1)) +
3030 days((wdi_.index()-1)*7 + 1);
3031 return static_cast<unsigned>(d2.count()) <= static_cast<unsigned>((y_/m_/last).day());
3032 }
3033
3034 CONSTCD14
3035 inline
3036 year_month_weekday
3037 year_month_weekday::from_days(days d) NOEXCEPT
3038 {
3039 sys_days dp{d};
3040 auto const wd = date::weekday(dp);
3041 auto const ymd = year_month_day(dp);
3042 return {ymd.year(), ymd.month(), wd[(static_cast<unsigned>(ymd.day())-1)/7+1]};
3043 }
3044
3045 CONSTCD14
3046 inline
3047 days
3048 year_month_weekday::to_days() const NOEXCEPT
3049 {
3050 auto d = sys_days(y_/m_/1);
3051 return (d + (wdi_.weekday() - date::weekday(d) + days{(wdi_.index()-1)*7})
3052 ).time_since_epoch();
3053 }
3054
3055 CONSTCD11
3056 inline
3057 bool
3058 operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT
3059 {
3060 return x.year() == y.year() && x.month() == y.month() &&
3061 x.weekday_indexed() == y.weekday_indexed();
3062 }
3063
3064 CONSTCD11
3065 inline
3066 bool
3067 operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT
3068 {
3069 return !(x == y);
3070 }
3071
3072 template<class CharT, class Traits>
3073 inline
3074 std::basic_ostream<CharT, Traits>&
3075 operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday& ymwdi)
3076 {
3077 return os << ymwdi.year() << '/' << ymwdi.month()
3078 << '/' << ymwdi.weekday_indexed();
3079 }
3080
3081 template<class>
3082 CONSTCD14
3083 inline
3084 year_month_weekday
3085 operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT
3086 {
3087 return (ymwd.year() / ymwd.month() + dm) / ymwd.weekday_indexed();
3088 }
3089
3090 template<class>
3091 CONSTCD14
3092 inline
3093 year_month_weekday
3094 operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT
3095 {
3096 return ymwd + dm;
3097 }
3098
3099 template<class>
3100 CONSTCD14
3101 inline
3102 year_month_weekday
3103 operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT
3104 {
3105 return ymwd + (-dm);
3106 }
3107
3108 CONSTCD11
3109 inline
3110 year_month_weekday
3111 operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT
3112 {
3113 return {ymwd.year()+dy, ymwd.month(), ymwd.weekday_indexed()};
3114 }
3115
3116 CONSTCD11
3117 inline
3118 year_month_weekday
3119 operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT
3120 {
3121 return ymwd + dy;
3122 }
3123
3124 CONSTCD11
3125 inline
3126 year_month_weekday
3127 operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT
3128 {
3129 return ymwd + (-dy);
3130 }
3131
3132 // year_month_weekday_last
3133
3134 CONSTCD11
3135 inline
3136 year_month_weekday_last::year_month_weekday_last(const date::year& y,
3137 const date::month& m,
3138 const date::weekday_last& wdl) NOEXCEPT
3139 : y_(y)
3140 , m_(m)
3141 , wdl_(wdl)
3142 {}
3143
3144 template<class>
3145 CONSTCD14
3146 inline
3147 year_month_weekday_last&
3148 year_month_weekday_last::operator+=(const months& m) NOEXCEPT
3149 {
3150 *this = *this + m;
3151 return *this;
3152 }
3153
3154 template<class>
3155 CONSTCD14
3156 inline
3157 year_month_weekday_last&
3158 year_month_weekday_last::operator-=(const months& m) NOEXCEPT
3159 {
3160 *this = *this - m;
3161 return *this;
3162 }
3163
3164 CONSTCD14
3165 inline
3166 year_month_weekday_last&
3167 year_month_weekday_last::operator+=(const years& y) NOEXCEPT
3168 {
3169 *this = *this + y;
3170 return *this;
3171 }
3172
3173 CONSTCD14
3174 inline
3175 year_month_weekday_last&
3176 year_month_weekday_last::operator-=(const years& y) NOEXCEPT
3177 {
3178 *this = *this - y;
3179 return *this;
3180 }
3181
3182 CONSTCD11 inline year year_month_weekday_last::year() const NOEXCEPT {return y_;}
3183 CONSTCD11 inline month year_month_weekday_last::month() const NOEXCEPT {return m_;}
3184
3185 CONSTCD11
3186 inline
3187 weekday
3188 year_month_weekday_last::weekday() const NOEXCEPT
3189 {
3190 return wdl_.weekday();
3191 }
3192
3193 CONSTCD11
3194 inline
3195 weekday_last
3196 year_month_weekday_last::weekday_last() const NOEXCEPT
3197 {
3198 return wdl_;
3199 }
3200
3201 CONSTCD14
3202 inline
3203 year_month_weekday_last::operator sys_days() const NOEXCEPT
3204 {
3205 return sys_days{to_days()};
3206 }
3207
3208 CONSTCD14
3209 inline
3210 year_month_weekday_last::operator local_days() const NOEXCEPT
3211 {
3212 return local_days{to_days()};
3213 }
3214
3215 CONSTCD11
3216 inline
3217 bool
3218 year_month_weekday_last::ok() const NOEXCEPT
3219 {
3220 return y_.ok() && m_.ok() && wdl_.ok();
3221 }
3222
3223 CONSTCD14
3224 inline
3225 days
3226 year_month_weekday_last::to_days() const NOEXCEPT
3227 {
3228 auto const d = sys_days(y_/m_/last);
3229 return (d - (date::weekday{d} - wdl_.weekday())).time_since_epoch();
3230 }
3231
3232 CONSTCD11
3233 inline
3234 bool
3235 operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT
3236 {
3237 return x.year() == y.year() && x.month() == y.month() &&
3238 x.weekday_last() == y.weekday_last();
3239 }
3240
3241 CONSTCD11
3242 inline
3243 bool
3244 operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT
3245 {
3246 return !(x == y);
3247 }
3248
3249 template<class CharT, class Traits>
3250 inline
3251 std::basic_ostream<CharT, Traits>&
3252 operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last& ymwdl)
3253 {
3254 return os << ymwdl.year() << '/' << ymwdl.month() << '/' << ymwdl.weekday_last();
3255 }
3256
3257 template<class>
3258 CONSTCD14
3259 inline
3260 year_month_weekday_last
3261 operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT
3262 {
3263 return (ymwdl.year() / ymwdl.month() + dm) / ymwdl.weekday_last();
3264 }
3265
3266 template<class>
3267 CONSTCD14
3268 inline
3269 year_month_weekday_last
3270 operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT
3271 {
3272 return ymwdl + dm;
3273 }
3274
3275 template<class>
3276 CONSTCD14
3277 inline
3278 year_month_weekday_last
3279 operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT
3280 {
3281 return ymwdl + (-dm);
3282 }
3283
3284 CONSTCD11
3285 inline
3286 year_month_weekday_last
3287 operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT
3288 {
3289 return {ymwdl.year()+dy, ymwdl.month(), ymwdl.weekday_last()};
3290 }
3291
3292 CONSTCD11
3293 inline
3294 year_month_weekday_last
3295 operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT
3296 {
3297 return ymwdl + dy;
3298 }
3299
3300 CONSTCD11
3301 inline
3302 year_month_weekday_last
3303 operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT
3304 {
3305 return ymwdl + (-dy);
3306 }
3307
3308 // year_month from operator/()
3309
3310 CONSTCD11
3311 inline
3312 year_month
3313 operator/(const year& y, const month& m) NOEXCEPT
3314 {
3315 return {y, m};
3316 }
3317
3318 CONSTCD11
3319 inline
3320 year_month
3321 operator/(const year& y, int m) NOEXCEPT
3322 {
3323 return y / month(static_cast<unsigned>(m));
3324 }
3325
3326 // month_day from operator/()
3327
3328 CONSTCD11
3329 inline
3330 month_day
3331 operator/(const month& m, const day& d) NOEXCEPT
3332 {
3333 return {m, d};
3334 }
3335
3336 CONSTCD11
3337 inline
3338 month_day
3339 operator/(const day& d, const month& m) NOEXCEPT
3340 {
3341 return m / d;
3342 }
3343
3344 CONSTCD11
3345 inline
3346 month_day
3347 operator/(const month& m, int d) NOEXCEPT
3348 {
3349 return m / day(static_cast<unsigned>(d));
3350 }
3351
3352 CONSTCD11
3353 inline
3354 month_day
3355 operator/(int m, const day& d) NOEXCEPT
3356 {
3357 return month(static_cast<unsigned>(m)) / d;
3358 }
3359
3360 CONSTCD11 inline month_day operator/(const day& d, int m) NOEXCEPT {return m / d;}
3361
3362 // month_day_last from operator/()
3363
3364 CONSTCD11
3365 inline
3366 month_day_last
3367 operator/(const month& m, last_spec) NOEXCEPT
3368 {
3369 return month_day_last{m};
3370 }
3371
3372 CONSTCD11
3373 inline
3374 month_day_last
3375 operator/(last_spec, const month& m) NOEXCEPT
3376 {
3377 return m/last;
3378 }
3379
3380 CONSTCD11
3381 inline
3382 month_day_last
3383 operator/(int m, last_spec) NOEXCEPT
3384 {
3385 return month(static_cast<unsigned>(m))/last;
3386 }
3387
3388 CONSTCD11
3389 inline
3390 month_day_last
3391 operator/(last_spec, int m) NOEXCEPT
3392 {
3393 return m/last;
3394 }
3395
3396 // month_weekday from operator/()
3397
3398 CONSTCD11
3399 inline
3400 month_weekday
3401 operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT
3402 {
3403 return {m, wdi};
3404 }
3405
3406 CONSTCD11
3407 inline
3408 month_weekday
3409 operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT
3410 {
3411 return m / wdi;
3412 }
3413
3414 CONSTCD11
3415 inline
3416 month_weekday
3417 operator/(int m, const weekday_indexed& wdi) NOEXCEPT
3418 {
3419 return month(static_cast<unsigned>(m)) / wdi;
3420 }
3421
3422 CONSTCD11
3423 inline
3424 month_weekday
3425 operator/(const weekday_indexed& wdi, int m) NOEXCEPT
3426 {
3427 return m / wdi;
3428 }
3429
3430 // month_weekday_last from operator/()
3431
3432 CONSTCD11
3433 inline
3434 month_weekday_last
3435 operator/(const month& m, const weekday_last& wdl) NOEXCEPT
3436 {
3437 return {m, wdl};
3438 }
3439
3440 CONSTCD11
3441 inline
3442 month_weekday_last
3443 operator/(const weekday_last& wdl, const month& m) NOEXCEPT
3444 {
3445 return m / wdl;
3446 }
3447
3448 CONSTCD11
3449 inline
3450 month_weekday_last
3451 operator/(int m, const weekday_last& wdl) NOEXCEPT
3452 {
3453 return month(static_cast<unsigned>(m)) / wdl;
3454 }
3455
3456 CONSTCD11
3457 inline
3458 month_weekday_last
3459 operator/(const weekday_last& wdl, int m) NOEXCEPT
3460 {
3461 return m / wdl;
3462 }
3463
3464 // year_month_day from operator/()
3465
3466 CONSTCD11
3467 inline
3468 year_month_day
3469 operator/(const year_month& ym, const day& d) NOEXCEPT
3470 {
3471 return {ym.year(), ym.month(), d};
3472 }
3473
3474 CONSTCD11
3475 inline
3476 year_month_day
3477 operator/(const year_month& ym, int d) NOEXCEPT
3478 {
3479 return ym / day(static_cast<unsigned>(d));
3480 }
3481
3482 CONSTCD11
3483 inline
3484 year_month_day
3485 operator/(const year& y, const month_day& md) NOEXCEPT
3486 {
3487 return y / md.month() / md.day();
3488 }
3489
3490 CONSTCD11
3491 inline
3492 year_month_day
3493 operator/(int y, const month_day& md) NOEXCEPT
3494 {
3495 return year(y) / md;
3496 }
3497
3498 CONSTCD11
3499 inline
3500 year_month_day
3501 operator/(const month_day& md, const year& y) NOEXCEPT
3502 {
3503 return y / md;
3504 }
3505
3506 CONSTCD11
3507 inline
3508 year_month_day
3509 operator/(const month_day& md, int y) NOEXCEPT
3510 {
3511 return year(y) / md;
3512 }
3513
3514 // year_month_day_last from operator/()
3515
3516 CONSTCD11
3517 inline
3518 year_month_day_last
3519 operator/(const year_month& ym, last_spec) NOEXCEPT
3520 {
3521 return {ym.year(), month_day_last{ym.month()}};
3522 }
3523
3524 CONSTCD11
3525 inline
3526 year_month_day_last
3527 operator/(const year& y, const month_day_last& mdl) NOEXCEPT
3528 {
3529 return {y, mdl};
3530 }
3531
3532 CONSTCD11
3533 inline
3534 year_month_day_last
3535 operator/(int y, const month_day_last& mdl) NOEXCEPT
3536 {
3537 return year(y) / mdl;
3538 }
3539
3540 CONSTCD11
3541 inline
3542 year_month_day_last
3543 operator/(const month_day_last& mdl, const year& y) NOEXCEPT
3544 {
3545 return y / mdl;
3546 }
3547
3548 CONSTCD11
3549 inline
3550 year_month_day_last
3551 operator/(const month_day_last& mdl, int y) NOEXCEPT
3552 {
3553 return year(y) / mdl;
3554 }
3555
3556 // year_month_weekday from operator/()
3557
3558 CONSTCD11
3559 inline
3560 year_month_weekday
3561 operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT
3562 {
3563 return {ym.year(), ym.month(), wdi};
3564 }
3565
3566 CONSTCD11
3567 inline
3568 year_month_weekday
3569 operator/(const year& y, const month_weekday& mwd) NOEXCEPT
3570 {
3571 return {y, mwd.month(), mwd.weekday_indexed()};
3572 }
3573
3574 CONSTCD11
3575 inline
3576 year_month_weekday
3577 operator/(int y, const month_weekday& mwd) NOEXCEPT
3578 {
3579 return year(y) / mwd;
3580 }
3581
3582 CONSTCD11
3583 inline
3584 year_month_weekday
3585 operator/(const month_weekday& mwd, const year& y) NOEXCEPT
3586 {
3587 return y / mwd;
3588 }
3589
3590 CONSTCD11
3591 inline
3592 year_month_weekday
3593 operator/(const month_weekday& mwd, int y) NOEXCEPT
3594 {
3595 return year(y) / mwd;
3596 }
3597
3598 // year_month_weekday_last from operator/()
3599
3600 CONSTCD11
3601 inline
3602 year_month_weekday_last
3603 operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT
3604 {
3605 return {ym.year(), ym.month(), wdl};
3606 }
3607
3608 CONSTCD11
3609 inline
3610 year_month_weekday_last
3611 operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT
3612 {
3613 return {y, mwdl.month(), mwdl.weekday_last()};
3614 }
3615
3616 CONSTCD11
3617 inline
3618 year_month_weekday_last
3619 operator/(int y, const month_weekday_last& mwdl) NOEXCEPT
3620 {
3621 return year(y) / mwdl;
3622 }
3623
3624 CONSTCD11
3625 inline
3626 year_month_weekday_last
3627 operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT
3628 {
3629 return y / mwdl;
3630 }
3631
3632 CONSTCD11
3633 inline
3634 year_month_weekday_last
3635 operator/(const month_weekday_last& mwdl, int y) NOEXCEPT
3636 {
3637 return year(y) / mwdl;
3638 }
3639
3640 template <class Duration>
3641 struct fields;
3642
3643 template <class CharT, class Traits, class Duration>
3644 std::basic_ostream<CharT, Traits>&
3645 to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
3646 const fields<Duration>& fds, const std::string* abbrev = nullptr,
3647 const std::chrono::seconds* offset_sec = nullptr);
3648
3649 template <class CharT, class Traits, class Duration, class Alloc>
3650 std::basic_istream<CharT, Traits>&
3651 from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
3652 fields<Duration>& fds, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
3653 std::chrono::minutes* offset = nullptr);
3654
3655 // hh_mm_ss
3656
3657 namespace detail
3658 {
3659
3660 struct undocumented {explicit undocumented() = default;};
3661
3662 // width<n>::value is the number of fractional decimal digits in 1/n
3663 // width<0>::value and width<1>::value are defined to be 0
3664 // If 1/n takes more than 18 fractional decimal digits,
3665 // the result is truncated to 19.
3666 // Example: width<2>::value == 1
3667 // Example: width<3>::value == 19
3668 // Example: width<4>::value == 2
3669 // Example: width<10>::value == 1
3670 // Example: width<1000>::value == 3
3671 template <std::uint64_t n, std::uint64_t d = 10, unsigned w = 0,
3672 bool should_continue = !(n < 2) && d != 0 && (w < 19)>
3673 struct width
3674 {
3675 static CONSTDATA unsigned value = 1 + width<n, d%n*10, w+1>::value;
3676 };
3677
3678 template <std::uint64_t n, std::uint64_t d, unsigned w>
3679 struct width<n, d, w, false>
3680 {
3681 static CONSTDATA unsigned value = 0;
3682 };
3683
3684 template <unsigned exp>
3685 struct static_pow10
3686 {
3687 private:
3688 static CONSTDATA std::uint64_t h = static_pow10<exp/2>::value;
3689 public:
3690 static CONSTDATA std::uint64_t value = h * h * (exp % 2 ? 10 : 1);
3691 };
3692
3693 template <>
3694 struct static_pow10<0>
3695 {
3696 static CONSTDATA std::uint64_t value = 1;
3697 };
3698
3699 template <class Duration>
3700 class decimal_format_seconds
3701 {
3702 using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
3703 using rep = typename CT::rep;
3704 public:
3705 static unsigned constexpr width = detail::width<CT::period::den>::value < 19 ?
3706 detail::width<CT::period::den>::value : 6u;
3707 using precision = std::chrono::duration<rep,
3708 std::ratio<1, static_pow10<width>::value>>;
3709
3710 private:
3711 std::chrono::seconds s_;
3712 precision sub_s_;
3713
3714 public:
3715 CONSTCD11 decimal_format_seconds()
3716 : s_()
3717 , sub_s_()
3718 {}
3719
3720 CONSTCD11 explicit decimal_format_seconds(const Duration& d) NOEXCEPT
3721 : s_(std::chrono::duration_cast<std::chrono::seconds>(d))
3722 , sub_s_(std::chrono::treat_as_floating_point<rep>::value ? d - s_ :
3723 std::chrono::duration_cast<precision>(d - s_))
3724 {}
3725
3726 CONSTCD14 std::chrono::seconds& seconds() NOEXCEPT {return s_;}
3727 CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_;}
3728 CONSTCD11 precision subseconds() const NOEXCEPT {return sub_s_;}
3729
3730 CONSTCD14 precision to_duration() const NOEXCEPT
3731 {
3732 return s_ + sub_s_;
3733 }
3734
3735 CONSTCD11 bool in_conventional_range() const NOEXCEPT
3736 {
3737 return sub_s_ < std::chrono::seconds{1} && s_ < std::chrono::minutes{1};
3738 }
3739
3740 template <class CharT, class Traits>
3741 friend
3742 std::basic_ostream<CharT, Traits>&
3743 operator<<(std::basic_ostream<CharT, Traits>& os, const decimal_format_seconds& x)
3744 {
3745 return x.print(os, std::chrono::treat_as_floating_point<rep>{});
3746 }
3747
3748 template <class CharT, class Traits>
3749 std::basic_ostream<CharT, Traits>&
3750 print(std::basic_ostream<CharT, Traits>& os, std::true_type) const
3751 {
3752 date::detail::save_ostream<CharT, Traits> _(os);
3753 std::chrono::duration<rep> d = s_ + sub_s_;
3754 if (d < std::chrono::seconds{10})
3755 os << '0';
3756 os << std::fixed << d.count();
3757 return os;
3758 }
3759
3760 template <class CharT, class Traits>
3761 std::basic_ostream<CharT, Traits>&
3762 print(std::basic_ostream<CharT, Traits>& os, std::false_type) const
3763 {
3764 date::detail::save_ostream<CharT, Traits> _(os);
3765 os.fill('0');
3766 os.flags(std::ios::dec | std::ios::right);
3767 os.width(2);
3768 os << s_.count();
3769 if (width > 0)
3770 {
3771 #if !ONLY_C_LOCALE
3772 os << std::use_facet<std::numpunct<CharT>>(os.getloc()).decimal_point();
3773 #else
3774 os << '.';
3775 #endif
3776 os.width(width);
3777 os << sub_s_.count();
3778 }
3779 return os;
3780 }
3781 };
3782
3783 template <class Rep, class Period>
3784 inline
3785 CONSTCD11
3786 typename std::enable_if
3787 <
3788 std::numeric_limits<Rep>::is_signed,
3789 std::chrono::duration<Rep, Period>
3790 >::type
3791 abs(std::chrono::duration<Rep, Period> d)
3792 {
3793 return d >= d.zero() ? +d : -d;
3794 }
3795
3796 template <class Rep, class Period>
3797 inline
3798 CONSTCD11
3799 typename std::enable_if
3800 <
3801 !std::numeric_limits<Rep>::is_signed,
3802 std::chrono::duration<Rep, Period>
3803 >::type
3804 abs(std::chrono::duration<Rep, Period> d)
3805 {
3806 return d;
3807 }
3808
3809 } // namespace detail
3810
3811 template <class Duration>
3812 class hh_mm_ss
3813 {
3814 using dfs = detail::decimal_format_seconds<typename std::common_type<Duration,
3815 std::chrono::seconds>::type>;
3816
3817 std::chrono::hours h_;
3818 std::chrono::minutes m_;
3819 dfs s_;
3820 bool neg_;
3821
3822 public:
3823 static unsigned CONSTDATA fractional_width = dfs::width;
3824 using precision = typename dfs::precision;
3825
3826 CONSTCD11 hh_mm_ss() NOEXCEPT
3827 : hh_mm_ss(Duration::zero())
3828 {}
3829
3830 CONSTCD11 explicit hh_mm_ss(Duration d) NOEXCEPT
3831 : h_(std::chrono::duration_cast<std::chrono::hours>(detail::abs(d)))
3832 , m_(std::chrono::duration_cast<std::chrono::minutes>(detail::abs(d)) - h_)
3833 , s_(detail::abs(d) - h_ - m_)
3834 , neg_(d < Duration::zero())
3835 {}
3836
3837 CONSTCD11 std::chrono::hours hours() const NOEXCEPT {return h_;}
3838 CONSTCD11 std::chrono::minutes minutes() const NOEXCEPT {return m_;}
3839 CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_.seconds();}
3840 CONSTCD14 std::chrono::seconds&
3841 seconds(detail::undocumented) NOEXCEPT {return s_.seconds();}
3842 CONSTCD11 precision subseconds() const NOEXCEPT {return s_.subseconds();}
3843 CONSTCD11 bool is_negative() const NOEXCEPT {return neg_;}
3844
3845 CONSTCD11 explicit operator precision() const NOEXCEPT {return to_duration();}
3846 CONSTCD11 precision to_duration() const NOEXCEPT
3847 {return (h_ + m_ + s_.to_duration()) * (1-2*neg_);}
3848
3849 CONSTCD11 bool in_conventional_range() const NOEXCEPT
3850 {
3851 return !neg_ && h_ < days{1} && m_ < std::chrono::hours{1} &&
3852 s_.in_conventional_range();
3853 }
3854
3855 private:
3856
3857 template <class charT, class traits>
3858 friend
3859 std::basic_ostream<charT, traits>&
3860 operator<<(std::basic_ostream<charT, traits>& os, hh_mm_ss const& tod)
3861 {
3862 if (tod.is_negative())
3863 os << '-';
3864 if (tod.h_ < std::chrono::hours{10})
3865 os << '0';
3866 os << tod.h_.count() << ':';
3867 if (tod.m_ < std::chrono::minutes{10})
3868 os << '0';
3869 os << tod.m_.count() << ':' << tod.s_;
3870 return os;
3871 }
3872
3873 template <class CharT, class Traits, class Duration2>
3874 friend
3875 std::basic_ostream<CharT, Traits>&
3876 date::to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
3877 const fields<Duration2>& fds, const std::string* abbrev,
3878 const std::chrono::seconds* offset_sec);
3879
3880 template <class CharT, class Traits, class Duration2, class Alloc>
3881 friend
3882 std::basic_istream<CharT, Traits>&
3883 date::from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
3884 fields<Duration2>& fds,
3885 std::basic_string<CharT, Traits, Alloc>* abbrev, std::chrono::minutes* offset);
3886 };
3887
3888 inline
3889 CONSTCD14
3890 bool
3891 is_am(std::chrono::hours const& h) NOEXCEPT
3892 {
3893 using std::chrono::hours;
3894 return hours{0} <= h && h < hours{12};
3895 }
3896
3897 inline
3898 CONSTCD14
3899 bool
3900 is_pm(std::chrono::hours const& h) NOEXCEPT
3901 {
3902 using std::chrono::hours;
3903 return hours{12} <= h && h < hours{24};
3904 }
3905
3906 inline
3907 CONSTCD14
3908 std::chrono::hours
3909 make12(std::chrono::hours h) NOEXCEPT
3910 {
3911 using std::chrono::hours;
3912 if (h < hours{12})
3913 {
3914 if (h == hours{0})
3915 h = hours{12};
3916 }
3917 else
3918 {
3919 if (h != hours{12})
3920 h = h - hours{12};
3921 }
3922 return h;
3923 }
3924
3925 inline
3926 CONSTCD14
3927 std::chrono::hours
3928 make24(std::chrono::hours h, bool is_pm) NOEXCEPT
3929 {
3930 using std::chrono::hours;
3931 if (is_pm)
3932 {
3933 if (h != hours{12})
3934 h = h + hours{12};
3935 }
3936 else if (h == hours{12})
3937 h = hours{0};
3938 return h;
3939 }
3940
3941 template <class Duration>
3942 using time_of_day = hh_mm_ss<Duration>;
3943
3944 template <class Rep, class Period,
3945 class = typename std::enable_if
3946 <!std::chrono::treat_as_floating_point<Rep>::value>::type>
3947 CONSTCD11
3948 inline
3949 hh_mm_ss<std::chrono::duration<Rep, Period>>
3950 make_time(const std::chrono::duration<Rep, Period>& d)
3951 {
3952 return hh_mm_ss<std::chrono::duration<Rep, Period>>(d);
3953 }
3954
3955 template <class CharT, class Traits, class Duration>
3956 inline
3957 typename std::enable_if
3958 <
3959 !std::chrono::treat_as_floating_point<typename Duration::rep>::value &&
3960 std::ratio_less<typename Duration::period, days::period>::value
3961 , std::basic_ostream<CharT, Traits>&
3962 >::type
3963 operator<<(std::basic_ostream<CharT, Traits>& os, const sys_time<Duration>& tp)
3964 {
3965 auto const dp = date::floor<days>(tp);
3966 return os << year_month_day(dp) << ' ' << make_time(tp-dp);
3967 }
3968
3969 template <class CharT, class Traits>
3970 inline
3971 std::basic_ostream<CharT, Traits>&
3972 operator<<(std::basic_ostream<CharT, Traits>& os, const sys_days& dp)
3973 {
3974 return os << year_month_day(dp);
3975 }
3976
3977 template <class CharT, class Traits, class Duration>
3978 inline
3979 std::basic_ostream<CharT, Traits>&
3980 operator<<(std::basic_ostream<CharT, Traits>& os, const local_time<Duration>& ut)
3981 {
3982 return (os << sys_time<Duration>{ut.time_since_epoch()});
3983 }
3984
3985 namespace detail
3986 {
3987
3988 template <class CharT, std::size_t N>
3989 class string_literal;
3990
3991 template <class CharT1, class CharT2, std::size_t N1, std::size_t N2>
3992 inline
3993 CONSTCD14
3994 string_literal<typename std::conditional<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>::type,
3995 N1 + N2 - 1>
3996 operator+(const string_literal<CharT1, N1>& x, const string_literal<CharT2, N2>& y) NOEXCEPT;
3997
3998 template <class CharT, std::size_t N>
3999 class string_literal
4000 {
4001 CharT p_[N];
4002
4003 CONSTCD11 string_literal() NOEXCEPT
4004 : p_{}
4005 {}
4006
4007 public:
4008 using const_iterator = const CharT*;
4009
4010 string_literal(string_literal const&) = default;
4011 string_literal& operator=(string_literal const&) = delete;
4012
4013 template <std::size_t N1 = 2,
4014 class = typename std::enable_if<N1 == N>::type>
4015 CONSTCD11 string_literal(CharT c) NOEXCEPT
4016 : p_{c}
4017 {
4018 }
4019
4020 template <std::size_t N1 = 3,
4021 class = typename std::enable_if<N1 == N>::type>
4022 CONSTCD11 string_literal(CharT c1, CharT c2) NOEXCEPT
4023 : p_{c1, c2}
4024 {
4025 }
4026
4027 template <std::size_t N1 = 4,
4028 class = typename std::enable_if<N1 == N>::type>
4029 CONSTCD11 string_literal(CharT c1, CharT c2, CharT c3) NOEXCEPT
4030 : p_{c1, c2, c3}
4031 {
4032 }
4033
4034 CONSTCD14 string_literal(const CharT(&a)[N]) NOEXCEPT
4035 : p_{}
4036 {
4037 for (std::size_t i = 0; i < N; ++i)
4038 p_[i] = a[i];
4039 }
4040
4041 template <class U = CharT,
4042 class = typename std::enable_if<(1 < sizeof(U))>::type>
4043 CONSTCD14 string_literal(const char(&a)[N]) NOEXCEPT
4044 : p_{}
4045 {
4046 for (std::size_t i = 0; i < N; ++i)
4047 p_[i] = a[i];
4048 }
4049
4050 template <class CharT2,
4051 class = typename std::enable_if<!std::is_same<CharT2, CharT>::value>::type>
4052 CONSTCD14 string_literal(string_literal<CharT2, N> const& a) NOEXCEPT
4053 : p_{}
4054 {
4055 for (std::size_t i = 0; i < N; ++i)
4056 p_[i] = a[i];
4057 }
4058
4059 CONSTCD11 const CharT* data() const NOEXCEPT {return p_;}
4060 CONSTCD11 std::size_t size() const NOEXCEPT {return N-1;}
4061
4062 CONSTCD11 const_iterator begin() const NOEXCEPT {return p_;}
4063 CONSTCD11 const_iterator end() const NOEXCEPT {return p_ + N-1;}
4064
4065 CONSTCD11 CharT const& operator[](std::size_t n) const NOEXCEPT
4066 {
4067 return p_[n];
4068 }
4069
4070 template <class Traits>
4071 friend
4072 std::basic_ostream<CharT, Traits>&
4073 operator<<(std::basic_ostream<CharT, Traits>& os, const string_literal& s)
4074 {
4075 return os << s.p_;
4076 }
4077
4078 template <class CharT1, class CharT2, std::size_t N1, std::size_t N2>
4079 friend
4080 CONSTCD14
4081 string_literal<typename std::conditional<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>::type,
4082 N1 + N2 - 1>
4083 operator+(const string_literal<CharT1, N1>& x, const string_literal<CharT2, N2>& y) NOEXCEPT;
4084 };
4085
4086 template <class CharT>
4087 CONSTCD11
4088 inline
4089 string_literal<CharT, 3>
4090 operator+(const string_literal<CharT, 2>& x, const string_literal<CharT, 2>& y) NOEXCEPT
4091 {
4092 return string_literal<CharT, 3>(x[0], y[0]);
4093 }
4094
4095 template <class CharT>
4096 CONSTCD11
4097 inline
4098 string_literal<CharT, 4>
4099 operator+(const string_literal<CharT, 3>& x, const string_literal<CharT, 2>& y) NOEXCEPT
4100 {
4101 return string_literal<CharT, 4>(x[0], x[1], y[0]);
4102 }
4103
4104 template <class CharT1, class CharT2, std::size_t N1, std::size_t N2>
4105 CONSTCD14
4106 inline
4107 string_literal<typename std::conditional<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>::type,
4108 N1 + N2 - 1>
4109 operator+(const string_literal<CharT1, N1>& x, const string_literal<CharT2, N2>& y) NOEXCEPT
4110 {
4111 using CT = typename std::conditional<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>::type;
4112
4113 string_literal<CT, N1 + N2 - 1> r;
4114 std::size_t i = 0;
4115 for (; i < N1-1; ++i)
4116 r.p_[i] = CT(x.p_[i]);
4117 for (std::size_t j = 0; j < N2; ++j, ++i)
4118 r.p_[i] = CT(y.p_[j]);
4119
4120 return r;
4121 }
4122
4123
4124 template <class CharT, class Traits, class Alloc, std::size_t N>
4125 inline
4126 std::basic_string<CharT, Traits, Alloc>
4127 operator+(std::basic_string<CharT, Traits, Alloc> x, const string_literal<CharT, N>& y)
4128 {
4129 x.append(y.data(), y.size());
4130 return x;
4131 }
4132
4133 #if __cplusplus >= 201402 && (!defined(__EDG_VERSION__) || __EDG_VERSION__ > 411) \
4134 && (!defined(__SUNPRO_CC) || __SUNPRO_CC > 0x5150)
4135
4136 template <class CharT,
4137 class = std::enable_if_t<std::is_same<CharT, char>{} ||
4138 std::is_same<CharT, wchar_t>{} ||
4139 std::is_same<CharT, char16_t>{} ||
4140 std::is_same<CharT, char32_t>{}>>
4141 CONSTCD14
4142 inline
4143 string_literal<CharT, 2>
4144 msl(CharT c) NOEXCEPT
4145 {
4146 return string_literal<CharT, 2>{c};
4147 }
4148
4149 CONSTCD14
4150 inline
4151 std::size_t
4152 to_string_len(std::intmax_t i)
4153 {
4154 std::size_t r = 0;
4155 do
4156 {
4157 i /= 10;
4158 ++r;
4159 } while (i > 0);
4160 return r;
4161 }
4162
4163 template <std::intmax_t N>
4164 CONSTCD14
4165 inline
4166 std::enable_if_t
4167 <
4168 N < 10,
4169 string_literal<char, to_string_len(N)+1>
4170 >
4171 msl() NOEXCEPT
4172 {
4173 return msl(char(N % 10 + '0'));
4174 }
4175
4176 template <std::intmax_t N>
4177 CONSTCD14
4178 inline
4179 std::enable_if_t
4180 <
4181 10 <= N,
4182 string_literal<char, to_string_len(N)+1>
4183 >
4184 msl() NOEXCEPT
4185 {
4186 return msl<N/10>() + msl(char(N % 10 + '0'));
4187 }
4188
4189 template <class CharT, std::intmax_t N, std::intmax_t D>
4190 CONSTCD14
4191 inline
4192 std::enable_if_t
4193 <
4194 std::ratio<N, D>::type::den != 1,
4195 string_literal<CharT, to_string_len(std::ratio<N, D>::type::num) +
4196 to_string_len(std::ratio<N, D>::type::den) + 4>
4197 >
4198 msl(std::ratio<N, D>) NOEXCEPT
4199 {
4200 using R = typename std::ratio<N, D>::type;
4201 return msl(CharT{'['}) + msl<R::num>() + msl(CharT{'/'}) +
4202 msl<R::den>() + msl(CharT{']'});
4203 }
4204
4205 template <class CharT, std::intmax_t N, std::intmax_t D>
4206 CONSTCD14
4207 inline
4208 std::enable_if_t
4209 <
4210 std::ratio<N, D>::type::den == 1,
4211 string_literal<CharT, to_string_len(std::ratio<N, D>::type::num) + 3>
4212 >
4213 msl(std::ratio<N, D>) NOEXCEPT
4214 {
4215 using R = typename std::ratio<N, D>::type;
4216 return msl(CharT{'['}) + msl<R::num>() + msl(CharT{']'});
4217 }
4218
4219
4220 #else // __cplusplus < 201402 || (defined(__EDG_VERSION__) && __EDG_VERSION__ <= 411)
4221
4222 inline
4223 std::string
4224 to_string(std::uint64_t x)
4225 {
4226 return std::to_string(x);
4227 }
4228
4229 template <class CharT>
4230 inline
4231 std::basic_string<CharT>
4232 to_string(std::uint64_t x)
4233 {
4234 auto y = std::to_string(x);
4235 return std::basic_string<CharT>(y.begin(), y.end());
4236 }
4237
4238 template <class CharT, std::intmax_t N, std::intmax_t D>
4239 inline
4240 typename std::enable_if
4241 <
4242 std::ratio<N, D>::type::den != 1,
4243 std::basic_string<CharT>
4244 >::type
4245 msl(std::ratio<N, D>)
4246 {
4247 using R = typename std::ratio<N, D>::type;
4248 return std::basic_string<CharT>(1, '[') + to_string<CharT>(R::num) + CharT{'/'} +
4249 to_string<CharT>(R::den) + CharT{']'};
4250 }
4251
4252 template <class CharT, std::intmax_t N, std::intmax_t D>
4253 inline
4254 typename std::enable_if
4255 <
4256 std::ratio<N, D>::type::den == 1,
4257 std::basic_string<CharT>
4258 >::type
4259 msl(std::ratio<N, D>)
4260 {
4261 using R = typename std::ratio<N, D>::type;
4262 return std::basic_string<CharT>(1, '[') + to_string<CharT>(R::num) + CharT{']'};
4263 }
4264
4265 #endif // __cplusplus < 201402 || (defined(__EDG_VERSION__) && __EDG_VERSION__ <= 411)
4266
4267 template <class CharT>
4268 CONSTCD11
4269 inline
4270 string_literal<CharT, 2>
4271 msl(std::atto) NOEXCEPT
4272 {
4273 return string_literal<CharT, 2>{'a'};
4274 }
4275
4276 template <class CharT>
4277 CONSTCD11
4278 inline
4279 string_literal<CharT, 2>
4280 msl(std::femto) NOEXCEPT
4281 {
4282 return string_literal<CharT, 2>{'f'};
4283 }
4284
4285 template <class CharT>
4286 CONSTCD11
4287 inline
4288 string_literal<CharT, 2>
4289 msl(std::pico) NOEXCEPT
4290 {
4291 return string_literal<CharT, 2>{'p'};
4292 }
4293
4294 template <class CharT>
4295 CONSTCD11
4296 inline
4297 string_literal<CharT, 2>
4298 msl(std::nano) NOEXCEPT
4299 {
4300 return string_literal<CharT, 2>{'n'};
4301 }
4302
4303 template <class CharT>
4304 CONSTCD11
4305 inline
4306 typename std::enable_if
4307 <
4308 std::is_same<CharT, char>::value,
4309 string_literal<char, 3>
4310 >::type
4311 msl(std::micro) NOEXCEPT
4312 {
4313 return string_literal<char, 3>{'\xC2', '\xB5'};
4314 }
4315
4316 template <class CharT>
4317 CONSTCD11
4318 inline
4319 typename std::enable_if
4320 <
4321 !std::is_same<CharT, char>::value,
4322 string_literal<CharT, 2>
4323 >::type
4324 msl(std::micro) NOEXCEPT
4325 {
4326 return string_literal<CharT, 2>{CharT{static_cast<unsigned char>('\xB5')}};
4327 }
4328
4329 template <class CharT>
4330 CONSTCD11
4331 inline
4332 string_literal<CharT, 2>
4333 msl(std::milli) NOEXCEPT
4334 {
4335 return string_literal<CharT, 2>{'m'};
4336 }
4337
4338 template <class CharT>
4339 CONSTCD11
4340 inline
4341 string_literal<CharT, 2>
4342 msl(std::centi) NOEXCEPT
4343 {
4344 return string_literal<CharT, 2>{'c'};
4345 }
4346
4347 template <class CharT>
4348 CONSTCD11
4349 inline
4350 string_literal<CharT, 3>
4351 msl(std::deca) NOEXCEPT
4352 {
4353 return string_literal<CharT, 3>{'d', 'a'};
4354 }
4355
4356 template <class CharT>
4357 CONSTCD11
4358 inline
4359 string_literal<CharT, 2>
4360 msl(std::deci) NOEXCEPT
4361 {
4362 return string_literal<CharT, 2>{'d'};
4363 }
4364
4365 template <class CharT>
4366 CONSTCD11
4367 inline
4368 string_literal<CharT, 2>
4369 msl(std::hecto) NOEXCEPT
4370 {
4371 return string_literal<CharT, 2>{'h'};
4372 }
4373
4374 template <class CharT>
4375 CONSTCD11
4376 inline
4377 string_literal<CharT, 2>
4378 msl(std::kilo) NOEXCEPT
4379 {
4380 return string_literal<CharT, 2>{'k'};
4381 }
4382
4383 template <class CharT>
4384 CONSTCD11
4385 inline
4386 string_literal<CharT, 2>
4387 msl(std::mega) NOEXCEPT
4388 {
4389 return string_literal<CharT, 2>{'M'};
4390 }
4391
4392 template <class CharT>
4393 CONSTCD11
4394 inline
4395 string_literal<CharT, 2>
4396 msl(std::giga) NOEXCEPT
4397 {
4398 return string_literal<CharT, 2>{'G'};
4399 }
4400
4401 template <class CharT>
4402 CONSTCD11
4403 inline
4404 string_literal<CharT, 2>
4405 msl(std::tera) NOEXCEPT
4406 {
4407 return string_literal<CharT, 2>{'T'};
4408 }
4409
4410 template <class CharT>
4411 CONSTCD11
4412 inline
4413 string_literal<CharT, 2>
4414 msl(std::peta) NOEXCEPT
4415 {
4416 return string_literal<CharT, 2>{'P'};
4417 }
4418
4419 template <class CharT>
4420 CONSTCD11
4421 inline
4422 string_literal<CharT, 2>
4423 msl(std::exa) NOEXCEPT
4424 {
4425 return string_literal<CharT, 2>{'E'};
4426 }
4427
4428 template <class CharT, class Period>
4429 CONSTCD11
4430 inline
4431 auto
4432 get_units(Period p)
4433 -> decltype(msl<CharT>(p) + string_literal<CharT, 2>{'s'})
4434 {
4435 return msl<CharT>(p) + string_literal<CharT, 2>{'s'};
4436 }
4437
4438 template <class CharT>
4439 CONSTCD11
4440 inline
4441 string_literal<CharT, 2>
4442 get_units(std::ratio<1>)
4443 {
4444 return string_literal<CharT, 2>{'s'};
4445 }
4446
4447 template <class CharT>
4448 CONSTCD11
4449 inline
4450 string_literal<CharT, 2>
4451 get_units(std::ratio<3600>)
4452 {
4453 return string_literal<CharT, 2>{'h'};
4454 }
4455
4456 template <class CharT>
4457 CONSTCD11
4458 inline
4459 string_literal<CharT, 4>
4460 get_units(std::ratio<60>)
4461 {
4462 return string_literal<CharT, 4>{'m', 'i', 'n'};
4463 }
4464
4465 template <class CharT>
4466 CONSTCD11
4467 inline
4468 string_literal<CharT, 2>
4469 get_units(std::ratio<86400>)
4470 {
4471 return string_literal<CharT, 2>{'d'};
4472 }
4473
4474 template <class CharT, class Traits = std::char_traits<CharT>>
4475 struct make_string;
4476
4477 template <>
4478 struct make_string<char>
4479 {
4480 template <class Rep>
4481 static
4482 std::string
4483 from(Rep n)
4484 {
4485 return std::to_string(n);
4486 }
4487 };
4488
4489 template <class Traits>
4490 struct make_string<char, Traits>
4491 {
4492 template <class Rep>
4493 static
4494 std::basic_string<char, Traits>
4495 from(Rep n)
4496 {
4497 auto s = std::to_string(n);
4498 return std::basic_string<char, Traits>(s.begin(), s.end());
4499 }
4500 };
4501
4502 template <>
4503 struct make_string<wchar_t>
4504 {
4505 template <class Rep>
4506 static
4507 std::wstring
4508 from(Rep n)
4509 {
4510 return std::to_wstring(n);
4511 }
4512 };
4513
4514 template <class Traits>
4515 struct make_string<wchar_t, Traits>
4516 {
4517 template <class Rep>
4518 static
4519 std::basic_string<wchar_t, Traits>
4520 from(Rep n)
4521 {
4522 auto s = std::to_wstring(n);
4523 return std::basic_string<wchar_t, Traits>(s.begin(), s.end());
4524 }
4525 };
4526
4527 } // namespace detail
4528
4529 // to_stream
4530
4531 CONSTDATA year nanyear{-32768};
4532
4533 template <class Duration>
4534 struct fields
4535 {
4536 year_month_day ymd{nanyear/0/0};
4537 weekday wd{8u};
4538 hh_mm_ss<Duration> tod{};
4539 bool has_tod = false;
4540
4541 fields() = default;
4542
4543 fields(year_month_day ymd_) : ymd(ymd_) {}
4544 fields(weekday wd_) : wd(wd_) {}
4545 fields(hh_mm_ss<Duration> tod_) : tod(tod_), has_tod(true) {}
4546
4547 fields(year_month_day ymd_, weekday wd_) : ymd(ymd_), wd(wd_) {}
4548 fields(year_month_day ymd_, hh_mm_ss<Duration> tod_) : ymd(ymd_), tod(tod_),
4549 has_tod(true) {}
4550
4551 fields(weekday wd_, hh_mm_ss<Duration> tod_) : wd(wd_), tod(tod_), has_tod(true) {}
4552
4553 fields(year_month_day ymd_, weekday wd_, hh_mm_ss<Duration> tod_)
4554 : ymd(ymd_)
4555 , wd(wd_)
4556 , tod(tod_)
4557 , has_tod(true)
4558 {}
4559 };
4560
4561 namespace detail
4562 {
4563
4564 template <class CharT, class Traits, class Duration>
4565 unsigned
4566 extract_weekday(std::basic_ostream<CharT, Traits>& os, const fields<Duration>& fds)
4567 {
4568 if (!fds.ymd.ok() && !fds.wd.ok())
4569 {
4570 // fds does not contain a valid weekday
4571 os.setstate(std::ios::failbit);
4572 return 8;
4573 }
4574 weekday wd;
4575 if (fds.ymd.ok())
4576 {
4577 wd = weekday{sys_days(fds.ymd)};
4578 if (fds.wd.ok() && wd != fds.wd)
4579 {
4580 // fds.ymd and fds.wd are inconsistent
4581 os.setstate(std::ios::failbit);
4582 return 8;
4583 }
4584 }
4585 else
4586 wd = fds.wd;
4587 return static_cast<unsigned>((wd - Sunday).count());
4588 }
4589
4590 template <class CharT, class Traits, class Duration>
4591 unsigned
4592 extract_month(std::basic_ostream<CharT, Traits>& os, const fields<Duration>& fds)
4593 {
4594 if (!fds.ymd.month().ok())
4595 {
4596 // fds does not contain a valid month
4597 os.setstate(std::ios::failbit);
4598 return 0;
4599 }
4600 return static_cast<unsigned>(fds.ymd.month());
4601 }
4602
4603 } // namespace detail
4604
4605 #if ONLY_C_LOCALE
4606
4607 namespace detail
4608 {
4609
4610 inline
4611 std::pair<const std::string*, const std::string*>
4612 weekday_names()
4613 {
4614 static const std::string nm[] =
4615 {
4616 "Sunday",
4617 "Monday",
4618 "Tuesday",
4619 "Wednesday",
4620 "Thursday",
4621 "Friday",
4622 "Saturday",
4623 "Sun",
4624 "Mon",
4625 "Tue",
4626 "Wed",
4627 "Thu",
4628 "Fri",
4629 "Sat"
4630 };
4631 return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0]));
4632 }
4633
4634 inline
4635 std::pair<const std::string*, const std::string*>
4636 month_names()
4637 {
4638 static const std::string nm[] =
4639 {
4640 "January",
4641 "February",
4642 "March",
4643 "April",
4644 "May",
4645 "June",
4646 "July",
4647 "August",
4648 "September",
4649 "October",
4650 "November",
4651 "December",
4652 "Jan",
4653 "Feb",
4654 "Mar",
4655 "Apr",
4656 "May",
4657 "Jun",
4658 "Jul",
4659 "Aug",
4660 "Sep",
4661 "Oct",
4662 "Nov",
4663 "Dec"
4664 };
4665 return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0]));
4666 }
4667
4668 inline
4669 std::pair<const std::string*, const std::string*>
4670 ampm_names()
4671 {
4672 static const std::string nm[] =
4673 {
4674 "AM",
4675 "PM"
4676 };
4677 return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0]));
4678 }
4679
4680 template <class CharT, class Traits, class FwdIter>
4681 FwdIter
4682 scan_keyword(std::basic_istream<CharT, Traits>& is, FwdIter kb, FwdIter ke)
4683 {
4684 size_t nkw = static_cast<size_t>(std::distance(kb, ke));
4685 const unsigned char doesnt_match = '\0';
4686 const unsigned char might_match = '\1';
4687 const unsigned char does_match = '\2';
4688 unsigned char statbuf[100];
4689 unsigned char* status = statbuf;
4690 std::unique_ptr<unsigned char, void(*)(void*)> stat_hold(0, free);
4691 if (nkw > sizeof(statbuf))
4692 {
4693 status = (unsigned char*)std::malloc(nkw);
4694 if (status == nullptr)
4695 throw std::bad_alloc();
4696 stat_hold.reset(status);
4697 }
4698 size_t n_might_match = nkw; // At this point, any keyword might match
4699 size_t n_does_match = 0; // but none of them definitely do
4700 // Initialize all statuses to might_match, except for "" keywords are does_match
4701 unsigned char* st = status;
4702 for (auto ky = kb; ky != ke; ++ky, ++st)
4703 {
4704 if (!ky->empty())
4705 *st = might_match;
4706 else
4707 {
4708 *st = does_match;
4709 --n_might_match;
4710 ++n_does_match;
4711 }
4712 }
4713 // While there might be a match, test keywords against the next CharT
4714 for (size_t indx = 0; is && n_might_match > 0; ++indx)
4715 {
4716 // Peek at the next CharT but don't consume it
4717 auto ic = is.peek();
4718 if (ic == EOF)
4719 {
4720 is.setstate(std::ios::eofbit);
4721 break;
4722 }
4723 auto c = static_cast<char>(toupper(ic));
4724 bool consume = false;
4725 // For each keyword which might match, see if the indx character is c
4726 // If a match if found, consume c
4727 // If a match is found, and that is the last character in the keyword,
4728 // then that keyword matches.
4729 // If the keyword doesn't match this character, then change the keyword
4730 // to doesn't match
4731 st = status;
4732 for (auto ky = kb; ky != ke; ++ky, ++st)
4733 {
4734 if (*st == might_match)
4735 {
4736 if (c == static_cast<char>(toupper((*ky)[indx])))
4737 {
4738 consume = true;
4739 if (ky->size() == indx+1)
4740 {
4741 *st = does_match;
4742 --n_might_match;
4743 ++n_does_match;
4744 }
4745 }
4746 else
4747 {
4748 *st = doesnt_match;
4749 --n_might_match;
4750 }
4751 }
4752 }
4753 // consume if we matched a character
4754 if (consume)
4755 {
4756 (void)is.get();
4757 // If we consumed a character and there might be a matched keyword that
4758 // was marked matched on a previous iteration, then such keywords
4759 // are now marked as not matching.
4760 if (n_might_match + n_does_match > 1)
4761 {
4762 st = status;
4763 for (auto ky = kb; ky != ke; ++ky, ++st)
4764 {
4765 if (*st == does_match && ky->size() != indx+1)
4766 {
4767 *st = doesnt_match;
4768 --n_does_match;
4769 }
4770 }
4771 }
4772 }
4773 }
4774 // We've exited the loop because we hit eof and/or we have no more "might matches".
4775 // Return the first matching result
4776 for (st = status; kb != ke; ++kb, ++st)
4777 if (*st == does_match)
4778 break;
4779 if (kb == ke)
4780 is.setstate(std::ios::failbit);
4781 return kb;
4782 }
4783
4784 } // namespace detail
4785
4786 #endif // ONLY_C_LOCALE
4787
4788 template <class CharT, class Traits, class Duration>
4789 std::basic_ostream<CharT, Traits>&
4790 to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
4791 const fields<Duration>& fds, const std::string* abbrev,
4792 const std::chrono::seconds* offset_sec)
4793 {
4794 #if ONLY_C_LOCALE
4795 using detail::weekday_names;
4796 using detail::month_names;
4797 using detail::ampm_names;
4798 #endif
4799 using detail::save_ostream;
4800 using detail::get_units;
4801 using detail::extract_weekday;
4802 using detail::extract_month;
4803 using std::ios;
4804 using std::chrono::duration_cast;
4805 using std::chrono::seconds;
4806 using std::chrono::minutes;
4807 using std::chrono::hours;
4808 date::detail::save_ostream<CharT, Traits> ss(os);
4809 os.fill(' ');
4810 os.flags(std::ios::skipws | std::ios::dec);
4811 os.width(0);
4812 tm tm{};
4813 bool insert_negative = fds.has_tod && fds.tod.to_duration() < Duration::zero();
4814 #if !ONLY_C_LOCALE
4815 auto& facet = std::use_facet<std::time_put<CharT>>(os.getloc());
4816 #endif
4817 const CharT* command = nullptr;
4818 CharT modified = CharT{};
4819 for (; *fmt; ++fmt)
4820 {
4821 switch (*fmt)
4822 {
4823 case 'a':
4824 case 'A':
4825 if (command)
4826 {
4827 if (modified == CharT{})
4828 {
4829 tm.tm_wday = static_cast<int>(extract_weekday(os, fds));
4830 if (os.fail())
4831 return os;
4832 #if !ONLY_C_LOCALE
4833 const CharT f[] = {'%', *fmt};
4834 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
4835 #else // ONLY_C_LOCALE
4836 os << weekday_names().first[tm.tm_wday+7*(*fmt == 'a')];
4837 #endif // ONLY_C_LOCALE
4838 }
4839 else
4840 {
4841 os << CharT{'%'} << modified << *fmt;
4842 modified = CharT{};
4843 }
4844 command = nullptr;
4845 }
4846 else
4847 os << *fmt;
4848 break;
4849 case 'b':
4850 case 'B':
4851 case 'h':
4852 if (command)
4853 {
4854 if (modified == CharT{})
4855 {
4856 tm.tm_mon = static_cast<int>(extract_month(os, fds)) - 1;
4857 #if !ONLY_C_LOCALE
4858 const CharT f[] = {'%', *fmt};
4859 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
4860 #else // ONLY_C_LOCALE
4861 os << month_names().first[tm.tm_mon+12*(*fmt != 'B')];
4862 #endif // ONLY_C_LOCALE
4863 }
4864 else
4865 {
4866 os << CharT{'%'} << modified << *fmt;
4867 modified = CharT{};
4868 }
4869 command = nullptr;
4870 }
4871 else
4872 os << *fmt;
4873 break;
4874 case 'c':
4875 case 'x':
4876 if (command)
4877 {
4878 if (modified == CharT{'O'})
4879 os << CharT{'%'} << modified << *fmt;
4880 else
4881 {
4882 if (!fds.ymd.ok())
4883 os.setstate(std::ios::failbit);
4884 if (*fmt == 'c' && !fds.has_tod)
4885 os.setstate(std::ios::failbit);
4886 #if !ONLY_C_LOCALE
4887 tm = std::tm{};
4888 auto const& ymd = fds.ymd;
4889 auto ld = local_days(ymd);
4890 if (*fmt == 'c')
4891 {
4892 tm.tm_sec = static_cast<int>(fds.tod.seconds().count());
4893 tm.tm_min = static_cast<int>(fds.tod.minutes().count());
4894 tm.tm_hour = static_cast<int>(fds.tod.hours().count());
4895 }
4896 tm.tm_mday = static_cast<int>(static_cast<unsigned>(ymd.day()));
4897 tm.tm_mon = static_cast<int>(extract_month(os, fds) - 1);
4898 tm.tm_year = static_cast<int>(ymd.year()) - 1900;
4899 tm.tm_wday = static_cast<int>(extract_weekday(os, fds));
4900 if (os.fail())
4901 return os;
4902 tm.tm_yday = static_cast<int>((ld - local_days(ymd.year()/1/1)).count());
4903 CharT f[3] = {'%'};
4904 auto fe = std::begin(f) + 1;
4905 if (modified == CharT{'E'})
4906 *fe++ = modified;
4907 *fe++ = *fmt;
4908 facet.put(os, os, os.fill(), &tm, std::begin(f), fe);
4909 #else // ONLY_C_LOCALE
4910 if (*fmt == 'c')
4911 {
4912 auto wd = static_cast<int>(extract_weekday(os, fds));
4913 os << weekday_names().first[static_cast<unsigned>(wd)+7]
4914 << ' ';
4915 os << month_names().first[extract_month(os, fds)-1+12] << ' ';
4916 auto d = static_cast<int>(static_cast<unsigned>(fds.ymd.day()));
4917 if (d < 10)
4918 os << ' ';
4919 os << d << ' '
4920 << make_time(duration_cast<seconds>(fds.tod.to_duration()))
4921 << ' ' << fds.ymd.year();
4922
4923 }
4924 else // *fmt == 'x'
4925 {
4926 auto const& ymd = fds.ymd;
4927 save_ostream<CharT, Traits> _(os);
4928 os.fill('0');
4929 os.flags(std::ios::dec | std::ios::right);
4930 os.width(2);
4931 os << static_cast<unsigned>(ymd.month()) << CharT{'/'};
4932 os.width(2);
4933 os << static_cast<unsigned>(ymd.day()) << CharT{'/'};
4934 os.width(2);
4935 os << static_cast<int>(ymd.year()) % 100;
4936 }
4937 #endif // ONLY_C_LOCALE
4938 }
4939 command = nullptr;
4940 modified = CharT{};
4941 }
4942 else
4943 os << *fmt;
4944 break;
4945 case 'C':
4946 if (command)
4947 {
4948 if (modified == CharT{'O'})
4949 os << CharT{'%'} << modified << *fmt;
4950 else
4951 {
4952 if (!fds.ymd.year().ok())
4953 os.setstate(std::ios::failbit);
4954 auto y = static_cast<int>(fds.ymd.year());
4955 #if !ONLY_C_LOCALE
4956 if (modified == CharT{})
4957 #endif
4958 {
4959 save_ostream<CharT, Traits> _(os);
4960 os.fill('0');
4961 os.flags(std::ios::dec | std::ios::right);
4962 if (y >= 0)
4963 {
4964 os.width(2);
4965 os << y/100;
4966 }
4967 else
4968 {
4969 os << CharT{'-'};
4970 os.width(2);
4971 os << -(y-99)/100;
4972 }
4973 }
4974 #if !ONLY_C_LOCALE
4975 else if (modified == CharT{'E'})
4976 {
4977 tm.tm_year = y - 1900;
4978 CharT f[3] = {'%', 'E', 'C'};
4979 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
4980 }
4981 #endif
4982 }
4983 command = nullptr;
4984 modified = CharT{};
4985 }
4986 else
4987 os << *fmt;
4988 break;
4989 case 'd':
4990 case 'e':
4991 if (command)
4992 {
4993 if (modified == CharT{'E'})
4994 os << CharT{'%'} << modified << *fmt;
4995 else
4996 {
4997 if (!fds.ymd.day().ok())
4998 os.setstate(std::ios::failbit);
4999 auto d = static_cast<int>(static_cast<unsigned>(fds.ymd.day()));
5000 #if !ONLY_C_LOCALE
5001 if (modified == CharT{})
5002 #endif
5003 {
5004 save_ostream<CharT, Traits> _(os);
5005 if (*fmt == CharT{'d'})
5006 os.fill('0');
5007 else
5008 os.fill(' ');
5009 os.flags(std::ios::dec | std::ios::right);
5010 os.width(2);
5011 os << d;
5012 }
5013 #if !ONLY_C_LOCALE
5014 else if (modified == CharT{'O'})
5015 {
5016 tm.tm_mday = d;
5017 CharT f[3] = {'%', 'O', *fmt};
5018 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
5019 }
5020 #endif
5021 }
5022 command = nullptr;
5023 modified = CharT{};
5024 }
5025 else
5026 os << *fmt;
5027 break;
5028 case 'D':
5029 if (command)
5030 {
5031 if (modified == CharT{})
5032 {
5033 if (!fds.ymd.ok())
5034 os.setstate(std::ios::failbit);
5035 auto const& ymd = fds.ymd;
5036 save_ostream<CharT, Traits> _(os);
5037 os.fill('0');
5038 os.flags(std::ios::dec | std::ios::right);
5039 os.width(2);
5040 os << static_cast<unsigned>(ymd.month()) << CharT{'/'};
5041 os.width(2);
5042 os << static_cast<unsigned>(ymd.day()) << CharT{'/'};
5043 os.width(2);
5044 os << static_cast<int>(ymd.year()) % 100;
5045 }
5046 else
5047 {
5048 os << CharT{'%'} << modified << *fmt;
5049 modified = CharT{};
5050 }
5051 command = nullptr;
5052 }
5053 else
5054 os << *fmt;
5055 break;
5056 case 'F':
5057 if (command)
5058 {
5059 if (modified == CharT{})
5060 {
5061 if (!fds.ymd.ok())
5062 os.setstate(std::ios::failbit);
5063 auto const& ymd = fds.ymd;
5064 save_ostream<CharT, Traits> _(os);
5065 os.fill('0');
5066 os.flags(std::ios::dec | std::ios::right);
5067 os.width(4);
5068 os << static_cast<int>(ymd.year()) << CharT{'-'};
5069 os.width(2);
5070 os << static_cast<unsigned>(ymd.month()) << CharT{'-'};
5071 os.width(2);
5072 os << static_cast<unsigned>(ymd.day());
5073 }
5074 else
5075 {
5076 os << CharT{'%'} << modified << *fmt;
5077 modified = CharT{};
5078 }
5079 command = nullptr;
5080 }
5081 else
5082 os << *fmt;
5083 break;
5084 case 'g':
5085 case 'G':
5086 if (command)
5087 {
5088 if (modified == CharT{})
5089 {
5090 if (!fds.ymd.ok())
5091 os.setstate(std::ios::failbit);
5092 auto ld = local_days(fds.ymd);
5093 auto y = year_month_day{ld + days{3}}.year();
5094 auto start = local_days((y-years{1})/December/Thursday[last]) +
5095 (Monday-Thursday);
5096 if (ld < start)
5097 --y;
5098 if (*fmt == CharT{'G'})
5099 os << y;
5100 else
5101 {
5102 save_ostream<CharT, Traits> _(os);
5103 os.fill('0');
5104 os.flags(std::ios::dec | std::ios::right);
5105 os.width(2);
5106 os << std::abs(static_cast<int>(y)) % 100;
5107 }
5108 }
5109 else
5110 {
5111 os << CharT{'%'} << modified << *fmt;
5112 modified = CharT{};
5113 }
5114 command = nullptr;
5115 }
5116 else
5117 os << *fmt;
5118 break;
5119 case 'H':
5120 case 'I':
5121 if (command)
5122 {
5123 if (modified == CharT{'E'})
5124 os << CharT{'%'} << modified << *fmt;
5125 else
5126 {
5127 if (!fds.has_tod)
5128 os.setstate(std::ios::failbit);
5129 if (insert_negative)
5130 {
5131 os << '-';
5132 insert_negative = false;
5133 }
5134 auto hms = fds.tod;
5135 #if !ONLY_C_LOCALE
5136 if (modified == CharT{})
5137 #endif
5138 {
5139 auto h = *fmt == CharT{'I'} ? date::make12(hms.hours()) : hms.hours();
5140 if (h < hours{10})
5141 os << CharT{'0'};
5142 os << h.count();
5143 }
5144 #if !ONLY_C_LOCALE
5145 else if (modified == CharT{'O'})
5146 {
5147 const CharT f[] = {'%', modified, *fmt};
5148 tm.tm_hour = static_cast<int>(hms.hours().count());
5149 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
5150 }
5151 #endif
5152 }
5153 modified = CharT{};
5154 command = nullptr;
5155 }
5156 else
5157 os << *fmt;
5158 break;
5159 case 'j':
5160 if (command)
5161 {
5162 if (modified == CharT{})
5163 {
5164 if (fds.ymd.ok() || fds.has_tod)
5165 {
5166 days doy;
5167 if (fds.ymd.ok())
5168 {
5169 auto ld = local_days(fds.ymd);
5170 auto y = fds.ymd.year();
5171 doy = ld - local_days(y/January/1) + days{1};
5172 }
5173 else
5174 {
5175 doy = duration_cast<days>(fds.tod.to_duration());
5176 }
5177 save_ostream<CharT, Traits> _(os);
5178 os.fill('0');
5179 os.flags(std::ios::dec | std::ios::right);
5180 os.width(3);
5181 os << doy.count();
5182 }
5183 else
5184 {
5185 os.setstate(std::ios::failbit);
5186 }
5187 }
5188 else
5189 {
5190 os << CharT{'%'} << modified << *fmt;
5191 modified = CharT{};
5192 }
5193 command = nullptr;
5194 }
5195 else
5196 os << *fmt;
5197 break;
5198 case 'm':
5199 if (command)
5200 {
5201 if (modified == CharT{'E'})
5202 os << CharT{'%'} << modified << *fmt;
5203 else
5204 {
5205 if (!fds.ymd.month().ok())
5206 os.setstate(std::ios::failbit);
5207 auto m = static_cast<unsigned>(fds.ymd.month());
5208 #if !ONLY_C_LOCALE
5209 if (modified == CharT{})
5210 #endif
5211 {
5212 if (m < 10)
5213 os << CharT{'0'};
5214 os << m;
5215 }
5216 #if !ONLY_C_LOCALE
5217 else if (modified == CharT{'O'})
5218 {
5219 const CharT f[] = {'%', modified, *fmt};
5220 tm.tm_mon = static_cast<int>(m-1);
5221 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
5222 }
5223 #endif
5224 }
5225 modified = CharT{};
5226 command = nullptr;
5227 }
5228 else
5229 os << *fmt;
5230 break;
5231 case 'M':
5232 if (command)
5233 {
5234 if (modified == CharT{'E'})
5235 os << CharT{'%'} << modified << *fmt;
5236 else
5237 {
5238 if (!fds.has_tod)
5239 os.setstate(std::ios::failbit);
5240 if (insert_negative)
5241 {
5242 os << '-';
5243 insert_negative = false;
5244 }
5245 #if !ONLY_C_LOCALE
5246 if (modified == CharT{})
5247 #endif
5248 {
5249 if (fds.tod.minutes() < minutes{10})
5250 os << CharT{'0'};
5251 os << fds.tod.minutes().count();
5252 }
5253 #if !ONLY_C_LOCALE
5254 else if (modified == CharT{'O'})
5255 {
5256 const CharT f[] = {'%', modified, *fmt};
5257 tm.tm_min = static_cast<int>(fds.tod.minutes().count());
5258 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
5259 }
5260 #endif
5261 }
5262 modified = CharT{};
5263 command = nullptr;
5264 }
5265 else
5266 os << *fmt;
5267 break;
5268 case 'n':
5269 if (command)
5270 {
5271 if (modified == CharT{})
5272 os << CharT{'\n'};
5273 else
5274 {
5275 os << CharT{'%'} << modified << *fmt;
5276 modified = CharT{};
5277 }
5278 command = nullptr;
5279 }
5280 else
5281 os << *fmt;
5282 break;
5283 case 'p':
5284 if (command)
5285 {
5286 if (modified == CharT{})
5287 {
5288 if (!fds.has_tod)
5289 os.setstate(std::ios::failbit);
5290 #if !ONLY_C_LOCALE
5291 const CharT f[] = {'%', *fmt};
5292 tm.tm_hour = static_cast<int>(fds.tod.hours().count());
5293 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
5294 #else
5295 if (date::is_am(fds.tod.hours()))
5296 os << ampm_names().first[0];
5297 else
5298 os << ampm_names().first[1];
5299 #endif
5300 }
5301 else
5302 {
5303 os << CharT{'%'} << modified << *fmt;
5304 }
5305 modified = CharT{};
5306 command = nullptr;
5307 }
5308 else
5309 os << *fmt;
5310 break;
5311 case 'Q':
5312 case 'q':
5313 if (command)
5314 {
5315 if (modified == CharT{})
5316 {
5317 if (!fds.has_tod)
5318 os.setstate(std::ios::failbit);
5319 auto d = fds.tod.to_duration();
5320 if (*fmt == 'q')
5321 os << get_units<CharT>(typename decltype(d)::period::type{});
5322 else
5323 os << d.count();
5324 }
5325 else
5326 {
5327 os << CharT{'%'} << modified << *fmt;
5328 }
5329 modified = CharT{};
5330 command = nullptr;
5331 }
5332 else
5333 os << *fmt;
5334 break;
5335 case 'r':
5336 if (command)
5337 {
5338 if (modified == CharT{})
5339 {
5340 if (!fds.has_tod)
5341 os.setstate(std::ios::failbit);
5342 #if !ONLY_C_LOCALE
5343 const CharT f[] = {'%', *fmt};
5344 tm.tm_hour = static_cast<int>(fds.tod.hours().count());
5345 tm.tm_min = static_cast<int>(fds.tod.minutes().count());
5346 tm.tm_sec = static_cast<int>(fds.tod.seconds().count());
5347 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
5348 #else
5349 hh_mm_ss<seconds> tod(duration_cast<seconds>(fds.tod.to_duration()));
5350 save_ostream<CharT, Traits> _(os);
5351 os.fill('0');
5352 os.width(2);
5353 os << date::make12(tod.hours()).count() << CharT{':'};
5354 os.width(2);
5355 os << tod.minutes().count() << CharT{':'};
5356 os.width(2);
5357 os << tod.seconds().count() << CharT{' '};
5358 if (date::is_am(tod.hours()))
5359 os << ampm_names().first[0];
5360 else
5361 os << ampm_names().first[1];
5362 #endif
5363 }
5364 else
5365 {
5366 os << CharT{'%'} << modified << *fmt;
5367 }
5368 modified = CharT{};
5369 command = nullptr;
5370 }
5371 else
5372 os << *fmt;
5373 break;
5374 case 'R':
5375 if (command)
5376 {
5377 if (modified == CharT{})
5378 {
5379 if (!fds.has_tod)
5380 os.setstate(std::ios::failbit);
5381 if (fds.tod.hours() < hours{10})
5382 os << CharT{'0'};
5383 os << fds.tod.hours().count() << CharT{':'};
5384 if (fds.tod.minutes() < minutes{10})
5385 os << CharT{'0'};
5386 os << fds.tod.minutes().count();
5387 }
5388 else
5389 {
5390 os << CharT{'%'} << modified << *fmt;
5391 modified = CharT{};
5392 }
5393 command = nullptr;
5394 }
5395 else
5396 os << *fmt;
5397 break;
5398 case 'S':
5399 if (command)
5400 {
5401 if (modified == CharT{'E'})
5402 os << CharT{'%'} << modified << *fmt;
5403 else
5404 {
5405 if (!fds.has_tod)
5406 os.setstate(std::ios::failbit);
5407 if (insert_negative)
5408 {
5409 os << '-';
5410 insert_negative = false;
5411 }
5412 #if !ONLY_C_LOCALE
5413 if (modified == CharT{})
5414 #endif
5415 {
5416 os << fds.tod.s_;
5417 }
5418 #if !ONLY_C_LOCALE
5419 else if (modified == CharT{'O'})
5420 {
5421 const CharT f[] = {'%', modified, *fmt};
5422 tm.tm_sec = static_cast<int>(fds.tod.s_.seconds().count());
5423 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
5424 }
5425 #endif
5426 }
5427 modified = CharT{};
5428 command = nullptr;
5429 }
5430 else
5431 os << *fmt;
5432 break;
5433 case 't':
5434 if (command)
5435 {
5436 if (modified == CharT{})
5437 os << CharT{'\t'};
5438 else
5439 {
5440 os << CharT{'%'} << modified << *fmt;
5441 modified = CharT{};
5442 }
5443 command = nullptr;
5444 }
5445 else
5446 os << *fmt;
5447 break;
5448 case 'T':
5449 if (command)
5450 {
5451 if (modified == CharT{})
5452 {
5453 if (!fds.has_tod)
5454 os.setstate(std::ios::failbit);
5455 os << fds.tod;
5456 }
5457 else
5458 {
5459 os << CharT{'%'} << modified << *fmt;
5460 modified = CharT{};
5461 }
5462 command = nullptr;
5463 }
5464 else
5465 os << *fmt;
5466 break;
5467 case 'u':
5468 if (command)
5469 {
5470 if (modified == CharT{'E'})
5471 os << CharT{'%'} << modified << *fmt;
5472 else
5473 {
5474 auto wd = extract_weekday(os, fds);
5475 #if !ONLY_C_LOCALE
5476 if (modified == CharT{})
5477 #endif
5478 {
5479 os << (wd != 0 ? wd : 7u);
5480 }
5481 #if !ONLY_C_LOCALE
5482 else if (modified == CharT{'O'})
5483 {
5484 const CharT f[] = {'%', modified, *fmt};
5485 tm.tm_wday = static_cast<int>(wd);
5486 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
5487 }
5488 #endif
5489 }
5490 modified = CharT{};
5491 command = nullptr;
5492 }
5493 else
5494 os << *fmt;
5495 break;
5496 case 'U':
5497 if (command)
5498 {
5499 if (modified == CharT{'E'})
5500 os << CharT{'%'} << modified << *fmt;
5501 else
5502 {
5503 auto const& ymd = fds.ymd;
5504 if (!ymd.ok())
5505 os.setstate(std::ios::failbit);
5506 auto ld = local_days(ymd);
5507 #if !ONLY_C_LOCALE
5508 if (modified == CharT{})
5509 #endif
5510 {
5511 auto st = local_days(Sunday[1]/January/ymd.year());
5512 if (ld < st)
5513 os << CharT{'0'} << CharT{'0'};
5514 else
5515 {
5516 auto wn = duration_cast<weeks>(ld - st).count() + 1;
5517 if (wn < 10)
5518 os << CharT{'0'};
5519 os << wn;
5520 }
5521 }
5522 #if !ONLY_C_LOCALE
5523 else if (modified == CharT{'O'})
5524 {
5525 const CharT f[] = {'%', modified, *fmt};
5526 tm.tm_year = static_cast<int>(ymd.year()) - 1900;
5527 tm.tm_wday = static_cast<int>(extract_weekday(os, fds));
5528 if (os.fail())
5529 return os;
5530 tm.tm_yday = static_cast<int>((ld - local_days(ymd.year()/1/1)).count());
5531 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
5532 }
5533 #endif
5534 }
5535 modified = CharT{};
5536 command = nullptr;
5537 }
5538 else
5539 os << *fmt;
5540 break;
5541 case 'V':
5542 if (command)
5543 {
5544 if (modified == CharT{'E'})
5545 os << CharT{'%'} << modified << *fmt;
5546 else
5547 {
5548 if (!fds.ymd.ok())
5549 os.setstate(std::ios::failbit);
5550 auto ld = local_days(fds.ymd);
5551 #if !ONLY_C_LOCALE
5552 if (modified == CharT{})
5553 #endif
5554 {
5555 auto y = year_month_day{ld + days{3}}.year();
5556 auto st = local_days((y-years{1})/12/Thursday[last]) +
5557 (Monday-Thursday);
5558 if (ld < st)
5559 {
5560 --y;
5561 st = local_days((y - years{1})/12/Thursday[last]) +
5562 (Monday-Thursday);
5563 }
5564 auto wn = duration_cast<weeks>(ld - st).count() + 1;
5565 if (wn < 10)
5566 os << CharT{'0'};
5567 os << wn;
5568 }
5569 #if !ONLY_C_LOCALE
5570 else if (modified == CharT{'O'})
5571 {
5572 const CharT f[] = {'%', modified, *fmt};
5573 auto const& ymd = fds.ymd;
5574 tm.tm_year = static_cast<int>(ymd.year()) - 1900;
5575 tm.tm_wday = static_cast<int>(extract_weekday(os, fds));
5576 if (os.fail())
5577 return os;
5578 tm.tm_yday = static_cast<int>((ld - local_days(ymd.year()/1/1)).count());
5579 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
5580 }
5581 #endif
5582 }
5583 modified = CharT{};
5584 command = nullptr;
5585 }
5586 else
5587 os << *fmt;
5588 break;
5589 case 'w':
5590 if (command)
5591 {
5592 auto wd = extract_weekday(os, fds);
5593 if (os.fail())
5594 return os;
5595 #if !ONLY_C_LOCALE
5596 if (modified == CharT{})
5597 #else
5598 if (modified != CharT{'E'})
5599 #endif
5600 {
5601 os << wd;
5602 }
5603 #if !ONLY_C_LOCALE
5604 else if (modified == CharT{'O'})
5605 {
5606 const CharT f[] = {'%', modified, *fmt};
5607 tm.tm_wday = static_cast<int>(wd);
5608 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
5609 }
5610 #endif
5611 else
5612 {
5613 os << CharT{'%'} << modified << *fmt;
5614 }
5615 modified = CharT{};
5616 command = nullptr;
5617 }
5618 else
5619 os << *fmt;
5620 break;
5621 case 'W':
5622 if (command)
5623 {
5624 if (modified == CharT{'E'})
5625 os << CharT{'%'} << modified << *fmt;
5626 else
5627 {
5628 auto const& ymd = fds.ymd;
5629 if (!ymd.ok())
5630 os.setstate(std::ios::failbit);
5631 auto ld = local_days(ymd);
5632 #if !ONLY_C_LOCALE
5633 if (modified == CharT{})
5634 #endif
5635 {
5636 auto st = local_days(Monday[1]/January/ymd.year());
5637 if (ld < st)
5638 os << CharT{'0'} << CharT{'0'};
5639 else
5640 {
5641 auto wn = duration_cast<weeks>(ld - st).count() + 1;
5642 if (wn < 10)
5643 os << CharT{'0'};
5644 os << wn;
5645 }
5646 }
5647 #if !ONLY_C_LOCALE
5648 else if (modified == CharT{'O'})
5649 {
5650 const CharT f[] = {'%', modified, *fmt};
5651 tm.tm_year = static_cast<int>(ymd.year()) - 1900;
5652 tm.tm_wday = static_cast<int>(extract_weekday(os, fds));
5653 if (os.fail())
5654 return os;
5655 tm.tm_yday = static_cast<int>((ld - local_days(ymd.year()/1/1)).count());
5656 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
5657 }
5658 #endif
5659 }
5660 modified = CharT{};
5661 command = nullptr;
5662 }
5663 else
5664 os << *fmt;
5665 break;
5666 case 'X':
5667 if (command)
5668 {
5669 if (modified == CharT{'O'})
5670 os << CharT{'%'} << modified << *fmt;
5671 else
5672 {
5673 if (!fds.has_tod)
5674 os.setstate(std::ios::failbit);
5675 #if !ONLY_C_LOCALE
5676 tm = std::tm{};
5677 tm.tm_sec = static_cast<int>(fds.tod.seconds().count());
5678 tm.tm_min = static_cast<int>(fds.tod.minutes().count());
5679 tm.tm_hour = static_cast<int>(fds.tod.hours().count());
5680 CharT f[3] = {'%'};
5681 auto fe = std::begin(f) + 1;
5682 if (modified == CharT{'E'})
5683 *fe++ = modified;
5684 *fe++ = *fmt;
5685 facet.put(os, os, os.fill(), &tm, std::begin(f), fe);
5686 #else
5687 os << fds.tod;
5688 #endif
5689 }
5690 command = nullptr;
5691 modified = CharT{};
5692 }
5693 else
5694 os << *fmt;
5695 break;
5696 case 'y':
5697 if (command)
5698 {
5699 if (!fds.ymd.year().ok())
5700 os.setstate(std::ios::failbit);
5701 auto y = static_cast<int>(fds.ymd.year());
5702 #if !ONLY_C_LOCALE
5703 if (modified == CharT{})
5704 {
5705 #endif
5706 y = std::abs(y) % 100;
5707 if (y < 10)
5708 os << CharT{'0'};
5709 os << y;
5710 #if !ONLY_C_LOCALE
5711 }
5712 else
5713 {
5714 const CharT f[] = {'%', modified, *fmt};
5715 tm.tm_year = y - 1900;
5716 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
5717 }
5718 #endif
5719 modified = CharT{};
5720 command = nullptr;
5721 }
5722 else
5723 os << *fmt;
5724 break;
5725 case 'Y':
5726 if (command)
5727 {
5728 if (modified == CharT{'O'})
5729 os << CharT{'%'} << modified << *fmt;
5730 else
5731 {
5732 if (!fds.ymd.year().ok())
5733 os.setstate(std::ios::failbit);
5734 auto y = fds.ymd.year();
5735 #if !ONLY_C_LOCALE
5736 if (modified == CharT{})
5737 #endif
5738 {
5739 os << y;
5740 }
5741 #if !ONLY_C_LOCALE
5742 else if (modified == CharT{'E'})
5743 {
5744 const CharT f[] = {'%', modified, *fmt};
5745 tm.tm_year = static_cast<int>(y) - 1900;
5746 facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
5747 }
5748 #endif
5749 }
5750 modified = CharT{};
5751 command = nullptr;
5752 }
5753 else
5754 os << *fmt;
5755 break;
5756 case 'z':
5757 if (command)
5758 {
5759 if (offset_sec == nullptr)
5760 {
5761 // Can not format %z with unknown offset
5762 os.setstate(ios::failbit);
5763 return os;
5764 }
5765 auto m = duration_cast<minutes>(*offset_sec);
5766 auto neg = m < minutes{0};
5767 m = date::abs(m);
5768 auto h = duration_cast<hours>(m);
5769 m -= h;
5770 if (neg)
5771 os << CharT{'-'};
5772 else
5773 os << CharT{'+'};
5774 if (h < hours{10})
5775 os << CharT{'0'};
5776 os << h.count();
5777 if (modified != CharT{})
5778 os << CharT{':'};
5779 if (m < minutes{10})
5780 os << CharT{'0'};
5781 os << m.count();
5782 command = nullptr;
5783 modified = CharT{};
5784 }
5785 else
5786 os << *fmt;
5787 break;
5788 case 'Z':
5789 if (command)
5790 {
5791 if (modified == CharT{})
5792 {
5793 if (abbrev == nullptr)
5794 {
5795 // Can not format %Z with unknown time_zone
5796 os.setstate(ios::failbit);
5797 return os;
5798 }
5799 for (auto c : *abbrev)
5800 os << CharT(c);
5801 }
5802 else
5803 {
5804 os << CharT{'%'} << modified << *fmt;
5805 modified = CharT{};
5806 }
5807 command = nullptr;
5808 }
5809 else
5810 os << *fmt;
5811 break;
5812 case 'E':
5813 case 'O':
5814 if (command)
5815 {
5816 if (modified == CharT{})
5817 {
5818 modified = *fmt;
5819 }
5820 else
5821 {
5822 os << CharT{'%'} << modified << *fmt;
5823 command = nullptr;
5824 modified = CharT{};
5825 }
5826 }
5827 else
5828 os << *fmt;
5829 break;
5830 case '%':
5831 if (command)
5832 {
5833 if (modified == CharT{})
5834 {
5835 os << CharT{'%'};
5836 command = nullptr;
5837 }
5838 else
5839 {
5840 os << CharT{'%'} << modified << CharT{'%'};
5841 command = nullptr;
5842 modified = CharT{};
5843 }
5844 }
5845 else
5846 command = fmt;
5847 break;
5848 default:
5849 if (command)
5850 {
5851 os << CharT{'%'};
5852 command = nullptr;
5853 }
5854 if (modified != CharT{})
5855 {
5856 os << modified;
5857 modified = CharT{};
5858 }
5859 os << *fmt;
5860 break;
5861 }
5862 }
5863 if (command)
5864 os << CharT{'%'};
5865 if (modified != CharT{})
5866 os << modified;
5867 return os;
5868 }
5869
5870 template <class CharT, class Traits>
5871 inline
5872 std::basic_ostream<CharT, Traits>&
5873 to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt, const year& y)
5874 {
5875 using CT = std::chrono::seconds;
5876 fields<CT> fds{y/0/0};
5877 return to_stream(os, fmt, fds);
5878 }
5879
5880 template <class CharT, class Traits>
5881 inline
5882 std::basic_ostream<CharT, Traits>&
5883 to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt, const month& m)
5884 {
5885 using CT = std::chrono::seconds;
5886 fields<CT> fds{m/0/nanyear};
5887 return to_stream(os, fmt, fds);
5888 }
5889
5890 template <class CharT, class Traits>
5891 inline
5892 std::basic_ostream<CharT, Traits>&
5893 to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt, const day& d)
5894 {
5895 using CT = std::chrono::seconds;
5896 fields<CT> fds{d/0/nanyear};
5897 return to_stream(os, fmt, fds);
5898 }
5899
5900 template <class CharT, class Traits>
5901 inline
5902 std::basic_ostream<CharT, Traits>&
5903 to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt, const weekday& wd)
5904 {
5905 using CT = std::chrono::seconds;
5906 fields<CT> fds{wd};
5907 return to_stream(os, fmt, fds);
5908 }
5909
5910 template <class CharT, class Traits>
5911 inline
5912 std::basic_ostream<CharT, Traits>&
5913 to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt, const year_month& ym)
5914 {
5915 using CT = std::chrono::seconds;
5916 fields<CT> fds{ym/0};
5917 return to_stream(os, fmt, fds);
5918 }
5919
5920 template <class CharT, class Traits>
5921 inline
5922 std::basic_ostream<CharT, Traits>&
5923 to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt, const month_day& md)
5924 {
5925 using CT = std::chrono::seconds;
5926 fields<CT> fds{md/nanyear};
5927 return to_stream(os, fmt, fds);
5928 }
5929
5930 template <class CharT, class Traits>
5931 inline
5932 std::basic_ostream<CharT, Traits>&
5933 to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
5934 const year_month_day& ymd)
5935 {
5936 using CT = std::chrono::seconds;
5937 fields<CT> fds{ymd};
5938 return to_stream(os, fmt, fds);
5939 }
5940
5941 template <class CharT, class Traits, class Rep, class Period>
5942 inline
5943 std::basic_ostream<CharT, Traits>&
5944 to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
5945 const std::chrono::duration<Rep, Period>& d)
5946 {
5947 using Duration = std::chrono::duration<Rep, Period>;
5948 using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
5949 fields<CT> fds{hh_mm_ss<CT>{d}};
5950 return to_stream(os, fmt, fds);
5951 }
5952
5953 template <class CharT, class Traits, class Duration>
5954 std::basic_ostream<CharT, Traits>&
5955 to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
5956 const local_time<Duration>& tp, const std::string* abbrev = nullptr,
5957 const std::chrono::seconds* offset_sec = nullptr)
5958 {
5959 using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
5960 auto ld = floor<days>(tp);
5961 fields<CT> fds{year_month_day{ld}, hh_mm_ss<CT>{tp-local_seconds{ld}}};
5962 return to_stream(os, fmt, fds, abbrev, offset_sec);
5963 }
5964
5965 template <class CharT, class Traits, class Duration>
5966 std::basic_ostream<CharT, Traits>&
5967 to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
5968 const sys_time<Duration>& tp)
5969 {
5970 using std::chrono::seconds;
5971 using CT = typename std::common_type<Duration, seconds>::type;
5972 const std::string abbrev("UTC");
5973 CONSTDATA seconds offset{0};
5974 auto sd = floor<days>(tp);
5975 fields<CT> fds{year_month_day{sd}, hh_mm_ss<CT>{tp-sys_seconds{sd}}};
5976 return to_stream(os, fmt, fds, &abbrev, &offset);
5977 }
5978
5979 // format
5980
5981 template <class CharT, class Streamable>
5982 auto
5983 format(const std::locale& loc, const CharT* fmt, const Streamable& tp)
5984 -> decltype(to_stream(std::declval<std::basic_ostream<CharT>&>(), fmt, tp),
5985 std::basic_string<CharT>{})
5986 {
5987 std::basic_ostringstream<CharT> os;
5988 os.exceptions(std::ios::failbit | std::ios::badbit);
5989 os.imbue(loc);
5990 to_stream(os, fmt, tp);
5991 return os.str();
5992 }
5993
5994 template <class CharT, class Streamable>
5995 auto
5996 format(const CharT* fmt, const Streamable& tp)
5997 -> decltype(to_stream(std::declval<std::basic_ostream<CharT>&>(), fmt, tp),
5998 std::basic_string<CharT>{})
5999 {
6000 std::basic_ostringstream<CharT> os;
6001 os.exceptions(std::ios::failbit | std::ios::badbit);
6002 to_stream(os, fmt, tp);
6003 return os.str();
6004 }
6005
6006 template <class CharT, class Traits, class Alloc, class Streamable>
6007 auto
6008 format(const std::locale& loc, const std::basic_string<CharT, Traits, Alloc>& fmt,
6009 const Streamable& tp)
6010 -> decltype(to_stream(std::declval<std::basic_ostream<CharT, Traits>&>(), fmt.c_str(), tp),
6011 std::basic_string<CharT, Traits, Alloc>{})
6012 {
6013 std::basic_ostringstream<CharT, Traits, Alloc> os;
6014 os.exceptions(std::ios::failbit | std::ios::badbit);
6015 os.imbue(loc);
6016 to_stream(os, fmt.c_str(), tp);
6017 return os.str();
6018 }
6019
6020 template <class CharT, class Traits, class Alloc, class Streamable>
6021 auto
6022 format(const std::basic_string<CharT, Traits, Alloc>& fmt, const Streamable& tp)
6023 -> decltype(to_stream(std::declval<std::basic_ostream<CharT, Traits>&>(), fmt.c_str(), tp),
6024 std::basic_string<CharT, Traits, Alloc>{})
6025 {
6026 std::basic_ostringstream<CharT, Traits, Alloc> os;
6027 os.exceptions(std::ios::failbit | std::ios::badbit);
6028 to_stream(os, fmt.c_str(), tp);
6029 return os.str();
6030 }
6031
6032 // parse
6033
6034 namespace detail
6035 {
6036
6037 template <class CharT, class Traits>
6038 bool
6039 read_char(std::basic_istream<CharT, Traits>& is, CharT fmt, std::ios::iostate& err)
6040 {
6041 auto ic = is.get();
6042 if (Traits::eq_int_type(ic, Traits::eof()) ||
6043 !Traits::eq(Traits::to_char_type(ic), fmt))
6044 {
6045 err |= std::ios::failbit;
6046 is.setstate(std::ios::failbit);
6047 return false;
6048 }
6049 return true;
6050 }
6051
6052 template <class CharT, class Traits>
6053 unsigned
6054 read_unsigned(std::basic_istream<CharT, Traits>& is, unsigned m = 1, unsigned M = 10)
6055 {
6056 unsigned x = 0;
6057 unsigned count = 0;
6058 while (true)
6059 {
6060 auto ic = is.peek();
6061 if (Traits::eq_int_type(ic, Traits::eof()))
6062 break;
6063 auto c = static_cast<char>(Traits::to_char_type(ic));
6064 if (!('0' <= c && c <= '9'))
6065 break;
6066 (void)is.get();
6067 ++count;
6068 x = 10*x + static_cast<unsigned>(c - '0');
6069 if (count == M)
6070 break;
6071 }
6072 if (count < m)
6073 is.setstate(std::ios::failbit);
6074 return x;
6075 }
6076
6077 template <class CharT, class Traits>
6078 int
6079 read_signed(std::basic_istream<CharT, Traits>& is, unsigned m = 1, unsigned M = 10)
6080 {
6081 auto ic = is.peek();
6082 if (!Traits::eq_int_type(ic, Traits::eof()))
6083 {
6084 auto c = static_cast<char>(Traits::to_char_type(ic));
6085 if (('0' <= c && c <= '9') || c == '-' || c == '+')
6086 {
6087 if (c == '-' || c == '+')
6088 (void)is.get();
6089 auto x = static_cast<int>(read_unsigned(is, std::max(m, 1u), M));
6090 if (!is.fail())
6091 {
6092 if (c == '-')
6093 x = -x;
6094 return x;
6095 }
6096 }
6097 }
6098 if (m > 0)
6099 is.setstate(std::ios::failbit);
6100 return 0;
6101 }
6102
6103 template <class CharT, class Traits>
6104 long double
6105 read_long_double(std::basic_istream<CharT, Traits>& is, unsigned m = 1, unsigned M = 10)
6106 {
6107 unsigned count = 0;
6108 auto decimal_point = Traits::to_int_type(
6109 std::use_facet<std::numpunct<CharT>>(is.getloc()).decimal_point());
6110 std::string buf;
6111 while (true)
6112 {
6113 auto ic = is.peek();
6114 if (Traits::eq_int_type(ic, Traits::eof()))
6115 break;
6116 if (Traits::eq_int_type(ic, decimal_point))
6117 {
6118 buf += '.';
6119 decimal_point = Traits::eof();
6120 is.get();
6121 }
6122 else
6123 {
6124 auto c = static_cast<char>(Traits::to_char_type(ic));
6125 if (!('0' <= c && c <= '9'))
6126 break;
6127 buf += c;
6128 (void)is.get();
6129 }
6130 if (++count == M)
6131 break;
6132 }
6133 if (count < m)
6134 {
6135 is.setstate(std::ios::failbit);
6136 return 0;
6137 }
6138 return std::stold(buf);
6139 }
6140
6141 struct rs
6142 {
6143 int& i;
6144 unsigned m;
6145 unsigned M;
6146 };
6147
6148 struct ru
6149 {
6150 int& i;
6151 unsigned m;
6152 unsigned M;
6153 };
6154
6155 struct rld
6156 {
6157 long double& i;
6158 unsigned m;
6159 unsigned M;
6160 };
6161
6162 template <class CharT, class Traits>
6163 void
6164 read(std::basic_istream<CharT, Traits>&)
6165 {
6166 }
6167
6168 template <class CharT, class Traits, class ...Args>
6169 void
6170 read(std::basic_istream<CharT, Traits>& is, CharT a0, Args&& ...args);
6171
6172 template <class CharT, class Traits, class ...Args>
6173 void
6174 read(std::basic_istream<CharT, Traits>& is, rs a0, Args&& ...args);
6175
6176 template <class CharT, class Traits, class ...Args>
6177 void
6178 read(std::basic_istream<CharT, Traits>& is, ru a0, Args&& ...args);
6179
6180 template <class CharT, class Traits, class ...Args>
6181 void
6182 read(std::basic_istream<CharT, Traits>& is, int a0, Args&& ...args);
6183
6184 template <class CharT, class Traits, class ...Args>
6185 void
6186 read(std::basic_istream<CharT, Traits>& is, rld a0, Args&& ...args);
6187
6188 template <class CharT, class Traits, class ...Args>
6189 void
6190 read(std::basic_istream<CharT, Traits>& is, CharT a0, Args&& ...args)
6191 {
6192 // No-op if a0 == CharT{}
6193 if (a0 != CharT{})
6194 {
6195 auto ic = is.peek();
6196 if (Traits::eq_int_type(ic, Traits::eof()))
6197 {
6198 is.setstate(std::ios::failbit | std::ios::eofbit);
6199 return;
6200 }
6201 if (!Traits::eq(Traits::to_char_type(ic), a0))
6202 {
6203 is.setstate(std::ios::failbit);
6204 return;
6205 }
6206 (void)is.get();
6207 }
6208 read(is, std::forward<Args>(args)...);
6209 }
6210
6211 template <class CharT, class Traits, class ...Args>
6212 void
6213 read(std::basic_istream<CharT, Traits>& is, rs a0, Args&& ...args)
6214 {
6215 auto x = read_signed(is, a0.m, a0.M);
6216 if (is.fail())
6217 return;
6218 a0.i = x;
6219 read(is, std::forward<Args>(args)...);
6220 }
6221
6222 template <class CharT, class Traits, class ...Args>
6223 void
6224 read(std::basic_istream<CharT, Traits>& is, ru a0, Args&& ...args)
6225 {
6226 auto x = read_unsigned(is, a0.m, a0.M);
6227 if (is.fail())
6228 return;
6229 a0.i = static_cast<int>(x);
6230 read(is, std::forward<Args>(args)...);
6231 }
6232
6233 template <class CharT, class Traits, class ...Args>
6234 void
6235 read(std::basic_istream<CharT, Traits>& is, int a0, Args&& ...args)
6236 {
6237 if (a0 != -1)
6238 {
6239 auto u = static_cast<unsigned>(a0);
6240 CharT buf[std::numeric_limits<unsigned>::digits10+2u] = {};
6241 auto e = buf;
6242 do
6243 {
6244 *e++ = static_cast<CharT>(CharT(u % 10) + CharT{'0'});
6245 u /= 10;
6246 } while (u > 0);
6247 std::reverse(buf, e);
6248 for (auto p = buf; p != e && is.rdstate() == std::ios::goodbit; ++p)
6249 read(is, *p);
6250 }
6251 if (is.rdstate() == std::ios::goodbit)
6252 read(is, std::forward<Args>(args)...);
6253 }
6254
6255 template <class CharT, class Traits, class ...Args>
6256 void
6257 read(std::basic_istream<CharT, Traits>& is, rld a0, Args&& ...args)
6258 {
6259 auto x = read_long_double(is, a0.m, a0.M);
6260 if (is.fail())
6261 return;
6262 a0.i = x;
6263 read(is, std::forward<Args>(args)...);
6264 }
6265
6266 template <class T, class CharT, class Traits>
6267 inline
6268 void
6269 checked_set(T& value, T from, T not_a_value, std::basic_ios<CharT, Traits>& is)
6270 {
6271 if (!is.fail())
6272 {
6273 if (value == not_a_value)
6274 value = std::move(from);
6275 else if (value != from)
6276 is.setstate(std::ios::failbit);
6277 }
6278 }
6279
6280 } // namespace detail;
6281
6282 template <class CharT, class Traits, class Duration, class Alloc = std::allocator<CharT>>
6283 std::basic_istream<CharT, Traits>&
6284 from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
6285 fields<Duration>& fds, std::basic_string<CharT, Traits, Alloc>* abbrev,
6286 std::chrono::minutes* offset)
6287 {
6288 using std::numeric_limits;
6289 using std::ios;
6290 using std::chrono::duration;
6291 using std::chrono::duration_cast;
6292 using std::chrono::seconds;
6293 using std::chrono::minutes;
6294 using std::chrono::hours;
6295 typename std::basic_istream<CharT, Traits>::sentry ok{is, true};
6296 if (ok)
6297 {
6298 date::detail::save_istream<CharT, Traits> ss(is);
6299 is.fill(' ');
6300 is.flags(std::ios::skipws | std::ios::dec);
6301 is.width(0);
6302 #if !ONLY_C_LOCALE
6303 auto& f = std::use_facet<std::time_get<CharT>>(is.getloc());
6304 std::tm tm{};
6305 #endif
6306 const CharT* command = nullptr;
6307 auto modified = CharT{};
6308 auto width = -1;
6309
6310 CONSTDATA int not_a_year = numeric_limits<int>::min();
6311 CONSTDATA int not_a_2digit_year = 100;
6312 CONSTDATA int not_a_century = not_a_year / 100;
6313 CONSTDATA int not_a_month = 0;
6314 CONSTDATA int not_a_day = 0;
6315 CONSTDATA int not_a_hour = numeric_limits<int>::min();
6316 CONSTDATA int not_a_hour_12_value = 0;
6317 CONSTDATA int not_a_minute = not_a_hour;
6318 CONSTDATA Duration not_a_second = Duration::min();
6319 CONSTDATA int not_a_doy = -1;
6320 CONSTDATA int not_a_weekday = 8;
6321 CONSTDATA int not_a_week_num = 100;
6322 CONSTDATA int not_a_ampm = -1;
6323 CONSTDATA minutes not_a_offset = minutes::min();
6324
6325 int Y = not_a_year; // c, F, Y *
6326 int y = not_a_2digit_year; // D, x, y *
6327 int g = not_a_2digit_year; // g *
6328 int G = not_a_year; // G *
6329 int C = not_a_century; // C *
6330 int m = not_a_month; // b, B, h, m, c, D, F, x *
6331 int d = not_a_day; // c, d, D, e, F, x *
6332 int j = not_a_doy; // j *
6333 int wd = not_a_weekday; // a, A, u, w *
6334 int H = not_a_hour; // c, H, R, T, X *
6335 int I = not_a_hour_12_value; // I, r *
6336 int p = not_a_ampm; // p, r *
6337 int M = not_a_minute; // c, M, r, R, T, X *
6338 Duration s = not_a_second; // c, r, S, T, X *
6339 int U = not_a_week_num; // U *
6340 int V = not_a_week_num; // V *
6341 int W = not_a_week_num; // W *
6342 std::basic_string<CharT, Traits, Alloc> temp_abbrev; // Z *
6343 minutes temp_offset = not_a_offset; // z *
6344
6345 using detail::read;
6346 using detail::rs;
6347 using detail::ru;
6348 using detail::rld;
6349 using detail::checked_set;
6350 for (; *fmt != CharT{} && !is.fail(); ++fmt)
6351 {
6352 switch (*fmt)
6353 {
6354 case 'a':
6355 case 'A':
6356 case 'u':
6357 case 'w': // wd: a, A, u, w
6358 if (command)
6359 {
6360 int trial_wd = not_a_weekday;
6361 if (*fmt == 'a' || *fmt == 'A')
6362 {
6363 if (modified == CharT{})
6364 {
6365 #if !ONLY_C_LOCALE
6366 ios::iostate err = ios::goodbit;
6367 f.get(is, nullptr, is, err, &tm, command, fmt+1);
6368 is.setstate(err);
6369 if (!is.fail())
6370 trial_wd = tm.tm_wday;
6371 #else
6372 auto nm = detail::weekday_names();
6373 auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
6374 if (!is.fail())
6375 trial_wd = i % 7;
6376 #endif
6377 }
6378 else
6379 read(is, CharT{'%'}, width, modified, *fmt);
6380 }
6381 else // *fmt == 'u' || *fmt == 'w'
6382 {
6383 #if !ONLY_C_LOCALE
6384 if (modified == CharT{})
6385 #else
6386 if (modified != CharT{'E'})
6387 #endif
6388 {
6389 read(is, ru{trial_wd, 1, width == -1 ?
6390 1u : static_cast<unsigned>(width)});
6391 if (!is.fail())
6392 {
6393 if (*fmt == 'u')
6394 {
6395 if (!(1 <= trial_wd && trial_wd <= 7))
6396 {
6397 trial_wd = not_a_weekday;
6398 is.setstate(ios::failbit);
6399 }
6400 else if (trial_wd == 7)
6401 trial_wd = 0;
6402 }
6403 else // *fmt == 'w'
6404 {
6405 if (!(0 <= trial_wd && trial_wd <= 6))
6406 {
6407 trial_wd = not_a_weekday;
6408 is.setstate(ios::failbit);
6409 }
6410 }
6411 }
6412 }
6413 #if !ONLY_C_LOCALE
6414 else if (modified == CharT{'O'})
6415 {
6416 ios::iostate err = ios::goodbit;
6417 f.get(is, nullptr, is, err, &tm, command, fmt+1);
6418 is.setstate(err);
6419 if (!is.fail())
6420 trial_wd = tm.tm_wday;
6421 }
6422 #endif
6423 else
6424 read(is, CharT{'%'}, width, modified, *fmt);
6425 }
6426 if (trial_wd != not_a_weekday)
6427 checked_set(wd, trial_wd, not_a_weekday, is);
6428 }
6429 else // !command
6430 read(is, *fmt);
6431 command = nullptr;
6432 width = -1;
6433 modified = CharT{};
6434 break;
6435 case 'b':
6436 case 'B':
6437 case 'h':
6438 if (command)
6439 {
6440 if (modified == CharT{})
6441 {
6442 int ttm = not_a_month;
6443 #if !ONLY_C_LOCALE
6444 ios::iostate err = ios::goodbit;
6445 f.get(is, nullptr, is, err, &tm, command, fmt+1);
6446 if ((err & ios::failbit) == 0)
6447 ttm = tm.tm_mon + 1;
6448 is.setstate(err);
6449 #else
6450 auto nm = detail::month_names();
6451 auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
6452 if (!is.fail())
6453 ttm = i % 12 + 1;
6454 #endif
6455 checked_set(m, ttm, not_a_month, is);
6456 }
6457 else
6458 read(is, CharT{'%'}, width, modified, *fmt);
6459 command = nullptr;
6460 width = -1;
6461 modified = CharT{};
6462 }
6463 else
6464 read(is, *fmt);
6465 break;
6466 case 'c':
6467 if (command)
6468 {
6469 if (modified != CharT{'O'})
6470 {
6471 #if !ONLY_C_LOCALE
6472 ios::iostate err = ios::goodbit;
6473 f.get(is, nullptr, is, err, &tm, command, fmt+1);
6474 if ((err & ios::failbit) == 0)
6475 {
6476 checked_set(Y, tm.tm_year + 1900, not_a_year, is);
6477 checked_set(m, tm.tm_mon + 1, not_a_month, is);
6478 checked_set(d, tm.tm_mday, not_a_day, is);
6479 checked_set(H, tm.tm_hour, not_a_hour, is);
6480 checked_set(M, tm.tm_min, not_a_minute, is);
6481 checked_set(s, duration_cast<Duration>(seconds{tm.tm_sec}),
6482 not_a_second, is);
6483 }
6484 is.setstate(err);
6485 #else
6486 // "%a %b %e %T %Y"
6487 auto nm = detail::weekday_names();
6488 auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
6489 checked_set(wd, static_cast<int>(i % 7), not_a_weekday, is);
6490 ws(is);
6491 nm = detail::month_names();
6492 i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
6493 checked_set(m, static_cast<int>(i % 12 + 1), not_a_month, is);
6494 ws(is);
6495 int td = not_a_day;
6496 read(is, rs{td, 1, 2});
6497 checked_set(d, td, not_a_day, is);
6498 ws(is);
6499 using dfs = detail::decimal_format_seconds<Duration>;
6500 CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
6501 int tH;
6502 int tM;
6503 long double S;
6504 read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2},
6505 CharT{':'}, rld{S, 1, w});
6506 checked_set(H, tH, not_a_hour, is);
6507 checked_set(M, tM, not_a_minute, is);
6508 checked_set(s, round<Duration>(duration<long double>{S}),
6509 not_a_second, is);
6510 ws(is);
6511 int tY = not_a_year;
6512 read(is, rs{tY, 1, 4u});
6513 checked_set(Y, tY, not_a_year, is);
6514 #endif
6515 }
6516 else
6517 read(is, CharT{'%'}, width, modified, *fmt);
6518 command = nullptr;
6519 width = -1;
6520 modified = CharT{};
6521 }
6522 else
6523 read(is, *fmt);
6524 break;
6525 case 'x':
6526 if (command)
6527 {
6528 if (modified != CharT{'O'})
6529 {
6530 #if !ONLY_C_LOCALE
6531 ios::iostate err = ios::goodbit;
6532 f.get(is, nullptr, is, err, &tm, command, fmt+1);
6533 if ((err & ios::failbit) == 0)
6534 {
6535 checked_set(Y, tm.tm_year + 1900, not_a_year, is);
6536 checked_set(m, tm.tm_mon + 1, not_a_month, is);
6537 checked_set(d, tm.tm_mday, not_a_day, is);
6538 }
6539 is.setstate(err);
6540 #else
6541 // "%m/%d/%y"
6542 int ty = not_a_2digit_year;
6543 int tm = not_a_month;
6544 int td = not_a_day;
6545 read(is, ru{tm, 1, 2}, CharT{'/'}, ru{td, 1, 2}, CharT{'/'},
6546 rs{ty, 1, 2});
6547 checked_set(y, ty, not_a_2digit_year, is);
6548 checked_set(m, tm, not_a_month, is);
6549 checked_set(d, td, not_a_day, is);
6550 #endif
6551 }
6552 else
6553 read(is, CharT{'%'}, width, modified, *fmt);
6554 command = nullptr;
6555 width = -1;
6556 modified = CharT{};
6557 }
6558 else
6559 read(is, *fmt);
6560 break;
6561 case 'X':
6562 if (command)
6563 {
6564 if (modified != CharT{'O'})
6565 {
6566 #if !ONLY_C_LOCALE
6567 ios::iostate err = ios::goodbit;
6568 f.get(is, nullptr, is, err, &tm, command, fmt+1);
6569 if ((err & ios::failbit) == 0)
6570 {
6571 checked_set(H, tm.tm_hour, not_a_hour, is);
6572 checked_set(M, tm.tm_min, not_a_minute, is);
6573 checked_set(s, duration_cast<Duration>(seconds{tm.tm_sec}),
6574 not_a_second, is);
6575 }
6576 is.setstate(err);
6577 #else
6578 // "%T"
6579 using dfs = detail::decimal_format_seconds<Duration>;
6580 CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
6581 int tH = not_a_hour;
6582 int tM = not_a_minute;
6583 long double S;
6584 read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2},
6585 CharT{':'}, rld{S, 1, w});
6586 checked_set(H, tH, not_a_hour, is);
6587 checked_set(M, tM, not_a_minute, is);
6588 checked_set(s, round<Duration>(duration<long double>{S}),
6589 not_a_second, is);
6590 #endif
6591 }
6592 else
6593 read(is, CharT{'%'}, width, modified, *fmt);
6594 command = nullptr;
6595 width = -1;
6596 modified = CharT{};
6597 }
6598 else
6599 read(is, *fmt);
6600 break;
6601 case 'C':
6602 if (command)
6603 {
6604 int tC = not_a_century;
6605 #if !ONLY_C_LOCALE
6606 if (modified == CharT{})
6607 {
6608 #endif
6609 read(is, rs{tC, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
6610 #if !ONLY_C_LOCALE
6611 }
6612 else
6613 {
6614 ios::iostate err = ios::goodbit;
6615 f.get(is, nullptr, is, err, &tm, command, fmt+1);
6616 if ((err & ios::failbit) == 0)
6617 {
6618 auto tY = tm.tm_year + 1900;
6619 tC = (tY >= 0 ? tY : tY-99) / 100;
6620 }
6621 is.setstate(err);
6622 }
6623 #endif
6624 checked_set(C, tC, not_a_century, is);
6625 command = nullptr;
6626 width = -1;
6627 modified = CharT{};
6628 }
6629 else
6630 read(is, *fmt);
6631 break;
6632 case 'D':
6633 if (command)
6634 {
6635 if (modified == CharT{})
6636 {
6637 int tn = not_a_month;
6638 int td = not_a_day;
6639 int ty = not_a_2digit_year;
6640 read(is, ru{tn, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'},
6641 ru{td, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'},
6642 rs{ty, 1, 2});
6643 checked_set(y, ty, not_a_2digit_year, is);
6644 checked_set(m, tn, not_a_month, is);
6645 checked_set(d, td, not_a_day, is);
6646 }
6647 else
6648 read(is, CharT{'%'}, width, modified, *fmt);
6649 command = nullptr;
6650 width = -1;
6651 modified = CharT{};
6652 }
6653 else
6654 read(is, *fmt);
6655 break;
6656 case 'F':
6657 if (command)
6658 {
6659 if (modified == CharT{})
6660 {
6661 int tY = not_a_year;
6662 int tn = not_a_month;
6663 int td = not_a_day;
6664 read(is, rs{tY, 1, width == -1 ? 4u : static_cast<unsigned>(width)},
6665 CharT{'-'}, ru{tn, 1, 2}, CharT{'-'}, ru{td, 1, 2});
6666 checked_set(Y, tY, not_a_year, is);
6667 checked_set(m, tn, not_a_month, is);
6668 checked_set(d, td, not_a_day, is);
6669 }
6670 else
6671 read(is, CharT{'%'}, width, modified, *fmt);
6672 command = nullptr;
6673 width = -1;
6674 modified = CharT{};
6675 }
6676 else
6677 read(is, *fmt);
6678 break;
6679 case 'd':
6680 case 'e':
6681 if (command)
6682 {
6683 #if !ONLY_C_LOCALE
6684 if (modified == CharT{})
6685 #else
6686 if (modified != CharT{'E'})
6687 #endif
6688 {
6689 int td = not_a_day;
6690 read(is, rs{td, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
6691 checked_set(d, td, not_a_day, is);
6692 }
6693 #if !ONLY_C_LOCALE
6694 else if (modified == CharT{'O'})
6695 {
6696 ios::iostate err = ios::goodbit;
6697 f.get(is, nullptr, is, err, &tm, command, fmt+1);
6698 command = nullptr;
6699 width = -1;
6700 modified = CharT{};
6701 if ((err & ios::failbit) == 0)
6702 checked_set(d, tm.tm_mday, not_a_day, is);
6703 is.setstate(err);
6704 }
6705 #endif
6706 else
6707 read(is, CharT{'%'}, width, modified, *fmt);
6708 command = nullptr;
6709 width = -1;
6710 modified = CharT{};
6711 }
6712 else
6713 read(is, *fmt);
6714 break;
6715 case 'H':
6716 if (command)
6717 {
6718 #if !ONLY_C_LOCALE
6719 if (modified == CharT{})
6720 #else
6721 if (modified != CharT{'E'})
6722 #endif
6723 {
6724 int tH = not_a_hour;
6725 read(is, ru{tH, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
6726 checked_set(H, tH, not_a_hour, is);
6727 }
6728 #if !ONLY_C_LOCALE
6729 else if (modified == CharT{'O'})
6730 {
6731 ios::iostate err = ios::goodbit;
6732 f.get(is, nullptr, is, err, &tm, command, fmt+1);
6733 if ((err & ios::failbit) == 0)
6734 checked_set(H, tm.tm_hour, not_a_hour, is);
6735 is.setstate(err);
6736 }
6737 #endif
6738 else
6739 read(is, CharT{'%'}, width, modified, *fmt);
6740 command = nullptr;
6741 width = -1;
6742 modified = CharT{};
6743 }
6744 else
6745 read(is, *fmt);
6746 break;
6747 case 'I':
6748 if (command)
6749 {
6750 if (modified == CharT{})
6751 {
6752 int tI = not_a_hour_12_value;
6753 // reads in an hour into I, but most be in [1, 12]
6754 read(is, rs{tI, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
6755 if (!(1 <= tI && tI <= 12))
6756 is.setstate(ios::failbit);
6757 checked_set(I, tI, not_a_hour_12_value, is);
6758 }
6759 else
6760 read(is, CharT{'%'}, width, modified, *fmt);
6761 command = nullptr;
6762 width = -1;
6763 modified = CharT{};
6764 }
6765 else
6766 read(is, *fmt);
6767 break;
6768 case 'j':
6769 if (command)
6770 {
6771 if (modified == CharT{})
6772 {
6773 int tj = not_a_doy;
6774 read(is, ru{tj, 1, width == -1 ? 3u : static_cast<unsigned>(width)});
6775 checked_set(j, tj, not_a_doy, is);
6776 }
6777 else
6778 read(is, CharT{'%'}, width, modified, *fmt);
6779 command = nullptr;
6780 width = -1;
6781 modified = CharT{};
6782 }
6783 else
6784 read(is, *fmt);
6785 break;
6786 case 'M':
6787 if (command)
6788 {
6789 #if !ONLY_C_LOCALE
6790 if (modified == CharT{})
6791 #else
6792 if (modified != CharT{'E'})
6793 #endif
6794 {
6795 int tM = not_a_minute;
6796 read(is, ru{tM, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
6797 checked_set(M, tM, not_a_minute, is);
6798 }
6799 #if !ONLY_C_LOCALE
6800 else if (modified == CharT{'O'})
6801 {
6802 ios::iostate err = ios::goodbit;
6803 f.get(is, nullptr, is, err, &tm, command, fmt+1);
6804 if ((err & ios::failbit) == 0)
6805 checked_set(M, tm.tm_min, not_a_minute, is);
6806 is.setstate(err);
6807 }
6808 #endif
6809 else
6810 read(is, CharT{'%'}, width, modified, *fmt);
6811 command = nullptr;
6812 width = -1;
6813 modified = CharT{};
6814 }
6815 else
6816 read(is, *fmt);
6817 break;
6818 case 'm':
6819 if (command)
6820 {
6821 #if !ONLY_C_LOCALE
6822 if (modified == CharT{})
6823 #else
6824 if (modified != CharT{'E'})
6825 #endif
6826 {
6827 int tn = not_a_month;
6828 read(is, rs{tn, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
6829 checked_set(m, tn, not_a_month, is);
6830 }
6831 #if !ONLY_C_LOCALE
6832 else if (modified == CharT{'O'})
6833 {
6834 ios::iostate err = ios::goodbit;
6835 f.get(is, nullptr, is, err, &tm, command, fmt+1);
6836 if ((err & ios::failbit) == 0)
6837 checked_set(m, tm.tm_mon + 1, not_a_month, is);
6838 is.setstate(err);
6839 }
6840 #endif
6841 else
6842 read(is, CharT{'%'}, width, modified, *fmt);
6843 command = nullptr;
6844 width = -1;
6845 modified = CharT{};
6846 }
6847 else
6848 read(is, *fmt);
6849 break;
6850 case 'n':
6851 case 't':
6852 if (command)
6853 {
6854 if (modified == CharT{})
6855 {
6856 // %n matches a single white space character
6857 // %t matches 0 or 1 white space characters
6858 auto ic = is.peek();
6859 if (Traits::eq_int_type(ic, Traits::eof()))
6860 {
6861 ios::iostate err = ios::eofbit;
6862 if (*fmt == 'n')
6863 err |= ios::failbit;
6864 is.setstate(err);
6865 break;
6866 }
6867 if (isspace(ic))
6868 {
6869 (void)is.get();
6870 }
6871 else if (*fmt == 'n')
6872 is.setstate(ios::failbit);
6873 }
6874 else
6875 read(is, CharT{'%'}, width, modified, *fmt);
6876 command = nullptr;
6877 width = -1;
6878 modified = CharT{};
6879 }
6880 else
6881 read(is, *fmt);
6882 break;
6883 case 'p':
6884 if (command)
6885 {
6886 if (modified == CharT{})
6887 {
6888 int tp = not_a_ampm;
6889 #if !ONLY_C_LOCALE
6890 tm = std::tm{};
6891 tm.tm_hour = 1;
6892 ios::iostate err = ios::goodbit;
6893 f.get(is, nullptr, is, err, &tm, command, fmt+1);
6894 is.setstate(err);
6895 if (tm.tm_hour == 1)
6896 tp = 0;
6897 else if (tm.tm_hour == 13)
6898 tp = 1;
6899 else
6900 is.setstate(err);
6901 #else
6902 auto nm = detail::ampm_names();
6903 auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
6904 tp = i;
6905 #endif
6906 checked_set(p, tp, not_a_ampm, is);
6907 }
6908 else
6909 read(is, CharT{'%'}, width, modified, *fmt);
6910 command = nullptr;
6911 width = -1;
6912 modified = CharT{};
6913 }
6914 else
6915 read(is, *fmt);
6916
6917 break;
6918 case 'r':
6919 if (command)
6920 {
6921 if (modified == CharT{})
6922 {
6923 #if !ONLY_C_LOCALE
6924 ios::iostate err = ios::goodbit;
6925 f.get(is, nullptr, is, err, &tm, command, fmt+1);
6926 if ((err & ios::failbit) == 0)
6927 {
6928 checked_set(H, tm.tm_hour, not_a_hour, is);
6929 checked_set(M, tm.tm_min, not_a_hour, is);
6930 checked_set(s, duration_cast<Duration>(seconds{tm.tm_sec}),
6931 not_a_second, is);
6932 }
6933 is.setstate(err);
6934 #else
6935 // "%I:%M:%S %p"
6936 using dfs = detail::decimal_format_seconds<Duration>;
6937 CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
6938 long double S;
6939 int tI = not_a_hour_12_value;
6940 int tM = not_a_minute;
6941 read(is, ru{tI, 1, 2}, CharT{':'}, ru{tM, 1, 2},
6942 CharT{':'}, rld{S, 1, w});
6943 checked_set(I, tI, not_a_hour_12_value, is);
6944 checked_set(M, tM, not_a_minute, is);
6945 checked_set(s, round<Duration>(duration<long double>{S}),
6946 not_a_second, is);
6947 ws(is);
6948 auto nm = detail::ampm_names();
6949 auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
6950 checked_set(p, static_cast<int>(i), not_a_ampm, is);
6951 #endif
6952 }
6953 else
6954 read(is, CharT{'%'}, width, modified, *fmt);
6955 command = nullptr;
6956 width = -1;
6957 modified = CharT{};
6958 }
6959 else
6960 read(is, *fmt);
6961 break;
6962 case 'R':
6963 if (command)
6964 {
6965 if (modified == CharT{})
6966 {
6967 int tH = not_a_hour;
6968 int tM = not_a_minute;
6969 read(is, ru{tH, 1, 2}, CharT{'\0'}, CharT{':'}, CharT{'\0'},
6970 ru{tM, 1, 2}, CharT{'\0'});
6971 checked_set(H, tH, not_a_hour, is);
6972 checked_set(M, tM, not_a_minute, is);
6973 }
6974 else
6975 read(is, CharT{'%'}, width, modified, *fmt);
6976 command = nullptr;
6977 width = -1;
6978 modified = CharT{};
6979 }
6980 else
6981 read(is, *fmt);
6982 break;
6983 case 'S':
6984 if (command)
6985 {
6986 #if !ONLY_C_LOCALE
6987 if (modified == CharT{})
6988 #else
6989 if (modified != CharT{'E'})
6990 #endif
6991 {
6992 using dfs = detail::decimal_format_seconds<Duration>;
6993 CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
6994 long double S;
6995 read(is, rld{S, 1, width == -1 ? w : static_cast<unsigned>(width)});
6996 checked_set(s, round<Duration>(duration<long double>{S}),
6997 not_a_second, is);
6998 }
6999 #if !ONLY_C_LOCALE
7000 else if (modified == CharT{'O'})
7001 {
7002 ios::iostate err = ios::goodbit;
7003 f.get(is, nullptr, is, err, &tm, command, fmt+1);
7004 if ((err & ios::failbit) == 0)
7005 checked_set(s, duration_cast<Duration>(seconds{tm.tm_sec}),
7006 not_a_second, is);
7007 is.setstate(err);
7008 }
7009 #endif
7010 else
7011 read(is, CharT{'%'}, width, modified, *fmt);
7012 command = nullptr;
7013 width = -1;
7014 modified = CharT{};
7015 }
7016 else
7017 read(is, *fmt);
7018 break;
7019 case 'T':
7020 if (command)
7021 {
7022 if (modified == CharT{})
7023 {
7024 using dfs = detail::decimal_format_seconds<Duration>;
7025 CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
7026 int tH = not_a_hour;
7027 int tM = not_a_minute;
7028 long double S;
7029 read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2},
7030 CharT{':'}, rld{S, 1, w});
7031 checked_set(H, tH, not_a_hour, is);
7032 checked_set(M, tM, not_a_minute, is);
7033 checked_set(s, round<Duration>(duration<long double>{S}),
7034 not_a_second, is);
7035 }
7036 else
7037 read(is, CharT{'%'}, width, modified, *fmt);
7038 command = nullptr;
7039 width = -1;
7040 modified = CharT{};
7041 }
7042 else
7043 read(is, *fmt);
7044 break;
7045 case 'Y':
7046 if (command)
7047 {
7048 #if !ONLY_C_LOCALE
7049 if (modified == CharT{})
7050 #else
7051 if (modified != CharT{'O'})
7052 #endif
7053 {
7054 int tY = not_a_year;
7055 read(is, rs{tY, 1, width == -1 ? 4u : static_cast<unsigned>(width)});
7056 checked_set(Y, tY, not_a_year, is);
7057 }
7058 #if !ONLY_C_LOCALE
7059 else if (modified == CharT{'E'})
7060 {
7061 ios::iostate err = ios::goodbit;
7062 f.get(is, nullptr, is, err, &tm, command, fmt+1);
7063 if ((err & ios::failbit) == 0)
7064 checked_set(Y, tm.tm_year + 1900, not_a_year, is);
7065 is.setstate(err);
7066 }
7067 #endif
7068 else
7069 read(is, CharT{'%'}, width, modified, *fmt);
7070 command = nullptr;
7071 width = -1;
7072 modified = CharT{};
7073 }
7074 else
7075 read(is, *fmt);
7076 break;
7077 case 'y':
7078 if (command)
7079 {
7080 #if !ONLY_C_LOCALE
7081 if (modified == CharT{})
7082 #endif
7083 {
7084 int ty = not_a_2digit_year;
7085 read(is, ru{ty, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
7086 checked_set(y, ty, not_a_2digit_year, is);
7087 }
7088 #if !ONLY_C_LOCALE
7089 else
7090 {
7091 ios::iostate err = ios::goodbit;
7092 f.get(is, nullptr, is, err, &tm, command, fmt+1);
7093 if ((err & ios::failbit) == 0)
7094 checked_set(Y, tm.tm_year + 1900, not_a_year, is);
7095 is.setstate(err);
7096 }
7097 #endif
7098 command = nullptr;
7099 width = -1;
7100 modified = CharT{};
7101 }
7102 else
7103 read(is, *fmt);
7104 break;
7105 case 'g':
7106 if (command)
7107 {
7108 if (modified == CharT{})
7109 {
7110 int tg = not_a_2digit_year;
7111 read(is, ru{tg, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
7112 checked_set(g, tg, not_a_2digit_year, is);
7113 }
7114 else
7115 read(is, CharT{'%'}, width, modified, *fmt);
7116 command = nullptr;
7117 width = -1;
7118 modified = CharT{};
7119 }
7120 else
7121 read(is, *fmt);
7122 break;
7123 case 'G':
7124 if (command)
7125 {
7126 if (modified == CharT{})
7127 {
7128 int tG = not_a_year;
7129 read(is, rs{tG, 1, width == -1 ? 4u : static_cast<unsigned>(width)});
7130 checked_set(G, tG, not_a_year, is);
7131 }
7132 else
7133 read(is, CharT{'%'}, width, modified, *fmt);
7134 command = nullptr;
7135 width = -1;
7136 modified = CharT{};
7137 }
7138 else
7139 read(is, *fmt);
7140 break;
7141 case 'U':
7142 if (command)
7143 {
7144 if (modified == CharT{})
7145 {
7146 int tU = not_a_week_num;
7147 read(is, ru{tU, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
7148 checked_set(U, tU, not_a_week_num, is);
7149 }
7150 else
7151 read(is, CharT{'%'}, width, modified, *fmt);
7152 command = nullptr;
7153 width = -1;
7154 modified = CharT{};
7155 }
7156 else
7157 read(is, *fmt);
7158 break;
7159 case 'V':
7160 if (command)
7161 {
7162 if (modified == CharT{})
7163 {
7164 int tV = not_a_week_num;
7165 read(is, ru{tV, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
7166 checked_set(V, tV, not_a_week_num, is);
7167 }
7168 else
7169 read(is, CharT{'%'}, width, modified, *fmt);
7170 command = nullptr;
7171 width = -1;
7172 modified = CharT{};
7173 }
7174 else
7175 read(is, *fmt);
7176 break;
7177 case 'W':
7178 if (command)
7179 {
7180 if (modified == CharT{})
7181 {
7182 int tW = not_a_week_num;
7183 read(is, ru{tW, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
7184 checked_set(W, tW, not_a_week_num, is);
7185 }
7186 else
7187 read(is, CharT{'%'}, width, modified, *fmt);
7188 command = nullptr;
7189 width = -1;
7190 modified = CharT{};
7191 }
7192 else
7193 read(is, *fmt);
7194 break;
7195 case 'E':
7196 case 'O':
7197 if (command)
7198 {
7199 if (modified == CharT{})
7200 {
7201 modified = *fmt;
7202 }
7203 else
7204 {
7205 read(is, CharT{'%'}, width, modified, *fmt);
7206 command = nullptr;
7207 width = -1;
7208 modified = CharT{};
7209 }
7210 }
7211 else
7212 read(is, *fmt);
7213 break;
7214 case '%':
7215 if (command)
7216 {
7217 if (modified == CharT{})
7218 read(is, *fmt);
7219 else
7220 read(is, CharT{'%'}, width, modified, *fmt);
7221 command = nullptr;
7222 width = -1;
7223 modified = CharT{};
7224 }
7225 else
7226 command = fmt;
7227 break;
7228 case 'z':
7229 if (command)
7230 {
7231 int tH, tM;
7232 minutes toff = not_a_offset;
7233 bool neg = false;
7234 auto ic = is.peek();
7235 if (!Traits::eq_int_type(ic, Traits::eof()))
7236 {
7237 auto c = static_cast<char>(Traits::to_char_type(ic));
7238 if (c == '-')
7239 neg = true;
7240 }
7241 if (modified == CharT{})
7242 {
7243 read(is, rs{tH, 2, 2});
7244 if (!is.fail())
7245 toff = hours{std::abs(tH)};
7246 if (is.good())
7247 {
7248 ic = is.peek();
7249 if (!Traits::eq_int_type(ic, Traits::eof()))
7250 {
7251 auto c = static_cast<char>(Traits::to_char_type(ic));
7252 if ('0' <= c && c <= '9')
7253 {
7254 read(is, ru{tM, 2, 2});
7255 if (!is.fail())
7256 toff += minutes{tM};
7257 }
7258 }
7259 }
7260 }
7261 else
7262 {
7263 read(is, rs{tH, 1, 2});
7264 if (!is.fail())
7265 toff = hours{std::abs(tH)};
7266 if (is.good())
7267 {
7268 ic = is.peek();
7269 if (!Traits::eq_int_type(ic, Traits::eof()))
7270 {
7271 auto c = static_cast<char>(Traits::to_char_type(ic));
7272 if (c == ':')
7273 {
7274 (void)is.get();
7275 read(is, ru{tM, 2, 2});
7276 if (!is.fail())
7277 toff += minutes{tM};
7278 }
7279 }
7280 }
7281 }
7282 if (neg)
7283 toff = -toff;
7284 checked_set(temp_offset, toff, not_a_offset, is);
7285 command = nullptr;
7286 width = -1;
7287 modified = CharT{};
7288 }
7289 else
7290 read(is, *fmt);
7291 break;
7292 case 'Z':
7293 if (command)
7294 {
7295 if (modified == CharT{})
7296 {
7297 std::basic_string<CharT, Traits, Alloc> buf;
7298 while (is.rdstate() == std::ios::goodbit)
7299 {
7300 auto i = is.rdbuf()->sgetc();
7301 if (Traits::eq_int_type(i, Traits::eof()))
7302 {
7303 is.setstate(ios::eofbit);
7304 break;
7305 }
7306 auto wc = Traits::to_char_type(i);
7307 auto c = static_cast<char>(wc);
7308 // is c a valid time zone name or abbreviation character?
7309 if (!(CharT{1} < wc && wc < CharT{127}) || !(isalnum(c) ||
7310 c == '_' || c == '/' || c == '-' || c == '+'))
7311 break;
7312 buf.push_back(c);
7313 is.rdbuf()->sbumpc();
7314 }
7315 if (buf.empty())
7316 is.setstate(ios::failbit);
7317 checked_set(temp_abbrev, buf, {}, is);
7318 }
7319 else
7320 read(is, CharT{'%'}, width, modified, *fmt);
7321 command = nullptr;
7322 width = -1;
7323 modified = CharT{};
7324 }
7325 else
7326 read(is, *fmt);
7327 break;
7328 default:
7329 if (command)
7330 {
7331 if (width == -1 && modified == CharT{} && '0' <= *fmt && *fmt <= '9')
7332 {
7333 width = static_cast<char>(*fmt) - '0';
7334 while ('0' <= fmt[1] && fmt[1] <= '9')
7335 width = 10*width + static_cast<char>(*++fmt) - '0';
7336 }
7337 else
7338 {
7339 if (modified == CharT{})
7340 read(is, CharT{'%'}, width, *fmt);
7341 else
7342 read(is, CharT{'%'}, width, modified, *fmt);
7343 command = nullptr;
7344 width = -1;
7345 modified = CharT{};
7346 }
7347 }
7348 else // !command
7349 {
7350 if (isspace(static_cast<unsigned char>(*fmt)))
7351 {
7352 // space matches 0 or more white space characters
7353 if (is.good())
7354 ws(is);
7355 }
7356 else
7357 read(is, *fmt);
7358 }
7359 break;
7360 }
7361 }
7362 // is.fail() || *fmt == CharT{}
7363 if (is.rdstate() == ios::goodbit && command)
7364 {
7365 if (modified == CharT{})
7366 read(is, CharT{'%'}, width);
7367 else
7368 read(is, CharT{'%'}, width, modified);
7369 }
7370 if (!is.fail())
7371 {
7372 if (y != not_a_2digit_year)
7373 {
7374 // Convert y and an optional C to Y
7375 if (!(0 <= y && y <= 99))
7376 goto broken;
7377 if (C == not_a_century)
7378 {
7379 if (Y == not_a_year)
7380 {
7381 if (y >= 69)
7382 C = 19;
7383 else
7384 C = 20;
7385 }
7386 else
7387 {
7388 C = (Y >= 0 ? Y : Y-100) / 100;
7389 }
7390 }
7391 int tY;
7392 if (C >= 0)
7393 tY = 100*C + y;
7394 else
7395 tY = 100*(C+1) - (y == 0 ? 100 : y);
7396 if (Y != not_a_year && Y != tY)
7397 goto broken;
7398 Y = tY;
7399 }
7400 if (g != not_a_2digit_year)
7401 {
7402 // Convert g and an optional C to G
7403 if (!(0 <= g && g <= 99))
7404 goto broken;
7405 if (C == not_a_century)
7406 {
7407 if (G == not_a_year)
7408 {
7409 if (g >= 69)
7410 C = 19;
7411 else
7412 C = 20;
7413 }
7414 else
7415 {
7416 C = (G >= 0 ? G : G-100) / 100;
7417 }
7418 }
7419 int tG;
7420 if (C >= 0)
7421 tG = 100*C + g;
7422 else
7423 tG = 100*(C+1) - (g == 0 ? 100 : g);
7424 if (G != not_a_year && G != tG)
7425 goto broken;
7426 G = tG;
7427 }
7428 if (Y < static_cast<int>(year::min()) || Y > static_cast<int>(year::max()))
7429 Y = not_a_year;
7430 bool computed = false;
7431 if (G != not_a_year && V != not_a_week_num && wd != not_a_weekday)
7432 {
7433 year_month_day ymd_trial = sys_days(year{G-1}/December/Thursday[last]) +
7434 (Monday-Thursday) + weeks{V-1} +
7435 (weekday{static_cast<unsigned>(wd)}-Monday);
7436 if (Y == not_a_year)
7437 Y = static_cast<int>(ymd_trial.year());
7438 else if (year{Y} != ymd_trial.year())
7439 goto broken;
7440 if (m == not_a_month)
7441 m = static_cast<int>(static_cast<unsigned>(ymd_trial.month()));
7442 else if (month(static_cast<unsigned>(m)) != ymd_trial.month())
7443 goto broken;
7444 if (d == not_a_day)
7445 d = static_cast<int>(static_cast<unsigned>(ymd_trial.day()));
7446 else if (day(static_cast<unsigned>(d)) != ymd_trial.day())
7447 goto broken;
7448 computed = true;
7449 }
7450 if (Y != not_a_year && U != not_a_week_num && wd != not_a_weekday)
7451 {
7452 year_month_day ymd_trial = sys_days(year{Y}/January/Sunday[1]) +
7453 weeks{U-1} +
7454 (weekday{static_cast<unsigned>(wd)} - Sunday);
7455 if (Y == not_a_year)
7456 Y = static_cast<int>(ymd_trial.year());
7457 else if (year{Y} != ymd_trial.year())
7458 goto broken;
7459 if (m == not_a_month)
7460 m = static_cast<int>(static_cast<unsigned>(ymd_trial.month()));
7461 else if (month(static_cast<unsigned>(m)) != ymd_trial.month())
7462 goto broken;
7463 if (d == not_a_day)
7464 d = static_cast<int>(static_cast<unsigned>(ymd_trial.day()));
7465 else if (day(static_cast<unsigned>(d)) != ymd_trial.day())
7466 goto broken;
7467 computed = true;
7468 }
7469 if (Y != not_a_year && W != not_a_week_num && wd != not_a_weekday)
7470 {
7471 year_month_day ymd_trial = sys_days(year{Y}/January/Monday[1]) +
7472 weeks{W-1} +
7473 (weekday{static_cast<unsigned>(wd)} - Monday);
7474 if (Y == not_a_year)
7475 Y = static_cast<int>(ymd_trial.year());
7476 else if (year{Y} != ymd_trial.year())
7477 goto broken;
7478 if (m == not_a_month)
7479 m = static_cast<int>(static_cast<unsigned>(ymd_trial.month()));
7480 else if (month(static_cast<unsigned>(m)) != ymd_trial.month())
7481 goto broken;
7482 if (d == not_a_day)
7483 d = static_cast<int>(static_cast<unsigned>(ymd_trial.day()));
7484 else if (day(static_cast<unsigned>(d)) != ymd_trial.day())
7485 goto broken;
7486 computed = true;
7487 }
7488 if (j != not_a_doy && Y != not_a_year)
7489 {
7490 auto ymd_trial = year_month_day{local_days(year{Y}/1/1) + days{j-1}};
7491 if (m == 0)
7492 m = static_cast<int>(static_cast<unsigned>(ymd_trial.month()));
7493 else if (month(static_cast<unsigned>(m)) != ymd_trial.month())
7494 goto broken;
7495 if (d == 0)
7496 d = static_cast<int>(static_cast<unsigned>(ymd_trial.day()));
7497 else if (day(static_cast<unsigned>(d)) != ymd_trial.day())
7498 goto broken;
7499 j = not_a_doy;
7500 }
7501 auto ymd = year{Y}/m/d;
7502 if (ymd.ok())
7503 {
7504 if (wd == not_a_weekday)
7505 wd = static_cast<int>((weekday(sys_days(ymd)) - Sunday).count());
7506 else if (wd != static_cast<int>((weekday(sys_days(ymd)) - Sunday).count()))
7507 goto broken;
7508 if (!computed)
7509 {
7510 if (G != not_a_year || V != not_a_week_num)
7511 {
7512 sys_days sd = ymd;
7513 auto G_trial = year_month_day{sd + days{3}}.year();
7514 auto start = sys_days((G_trial - years{1})/December/Thursday[last]) +
7515 (Monday - Thursday);
7516 if (sd < start)
7517 {
7518 --G_trial;
7519 if (V != not_a_week_num)
7520 start = sys_days((G_trial - years{1})/December/Thursday[last])
7521 + (Monday - Thursday);
7522 }
7523 if (G != not_a_year && G != static_cast<int>(G_trial))
7524 goto broken;
7525 if (V != not_a_week_num)
7526 {
7527 auto V_trial = duration_cast<weeks>(sd - start).count() + 1;
7528 if (V != V_trial)
7529 goto broken;
7530 }
7531 }
7532 if (U != not_a_week_num)
7533 {
7534 auto start = sys_days(Sunday[1]/January/ymd.year());
7535 auto U_trial = floor<weeks>(sys_days(ymd) - start).count() + 1;
7536 if (U != U_trial)
7537 goto broken;
7538 }
7539 if (W != not_a_week_num)
7540 {
7541 auto start = sys_days(Monday[1]/January/ymd.year());
7542 auto W_trial = floor<weeks>(sys_days(ymd) - start).count() + 1;
7543 if (W != W_trial)
7544 goto broken;
7545 }
7546 }
7547 }
7548 fds.ymd = ymd;
7549 if (I != not_a_hour_12_value)
7550 {
7551 if (!(1 <= I && I <= 12))
7552 goto broken;
7553 if (p != not_a_ampm)
7554 {
7555 // p is in [0, 1] == [AM, PM]
7556 // Store trial H in I
7557 if (I == 12)
7558 --p;
7559 I += p*12;
7560 // Either set H from I or make sure H and I are consistent
7561 if (H == not_a_hour)
7562 H = I;
7563 else if (I != H)
7564 goto broken;
7565 }
7566 else // p == not_a_ampm
7567 {
7568 // if H, make sure H and I could be consistent
7569 if (H != not_a_hour)
7570 {
7571 if (I == 12)
7572 {
7573 if (H != 0 && H != 12)
7574 goto broken;
7575 }
7576 else if (!(I == H || I == H+12))
7577 {
7578 goto broken;
7579 }
7580 }
7581 }
7582 }
7583 if (H != not_a_hour)
7584 {
7585 fds.has_tod = true;
7586 fds.tod = hh_mm_ss<Duration>{hours{H}};
7587 }
7588 if (M != not_a_minute)
7589 {
7590 fds.has_tod = true;
7591 fds.tod.m_ = minutes{M};
7592 }
7593 if (s != not_a_second)
7594 {
7595 fds.has_tod = true;
7596 fds.tod.s_ = detail::decimal_format_seconds<Duration>{s};
7597 }
7598 if (j != not_a_doy)
7599 {
7600 fds.has_tod = true;
7601 fds.tod.h_ += hours{days{j}};
7602 }
7603 if (wd != not_a_weekday)
7604 fds.wd = weekday{static_cast<unsigned>(wd)};
7605 if (abbrev != nullptr)
7606 *abbrev = std::move(temp_abbrev);
7607 if (offset != nullptr && temp_offset != not_a_offset)
7608 *offset = temp_offset;
7609 }
7610 return is;
7611 }
7612 broken:
7613 is.setstate(ios::failbit);
7614 return is;
7615 }
7616
7617 template <class CharT, class Traits, class Alloc = std::allocator<CharT>>
7618 std::basic_istream<CharT, Traits>&
7619 from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, year& y,
7620 std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
7621 std::chrono::minutes* offset = nullptr)
7622 {
7623 using CT = std::chrono::seconds;
7624 fields<CT> fds{};
7625 from_stream(is, fmt, fds, abbrev, offset);
7626 if (!fds.ymd.year().ok())
7627 is.setstate(std::ios::failbit);
7628 if (!is.fail())
7629 y = fds.ymd.year();
7630 return is;
7631 }
7632
7633 template <class CharT, class Traits, class Alloc = std::allocator<CharT>>
7634 std::basic_istream<CharT, Traits>&
7635 from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, month& m,
7636 std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
7637 std::chrono::minutes* offset = nullptr)
7638 {
7639 using CT = std::chrono::seconds;
7640 fields<CT> fds{};
7641 from_stream(is, fmt, fds, abbrev, offset);
7642 if (!fds.ymd.month().ok())
7643 is.setstate(std::ios::failbit);
7644 if (!is.fail())
7645 m = fds.ymd.month();
7646 return is;
7647 }
7648
7649 template <class CharT, class Traits, class Alloc = std::allocator<CharT>>
7650 std::basic_istream<CharT, Traits>&
7651 from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, day& d,
7652 std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
7653 std::chrono::minutes* offset = nullptr)
7654 {
7655 using CT = std::chrono::seconds;
7656 fields<CT> fds{};
7657 from_stream(is, fmt, fds, abbrev, offset);
7658 if (!fds.ymd.day().ok())
7659 is.setstate(std::ios::failbit);
7660 if (!is.fail())
7661 d = fds.ymd.day();
7662 return is;
7663 }
7664
7665 template <class CharT, class Traits, class Alloc = std::allocator<CharT>>
7666 std::basic_istream<CharT, Traits>&
7667 from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, weekday& wd,
7668 std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
7669 std::chrono::minutes* offset = nullptr)
7670 {
7671 using CT = std::chrono::seconds;
7672 fields<CT> fds{};
7673 from_stream(is, fmt, fds, abbrev, offset);
7674 if (!fds.wd.ok())
7675 is.setstate(std::ios::failbit);
7676 if (!is.fail())
7677 wd = fds.wd;
7678 return is;
7679 }
7680
7681 template <class CharT, class Traits, class Alloc = std::allocator<CharT>>
7682 std::basic_istream<CharT, Traits>&
7683 from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, year_month& ym,
7684 std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
7685 std::chrono::minutes* offset = nullptr)
7686 {
7687 using CT = std::chrono::seconds;
7688 fields<CT> fds{};
7689 from_stream(is, fmt, fds, abbrev, offset);
7690 if (!fds.ymd.month().ok())
7691 is.setstate(std::ios::failbit);
7692 if (!is.fail())
7693 ym = fds.ymd.year()/fds.ymd.month();
7694 return is;
7695 }
7696
7697 template <class CharT, class Traits, class Alloc = std::allocator<CharT>>
7698 std::basic_istream<CharT, Traits>&
7699 from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, month_day& md,
7700 std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
7701 std::chrono::minutes* offset = nullptr)
7702 {
7703 using CT = std::chrono::seconds;
7704 fields<CT> fds{};
7705 from_stream(is, fmt, fds, abbrev, offset);
7706 if (!fds.ymd.month().ok() || !fds.ymd.day().ok())
7707 is.setstate(std::ios::failbit);
7708 if (!is.fail())
7709 md = fds.ymd.month()/fds.ymd.day();
7710 return is;
7711 }
7712
7713 template <class CharT, class Traits, class Alloc = std::allocator<CharT>>
7714 std::basic_istream<CharT, Traits>&
7715 from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
7716 year_month_day& ymd, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
7717 std::chrono::minutes* offset = nullptr)
7718 {
7719 using CT = std::chrono::seconds;
7720 fields<CT> fds{};
7721 from_stream(is, fmt, fds, abbrev, offset);
7722 if (!fds.ymd.ok())
7723 is.setstate(std::ios::failbit);
7724 if (!is.fail())
7725 ymd = fds.ymd;
7726 return is;
7727 }
7728
7729 template <class Duration, class CharT, class Traits, class Alloc = std::allocator<CharT>>
7730 std::basic_istream<CharT, Traits>&
7731 from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
7732 sys_time<Duration>& tp, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
7733 std::chrono::minutes* offset = nullptr)
7734 {
7735 using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
7736 std::chrono::minutes offset_local{};
7737 auto offptr = offset ? offset : &offset_local;
7738 fields<CT> fds{};
7739 fds.has_tod = true;
7740 from_stream(is, fmt, fds, abbrev, offptr);
7741 if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
7742 is.setstate(std::ios::failbit);
7743 if (!is.fail())
7744 tp = round<Duration>(sys_days(fds.ymd) - *offptr + fds.tod.to_duration());
7745 return is;
7746 }
7747
7748 template <class Duration, class CharT, class Traits, class Alloc = std::allocator<CharT>>
7749 std::basic_istream<CharT, Traits>&
7750 from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
7751 local_time<Duration>& tp, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
7752 std::chrono::minutes* offset = nullptr)
7753 {
7754 using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
7755 fields<CT> fds{};
7756 fds.has_tod = true;
7757 from_stream(is, fmt, fds, abbrev, offset);
7758 if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
7759 is.setstate(std::ios::failbit);
7760 if (!is.fail())
7761 tp = round<Duration>(local_seconds{local_days(fds.ymd)} + fds.tod.to_duration());
7762 return is;
7763 }
7764
7765 template <class Rep, class Period, class CharT, class Traits, class Alloc = std::allocator<CharT>>
7766 std::basic_istream<CharT, Traits>&
7767 from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
7768 std::chrono::duration<Rep, Period>& d,
7769 std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
7770 std::chrono::minutes* offset = nullptr)
7771 {
7772 using Duration = std::chrono::duration<Rep, Period>;
7773 using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
7774 fields<CT> fds{};
7775 from_stream(is, fmt, fds, abbrev, offset);
7776 if (!fds.has_tod)
7777 is.setstate(std::ios::failbit);
7778 if (!is.fail())
7779 d = std::chrono::duration_cast<Duration>(fds.tod.to_duration());
7780 return is;
7781 }
7782
7783 template <class Parsable, class CharT, class Traits = std::char_traits<CharT>,
7784 class Alloc = std::allocator<CharT>>
7785 struct parse_manip
7786 {
7787 const std::basic_string<CharT, Traits, Alloc> format_;
7788 Parsable& tp_;
7789 std::basic_string<CharT, Traits, Alloc>* abbrev_;
7790 std::chrono::minutes* offset_;
7791
7792 public:
7793 parse_manip(std::basic_string<CharT, Traits, Alloc> format, Parsable& tp,
7794 std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
7795 std::chrono::minutes* offset = nullptr)
7796 : format_(std::move(format))
7797 , tp_(tp)
7798 , abbrev_(abbrev)
7799 , offset_(offset)
7800 {}
7801
7802 };
7803
7804 template <class Parsable, class CharT, class Traits, class Alloc>
7805 std::basic_istream<CharT, Traits>&
7806 operator>>(std::basic_istream<CharT, Traits>& is,
7807 const parse_manip<Parsable, CharT, Traits, Alloc>& x)
7808 {
7809 return from_stream(is, x.format_.c_str(), x.tp_, x.abbrev_, x.offset_);
7810 }
7811
7812 template <class Parsable, class CharT, class Traits, class Alloc>
7813 inline
7814 auto
7815 parse(const std::basic_string<CharT, Traits, Alloc>& format, Parsable& tp)
7816 -> decltype(from_stream(std::declval<std::basic_istream<CharT, Traits>&>(),
7817 format.c_str(), tp),
7818 parse_manip<Parsable, CharT, Traits, Alloc>{format, tp})
7819 {
7820 return {format, tp};
7821 }
7822
7823 template <class Parsable, class CharT, class Traits, class Alloc>
7824 inline
7825 auto
7826 parse(const std::basic_string<CharT, Traits, Alloc>& format, Parsable& tp,
7827 std::basic_string<CharT, Traits, Alloc>& abbrev)
7828 -> decltype(from_stream(std::declval<std::basic_istream<CharT, Traits>&>(),
7829 format.c_str(), tp, &abbrev),
7830 parse_manip<Parsable, CharT, Traits, Alloc>{format, tp, &abbrev})
7831 {
7832 return {format, tp, &abbrev};
7833 }
7834
7835 template <class Parsable, class CharT, class Traits, class Alloc>
7836 inline
7837 auto
7838 parse(const std::basic_string<CharT, Traits, Alloc>& format, Parsable& tp,
7839 std::chrono::minutes& offset)
7840 -> decltype(from_stream(std::declval<std::basic_istream<CharT, Traits>&>(),
7841 format.c_str(), tp,
7842 std::declval<std::basic_string<CharT, Traits, Alloc>*>(),
7843 &offset),
7844 parse_manip<Parsable, CharT, Traits, Alloc>{format, tp, nullptr, &offset})
7845 {
7846 return {format, tp, nullptr, &offset};
7847 }
7848
7849 template <class Parsable, class CharT, class Traits, class Alloc>
7850 inline
7851 auto
7852 parse(const std::basic_string<CharT, Traits, Alloc>& format, Parsable& tp,
7853 std::basic_string<CharT, Traits, Alloc>& abbrev, std::chrono::minutes& offset)
7854 -> decltype(from_stream(std::declval<std::basic_istream<CharT, Traits>&>(),
7855 format.c_str(), tp, &abbrev, &offset),
7856 parse_manip<Parsable, CharT, Traits, Alloc>{format, tp, &abbrev, &offset})
7857 {
7858 return {format, tp, &abbrev, &offset};
7859 }
7860
7861 // const CharT* formats
7862
7863 template <class Parsable, class CharT>
7864 inline
7865 auto
7866 parse(const CharT* format, Parsable& tp)
7867 -> decltype(from_stream(std::declval<std::basic_istream<CharT>&>(), format, tp),
7868 parse_manip<Parsable, CharT>{format, tp})
7869 {
7870 return {format, tp};
7871 }
7872
7873 template <class Parsable, class CharT, class Traits, class Alloc>
7874 inline
7875 auto
7876 parse(const CharT* format, Parsable& tp, std::basic_string<CharT, Traits, Alloc>& abbrev)
7877 -> decltype(from_stream(std::declval<std::basic_istream<CharT, Traits>&>(), format,
7878 tp, &abbrev),
7879 parse_manip<Parsable, CharT, Traits, Alloc>{format, tp, &abbrev})
7880 {
7881 return {format, tp, &abbrev};
7882 }
7883
7884 template <class Parsable, class CharT>
7885 inline
7886 auto
7887 parse(const CharT* format, Parsable& tp, std::chrono::minutes& offset)
7888 -> decltype(from_stream(std::declval<std::basic_istream<CharT>&>(), format,
7889 tp, std::declval<std::basic_string<CharT>*>(), &offset),
7890 parse_manip<Parsable, CharT>{format, tp, nullptr, &offset})
7891 {
7892 return {format, tp, nullptr, &offset};
7893 }
7894
7895 template <class Parsable, class CharT, class Traits, class Alloc>
7896 inline
7897 auto
7898 parse(const CharT* format, Parsable& tp,
7899 std::basic_string<CharT, Traits, Alloc>& abbrev, std::chrono::minutes& offset)
7900 -> decltype(from_stream(std::declval<std::basic_istream<CharT, Traits>&>(), format,
7901 tp, &abbrev, &offset),
7902 parse_manip<Parsable, CharT, Traits, Alloc>{format, tp, &abbrev, &offset})
7903 {
7904 return {format, tp, &abbrev, &offset};
7905 }
7906
7907 // duration streaming
7908
7909 template <class CharT, class Traits, class Rep, class Period>
7910 inline
7911 std::basic_ostream<CharT, Traits>&
7912 operator<<(std::basic_ostream<CharT, Traits>& os,
7913 const std::chrono::duration<Rep, Period>& d)
7914 {
7915 return os << detail::make_string<CharT, Traits>::from(d.count()) +
7916 detail::get_units<CharT>(typename Period::type{});
7917 }
7918
7919 } // namespace date
7920
7921 #ifdef _MSC_VER
7922 # pragma warning(pop)
7923 #endif
7924
7925 #ifdef __GNUC__
7926 # pragma GCC diagnostic pop
7927 #endif
7928
7929 #endif // DATE_H