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