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