File indexing completed on 2025-08-28 08:27:13
0001 #ifndef DATE_H
0002 #define DATE_H
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
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
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
0077 # pragma GCC diagnostic ignored "-Wmissing-field-initializers"
0078 # endif
0079 #endif
0080
0081 #ifdef _MSC_VER
0082 # pragma warning(push)
0083
0084 # pragma warning(disable : 4127)
0085 #endif
0086
0087 namespace arrow_vendored::date
0088 {
0089
0090
0091
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
0100 # ifndef _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING
0101 # define _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING
0102 # endif
0103 # if _MSC_VER < 1910
0104
0105 # define CONSTDATA const
0106 # define CONSTCD11
0107 # define CONSTCD14
0108 # define NOEXCEPT _NOEXCEPT
0109 # else
0110
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
0119 # define CONSTDATA constexpr const
0120 # define CONSTCD11 constexpr
0121 # define CONSTCD14
0122 # define NOEXCEPT noexcept
0123
0124 #elif __cplusplus >= 201402
0125
0126 # define CONSTDATA constexpr const
0127 # define CONSTCD11 constexpr
0128 # define CONSTCD14 constexpr
0129 # define NOEXCEPT noexcept
0130 #else
0131
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
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
0153
0154
0155 #ifdef sun
0156 # undef sun
0157 #endif
0158
0159
0160
0161
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 }
0169
0170
0171
0172
0173
0174
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
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
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
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
0316
0317
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
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
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
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
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
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 }
0539
0540
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
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
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
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
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
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
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
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
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 }
0970 #endif
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988
0989
0990
0991
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
1010
1011
1012
1013
1014
1015
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
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 }
1197
1198
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
1239
1240 #if HAS_CHRONO_ROUNDING == 0
1241
1242
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
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
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
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
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
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
1356
1357 using std::chrono::floor;
1358 using std::chrono::ceil;
1359 using std::chrono::round;
1360 using std::chrono::abs;
1361
1362 #endif
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 }
1404
1405
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
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 }
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
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 }
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
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 }
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
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 }
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
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 }
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
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
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
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 }
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
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 }
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
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 }
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
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 }
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
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 }
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
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 }
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
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 }
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
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 }
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
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);
2984 auto const doy = (153*(m > 2 ? m-3 : m+9) + 2)/5 + d-1;
2985 auto const doe = yoe * 365 + yoe/4 - yoe/100 + doy;
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);
3096 auto const yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365;
3097 auto const y = static_cast<days::rep>(yoe) + era * 400;
3098 auto const doy = doe - (365*yoe + yoe/4 - yoe/100);
3099 auto const mp = (5*doy + 2)/153;
3100 auto const d = doy - (153*mp+2)/5 + 1;
3101 auto const m = mp < 10 ? mp+3 : mp-9;
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
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
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
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
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
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
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
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
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
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
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
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
3904
3905 namespace detail
3906 {
3907
3908 struct undocumented {explicit undocumented() = default;};
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
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 }
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
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
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 }
4777
4778
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
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
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
4850 os.setstate(std::ios::failbit);
4851 return 0;
4852 }
4853 return static_cast<unsigned>(fds.ymd.month());
4854 }
4855
4856 }
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;
4952 size_t n_does_match = 0;
4953
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
4967 for (size_t indx = 0; is && n_might_match > 0; ++indx)
4968 {
4969
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
4979
4980
4981
4982
4983
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
5007 if (consume)
5008 {
5009 (void)is.get();
5010
5011
5012
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
5028
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 }
5038
5039 #endif
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
5089 os << weekday_names().first[tm.tm_wday+7*(*fmt == 'a')];
5090 #endif
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
5114 os << month_names().first[tm.tm_mon+12*(*fmt != 'B')];
5115 #endif
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
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
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
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
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
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
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
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
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 }
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;
6617 int y = not_a_2digit_year;
6618 int g = not_a_2digit_year;
6619 int G = not_a_year;
6620 int C = not_a_century;
6621 int m = not_a_month;
6622 int d = not_a_day;
6623 int j = not_a_doy;
6624 int wd = not_a_weekday;
6625 int H = not_a_hour;
6626 int I = not_a_hour_12_value;
6627 int p = not_a_ampm;
6628 int M = not_a_minute;
6629 Duration s = not_a_second;
6630 int U = not_a_week_num;
6631 int V = not_a_week_num;
6632 int W = not_a_week_num;
6633 std::basic_string<CharT, Traits, Alloc> temp_abbrev;
6634 minutes temp_offset = not_a_offset;
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':
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
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
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
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
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
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
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
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
7148
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
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
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
7645 {
7646 if (isspace(static_cast<unsigned char>(*fmt)))
7647 {
7648
7649 if (is.good())
7650 ws(is);
7651 }
7652 else
7653 read(is, *fmt);
7654 }
7655 break;
7656 }
7657 }
7658
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
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
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
7848
7849 if (I == 12)
7850 --p;
7851 I += p*12;
7852
7853 if (H == not_a_hour)
7854 H = I;
7855 else if (I != H)
7856 goto broken;
7857 }
7858 else
7859 {
7860
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
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
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
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
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 }
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