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