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