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