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