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