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