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