Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-08-28 08:27:13

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