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