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