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