ferencd@0: #ifndef DATE_H ferencd@0: #define DATE_H ferencd@0: ferencd@0: // The MIT License (MIT) ferencd@0: // ferencd@0: // Copyright (c) 2015, 2016, 2017 Howard Hinnant ferencd@0: // Copyright (c) 2016 Adrian Colomitchi ferencd@0: // Copyright (c) 2017 Florian Dang ferencd@0: // Copyright (c) 2017 Paul Thompson ferencd@0: // Copyright (c) 2018, 2019 Tomasz KamiƄski ferencd@0: // ferencd@0: // Permission is hereby granted, free of charge, to any person obtaining a copy ferencd@0: // of this software and associated documentation files (the "Software"), to deal ferencd@0: // in the Software without restriction, including without limitation the rights ferencd@0: // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ferencd@0: // copies of the Software, and to permit persons to whom the Software is ferencd@0: // furnished to do so, subject to the following conditions: ferencd@0: // ferencd@0: // The above copyright notice and this permission notice shall be included in all ferencd@0: // copies or substantial portions of the Software. ferencd@0: // ferencd@0: // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ferencd@0: // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ferencd@0: // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ferencd@0: // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ferencd@0: // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ferencd@0: // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ferencd@0: // SOFTWARE. ferencd@0: // ferencd@0: // Our apologies. When the previous paragraph was written, lowercase had not yet ferencd@0: // been invented (that would involve another several millennia of evolution). ferencd@0: // We did not mean to shout. ferencd@0: ferencd@0: #ifndef HAS_STRING_VIEW ferencd@0: # if __cplusplus >= 201703 || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) ferencd@0: # define HAS_STRING_VIEW 1 ferencd@0: # else ferencd@0: # define HAS_STRING_VIEW 0 ferencd@0: # endif ferencd@0: #endif // HAS_STRING_VIEW ferencd@0: ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #if !(__cplusplus >= 201402) ferencd@0: # include ferencd@0: #endif ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #if HAS_STRING_VIEW ferencd@0: # include ferencd@0: #endif ferencd@0: #include ferencd@0: #include ferencd@0: ferencd@0: #ifdef __GNUC__ ferencd@0: # pragma GCC diagnostic push ferencd@0: # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR > 7) ferencd@0: # pragma GCC diagnostic ignored "-Wpedantic" ferencd@0: # endif ferencd@0: # if __GNUC__ < 5 ferencd@0: // GCC 4.9 Bug 61489 Wrong warning with -Wmissing-field-initializers ferencd@0: # pragma GCC diagnostic ignored "-Wmissing-field-initializers" ferencd@0: # endif ferencd@0: #endif ferencd@0: ferencd@0: #ifdef _MSC_VER ferencd@0: # pragma warning(push) ferencd@0: // warning C4127: conditional expression is constant ferencd@0: # pragma warning(disable : 4127) ferencd@0: #endif ferencd@0: ferencd@0: namespace date ferencd@0: { ferencd@0: ferencd@0: //---------------+ ferencd@0: // Configuration | ferencd@0: //---------------+ ferencd@0: ferencd@0: #ifndef ONLY_C_LOCALE ferencd@0: # define ONLY_C_LOCALE 0 ferencd@0: #endif ferencd@0: ferencd@0: #if defined(_MSC_VER) && (!defined(__clang__) || (_MSC_VER < 1910)) ferencd@0: // MSVC ferencd@0: # ifndef _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING ferencd@0: # define _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING ferencd@0: # endif ferencd@0: # if _MSC_VER < 1910 ferencd@0: // before VS2017 ferencd@0: # define CONSTDATA const ferencd@0: # define CONSTCD11 ferencd@0: # define CONSTCD14 ferencd@0: # define NOEXCEPT _NOEXCEPT ferencd@0: # else ferencd@0: // VS2017 and later ferencd@0: # define CONSTDATA constexpr const ferencd@0: # define CONSTCD11 constexpr ferencd@0: # define CONSTCD14 constexpr ferencd@0: # define NOEXCEPT noexcept ferencd@0: # endif ferencd@0: ferencd@0: #elif defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x5150 ferencd@0: // Oracle Developer Studio 12.6 and earlier ferencd@0: # define CONSTDATA constexpr const ferencd@0: # define CONSTCD11 constexpr ferencd@0: # define CONSTCD14 ferencd@0: # define NOEXCEPT noexcept ferencd@0: ferencd@0: #elif __cplusplus >= 201402 ferencd@0: // C++14 ferencd@0: # define CONSTDATA constexpr const ferencd@0: # define CONSTCD11 constexpr ferencd@0: # define CONSTCD14 constexpr ferencd@0: # define NOEXCEPT noexcept ferencd@0: #else ferencd@0: // C++11 ferencd@0: # define CONSTDATA constexpr const ferencd@0: # define CONSTCD11 constexpr ferencd@0: # define CONSTCD14 ferencd@0: # define NOEXCEPT noexcept ferencd@0: #endif ferencd@0: ferencd@0: #ifndef HAS_UNCAUGHT_EXCEPTIONS ferencd@0: # if __cplusplus > 201703 || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L) ferencd@0: # define HAS_UNCAUGHT_EXCEPTIONS 1 ferencd@0: # else ferencd@0: # define HAS_UNCAUGHT_EXCEPTIONS 0 ferencd@0: # endif ferencd@0: #endif // HAS_UNCAUGHT_EXCEPTIONS ferencd@0: ferencd@0: #ifndef HAS_VOID_T ferencd@0: # if __cplusplus >= 201703 || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) ferencd@0: # define HAS_VOID_T 1 ferencd@0: # else ferencd@0: # define HAS_VOID_T 0 ferencd@0: # endif ferencd@0: #endif // HAS_VOID_T ferencd@0: ferencd@0: // Protect from Oracle sun macro ferencd@0: #ifdef sun ferencd@0: # undef sun ferencd@0: #endif ferencd@0: ferencd@0: //-----------+ ferencd@0: // Interface | ferencd@0: //-----------+ ferencd@0: ferencd@0: // durations ferencd@0: ferencd@0: using days = std::chrono::duration ferencd@0: , std::chrono::hours::period>::type>; ferencd@0: ferencd@0: using weeks = std::chrono::duration ferencd@0: , days::period>::type>; ferencd@0: ferencd@0: using years = std::chrono::duration ferencd@0: , days::period>::type>; ferencd@0: ferencd@0: using months = std::chrono::duration ferencd@0: >::type>; ferencd@0: ferencd@0: // time_point ferencd@0: ferencd@0: template ferencd@0: using sys_time = std::chrono::time_point; ferencd@0: ferencd@0: using sys_days = sys_time; ferencd@0: using sys_seconds = sys_time; ferencd@0: ferencd@0: struct local_t {}; ferencd@0: ferencd@0: template ferencd@0: using local_time = std::chrono::time_point; ferencd@0: ferencd@0: using local_seconds = local_time; ferencd@0: using local_days = local_time; ferencd@0: ferencd@0: // types ferencd@0: ferencd@0: struct last_spec ferencd@0: { ferencd@0: explicit last_spec() = default; ferencd@0: }; ferencd@0: ferencd@0: class day; ferencd@0: class month; ferencd@0: class year; ferencd@0: ferencd@0: class weekday; ferencd@0: class weekday_indexed; ferencd@0: class weekday_last; ferencd@0: ferencd@0: class month_day; ferencd@0: class month_day_last; ferencd@0: class month_weekday; ferencd@0: class month_weekday_last; ferencd@0: ferencd@0: class year_month; ferencd@0: ferencd@0: class year_month_day; ferencd@0: class year_month_day_last; ferencd@0: class year_month_weekday; ferencd@0: class year_month_weekday_last; ferencd@0: ferencd@0: // date composition operators ferencd@0: ferencd@0: CONSTCD11 year_month operator/(const year& y, const month& m) NOEXCEPT; ferencd@0: CONSTCD11 year_month operator/(const year& y, int m) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 month_day operator/(const day& d, const month& m) NOEXCEPT; ferencd@0: CONSTCD11 month_day operator/(const day& d, int m) NOEXCEPT; ferencd@0: CONSTCD11 month_day operator/(const month& m, const day& d) NOEXCEPT; ferencd@0: CONSTCD11 month_day operator/(const month& m, int d) NOEXCEPT; ferencd@0: CONSTCD11 month_day operator/(int m, const day& d) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 month_day_last operator/(const month& m, last_spec) NOEXCEPT; ferencd@0: CONSTCD11 month_day_last operator/(int m, last_spec) NOEXCEPT; ferencd@0: CONSTCD11 month_day_last operator/(last_spec, const month& m) NOEXCEPT; ferencd@0: CONSTCD11 month_day_last operator/(last_spec, int m) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 month_weekday operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT; ferencd@0: CONSTCD11 month_weekday operator/(int m, const weekday_indexed& wdi) NOEXCEPT; ferencd@0: CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT; ferencd@0: CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, int m) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 month_weekday_last operator/(const month& m, const weekday_last& wdl) NOEXCEPT; ferencd@0: CONSTCD11 month_weekday_last operator/(int m, const weekday_last& wdl) NOEXCEPT; ferencd@0: CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, const month& m) NOEXCEPT; ferencd@0: CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, int m) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 year_month_day operator/(const year_month& ym, const day& d) NOEXCEPT; ferencd@0: CONSTCD11 year_month_day operator/(const year_month& ym, int d) NOEXCEPT; ferencd@0: CONSTCD11 year_month_day operator/(const year& y, const month_day& md) NOEXCEPT; ferencd@0: CONSTCD11 year_month_day operator/(int y, const month_day& md) NOEXCEPT; ferencd@0: CONSTCD11 year_month_day operator/(const month_day& md, const year& y) NOEXCEPT; ferencd@0: CONSTCD11 year_month_day operator/(const month_day& md, int y) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_day_last operator/(const year_month& ym, last_spec) NOEXCEPT; ferencd@0: CONSTCD11 ferencd@0: year_month_day_last operator/(const year& y, const month_day_last& mdl) NOEXCEPT; ferencd@0: CONSTCD11 ferencd@0: year_month_day_last operator/(int y, const month_day_last& mdl) NOEXCEPT; ferencd@0: CONSTCD11 ferencd@0: year_month_day_last operator/(const month_day_last& mdl, const year& y) NOEXCEPT; ferencd@0: CONSTCD11 ferencd@0: year_month_day_last operator/(const month_day_last& mdl, int y) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_weekday ferencd@0: operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_weekday ferencd@0: operator/(const year& y, const month_weekday& mwd) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_weekday ferencd@0: operator/(int y, const month_weekday& mwd) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_weekday ferencd@0: operator/(const month_weekday& mwd, const year& y) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_weekday ferencd@0: operator/(const month_weekday& mwd, int y) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_weekday_last ferencd@0: operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_weekday_last ferencd@0: operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_weekday_last ferencd@0: operator/(int y, const month_weekday_last& mwdl) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_weekday_last ferencd@0: operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_weekday_last ferencd@0: operator/(const month_weekday_last& mwdl, int y) NOEXCEPT; ferencd@0: ferencd@0: // Detailed interface ferencd@0: ferencd@0: // day ferencd@0: ferencd@0: class day ferencd@0: { ferencd@0: unsigned char d_; ferencd@0: ferencd@0: public: ferencd@0: day() = default; ferencd@0: explicit CONSTCD11 day(unsigned d) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD14 day& operator++() NOEXCEPT; ferencd@0: CONSTCD14 day operator++(int) NOEXCEPT; ferencd@0: CONSTCD14 day& operator--() NOEXCEPT; ferencd@0: CONSTCD14 day operator--(int) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD14 day& operator+=(const days& d) NOEXCEPT; ferencd@0: CONSTCD14 day& operator-=(const days& d) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 explicit operator unsigned() const NOEXCEPT; ferencd@0: CONSTCD11 bool ok() const NOEXCEPT; ferencd@0: }; ferencd@0: ferencd@0: CONSTCD11 bool operator==(const day& x, const day& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator!=(const day& x, const day& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator< (const day& x, const day& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator> (const day& x, const day& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator<=(const day& x, const day& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator>=(const day& x, const day& y) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 day operator+(const day& x, const days& y) NOEXCEPT; ferencd@0: CONSTCD11 day operator+(const days& x, const day& y) NOEXCEPT; ferencd@0: CONSTCD11 day operator-(const day& x, const days& y) NOEXCEPT; ferencd@0: CONSTCD11 days operator-(const day& x, const day& y) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const day& d); ferencd@0: ferencd@0: // month ferencd@0: ferencd@0: class month ferencd@0: { ferencd@0: unsigned char m_; ferencd@0: ferencd@0: public: ferencd@0: month() = default; ferencd@0: explicit CONSTCD11 month(unsigned m) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD14 month& operator++() NOEXCEPT; ferencd@0: CONSTCD14 month operator++(int) NOEXCEPT; ferencd@0: CONSTCD14 month& operator--() NOEXCEPT; ferencd@0: CONSTCD14 month operator--(int) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD14 month& operator+=(const months& m) NOEXCEPT; ferencd@0: CONSTCD14 month& operator-=(const months& m) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 explicit operator unsigned() const NOEXCEPT; ferencd@0: CONSTCD11 bool ok() const NOEXCEPT; ferencd@0: }; ferencd@0: ferencd@0: CONSTCD11 bool operator==(const month& x, const month& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator!=(const month& x, const month& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator< (const month& x, const month& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator> (const month& x, const month& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator<=(const month& x, const month& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator>=(const month& x, const month& y) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD14 month operator+(const month& x, const months& y) NOEXCEPT; ferencd@0: CONSTCD14 month operator+(const months& x, const month& y) NOEXCEPT; ferencd@0: CONSTCD14 month operator-(const month& x, const months& y) NOEXCEPT; ferencd@0: CONSTCD14 months operator-(const month& x, const month& y) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const month& m); ferencd@0: ferencd@0: // year ferencd@0: ferencd@0: class year ferencd@0: { ferencd@0: short y_; ferencd@0: ferencd@0: public: ferencd@0: year() = default; ferencd@0: explicit CONSTCD11 year(int y) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD14 year& operator++() NOEXCEPT; ferencd@0: CONSTCD14 year operator++(int) NOEXCEPT; ferencd@0: CONSTCD14 year& operator--() NOEXCEPT; ferencd@0: CONSTCD14 year operator--(int) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD14 year& operator+=(const years& y) NOEXCEPT; ferencd@0: CONSTCD14 year& operator-=(const years& y) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 year operator-() const NOEXCEPT; ferencd@0: CONSTCD11 year operator+() const NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 bool is_leap() const NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 explicit operator int() const NOEXCEPT; ferencd@0: CONSTCD11 bool ok() const NOEXCEPT; ferencd@0: ferencd@0: static CONSTCD11 year min() NOEXCEPT { return year{-32767}; } ferencd@0: static CONSTCD11 year max() NOEXCEPT { return year{32767}; } ferencd@0: }; ferencd@0: ferencd@0: CONSTCD11 bool operator==(const year& x, const year& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator!=(const year& x, const year& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator< (const year& x, const year& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator> (const year& x, const year& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator<=(const year& x, const year& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator>=(const year& x, const year& y) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 year operator+(const year& x, const years& y) NOEXCEPT; ferencd@0: CONSTCD11 year operator+(const years& x, const year& y) NOEXCEPT; ferencd@0: CONSTCD11 year operator-(const year& x, const years& y) NOEXCEPT; ferencd@0: CONSTCD11 years operator-(const year& x, const year& y) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const year& y); ferencd@0: ferencd@0: // weekday ferencd@0: ferencd@0: class weekday ferencd@0: { ferencd@0: unsigned char wd_; ferencd@0: public: ferencd@0: weekday() = default; ferencd@0: explicit CONSTCD11 weekday(unsigned wd) NOEXCEPT; ferencd@0: CONSTCD14 weekday(const sys_days& dp) NOEXCEPT; ferencd@0: CONSTCD14 explicit weekday(const local_days& dp) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD14 weekday& operator++() NOEXCEPT; ferencd@0: CONSTCD14 weekday operator++(int) NOEXCEPT; ferencd@0: CONSTCD14 weekday& operator--() NOEXCEPT; ferencd@0: CONSTCD14 weekday operator--(int) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD14 weekday& operator+=(const days& d) NOEXCEPT; ferencd@0: CONSTCD14 weekday& operator-=(const days& d) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 bool ok() const NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 unsigned c_encoding() const NOEXCEPT; ferencd@0: CONSTCD11 unsigned iso_encoding() const NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 weekday_indexed operator[](unsigned index) const NOEXCEPT; ferencd@0: CONSTCD11 weekday_last operator[](last_spec) const NOEXCEPT; ferencd@0: ferencd@0: private: ferencd@0: static CONSTCD14 unsigned char weekday_from_days(int z) NOEXCEPT; ferencd@0: ferencd@0: friend CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT; ferencd@0: friend CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT; ferencd@0: friend CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT; ferencd@0: template ferencd@0: friend std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const weekday& wd); ferencd@0: friend class weekday_indexed; ferencd@0: }; ferencd@0: ferencd@0: CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator!=(const weekday& x, const weekday& y) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT; ferencd@0: CONSTCD14 weekday operator+(const days& x, const weekday& y) NOEXCEPT; ferencd@0: CONSTCD14 weekday operator-(const weekday& x, const days& y) NOEXCEPT; ferencd@0: CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const weekday& wd); ferencd@0: ferencd@0: // weekday_indexed ferencd@0: ferencd@0: class weekday_indexed ferencd@0: { ferencd@0: unsigned char wd_ : 4; ferencd@0: unsigned char index_ : 4; ferencd@0: ferencd@0: public: ferencd@0: weekday_indexed() = default; ferencd@0: CONSTCD11 weekday_indexed(const date::weekday& wd, unsigned index) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 date::weekday weekday() const NOEXCEPT; ferencd@0: CONSTCD11 unsigned index() const NOEXCEPT; ferencd@0: CONSTCD11 bool ok() const NOEXCEPT; ferencd@0: }; ferencd@0: ferencd@0: CONSTCD11 bool operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const weekday_indexed& wdi); ferencd@0: ferencd@0: // weekday_last ferencd@0: ferencd@0: class weekday_last ferencd@0: { ferencd@0: date::weekday wd_; ferencd@0: ferencd@0: public: ferencd@0: explicit CONSTCD11 weekday_last(const date::weekday& wd) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 date::weekday weekday() const NOEXCEPT; ferencd@0: CONSTCD11 bool ok() const NOEXCEPT; ferencd@0: }; ferencd@0: ferencd@0: CONSTCD11 bool operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const weekday_last& wdl); ferencd@0: ferencd@0: namespace detail ferencd@0: { ferencd@0: ferencd@0: struct unspecified_month_disambiguator {}; ferencd@0: ferencd@0: } // namespace detail ferencd@0: ferencd@0: // year_month ferencd@0: ferencd@0: class year_month ferencd@0: { ferencd@0: date::year y_; ferencd@0: date::month m_; ferencd@0: ferencd@0: public: ferencd@0: year_month() = default; ferencd@0: CONSTCD11 year_month(const date::year& y, const date::month& m) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 date::year year() const NOEXCEPT; ferencd@0: CONSTCD11 date::month month() const NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 year_month& operator+=(const months& dm) NOEXCEPT; ferencd@0: template ferencd@0: CONSTCD14 year_month& operator-=(const months& dm) NOEXCEPT; ferencd@0: CONSTCD14 year_month& operator+=(const years& dy) NOEXCEPT; ferencd@0: CONSTCD14 year_month& operator-=(const years& dy) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 bool ok() const NOEXCEPT; ferencd@0: }; ferencd@0: ferencd@0: CONSTCD11 bool operator==(const year_month& x, const year_month& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator!=(const year_month& x, const year_month& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator< (const year_month& x, const year_month& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator> (const year_month& x, const year_month& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator<=(const year_month& x, const year_month& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator>=(const year_month& x, const year_month& y) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 year_month operator+(const year_month& ym, const months& dm) NOEXCEPT; ferencd@0: template ferencd@0: CONSTCD14 year_month operator+(const months& dm, const year_month& ym) NOEXCEPT; ferencd@0: template ferencd@0: CONSTCD14 year_month operator-(const year_month& ym, const months& dm) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 months operator-(const year_month& x, const year_month& y) NOEXCEPT; ferencd@0: CONSTCD11 year_month operator+(const year_month& ym, const years& dy) NOEXCEPT; ferencd@0: CONSTCD11 year_month operator+(const years& dy, const year_month& ym) NOEXCEPT; ferencd@0: CONSTCD11 year_month operator-(const year_month& ym, const years& dy) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const year_month& ym); ferencd@0: ferencd@0: // month_day ferencd@0: ferencd@0: class month_day ferencd@0: { ferencd@0: date::month m_; ferencd@0: date::day d_; ferencd@0: ferencd@0: public: ferencd@0: month_day() = default; ferencd@0: CONSTCD11 month_day(const date::month& m, const date::day& d) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 date::month month() const NOEXCEPT; ferencd@0: CONSTCD11 date::day day() const NOEXCEPT; ferencd@0: ferencd@0: CONSTCD14 bool ok() const NOEXCEPT; ferencd@0: }; ferencd@0: ferencd@0: CONSTCD11 bool operator==(const month_day& x, const month_day& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator!=(const month_day& x, const month_day& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator< (const month_day& x, const month_day& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator> (const month_day& x, const month_day& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator<=(const month_day& x, const month_day& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator>=(const month_day& x, const month_day& y) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const month_day& md); ferencd@0: ferencd@0: // month_day_last ferencd@0: ferencd@0: class month_day_last ferencd@0: { ferencd@0: date::month m_; ferencd@0: ferencd@0: public: ferencd@0: CONSTCD11 explicit month_day_last(const date::month& m) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 date::month month() const NOEXCEPT; ferencd@0: CONSTCD11 bool ok() const NOEXCEPT; ferencd@0: }; ferencd@0: ferencd@0: CONSTCD11 bool operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator< (const month_day_last& x, const month_day_last& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator> (const month_day_last& x, const month_day_last& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const month_day_last& mdl); ferencd@0: ferencd@0: // month_weekday ferencd@0: ferencd@0: class month_weekday ferencd@0: { ferencd@0: date::month m_; ferencd@0: date::weekday_indexed wdi_; ferencd@0: public: ferencd@0: CONSTCD11 month_weekday(const date::month& m, ferencd@0: const date::weekday_indexed& wdi) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 date::month month() const NOEXCEPT; ferencd@0: CONSTCD11 date::weekday_indexed weekday_indexed() const NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 bool ok() const NOEXCEPT; ferencd@0: }; ferencd@0: ferencd@0: CONSTCD11 bool operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const month_weekday& mwd); ferencd@0: ferencd@0: // month_weekday_last ferencd@0: ferencd@0: class month_weekday_last ferencd@0: { ferencd@0: date::month m_; ferencd@0: date::weekday_last wdl_; ferencd@0: ferencd@0: public: ferencd@0: CONSTCD11 month_weekday_last(const date::month& m, ferencd@0: const date::weekday_last& wd) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 date::month month() const NOEXCEPT; ferencd@0: CONSTCD11 date::weekday_last weekday_last() const NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 bool ok() const NOEXCEPT; ferencd@0: }; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: bool operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT; ferencd@0: CONSTCD11 ferencd@0: bool operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const month_weekday_last& mwdl); ferencd@0: ferencd@0: // class year_month_day ferencd@0: ferencd@0: class year_month_day ferencd@0: { ferencd@0: date::year y_; ferencd@0: date::month m_; ferencd@0: date::day d_; ferencd@0: ferencd@0: public: ferencd@0: year_month_day() = default; ferencd@0: CONSTCD11 year_month_day(const date::year& y, const date::month& m, ferencd@0: const date::day& d) NOEXCEPT; ferencd@0: CONSTCD14 year_month_day(const year_month_day_last& ymdl) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD14 year_month_day(sys_days dp) NOEXCEPT; ferencd@0: CONSTCD14 explicit year_month_day(local_days dp) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 year_month_day& operator+=(const months& m) NOEXCEPT; ferencd@0: template ferencd@0: CONSTCD14 year_month_day& operator-=(const months& m) NOEXCEPT; ferencd@0: CONSTCD14 year_month_day& operator+=(const years& y) NOEXCEPT; ferencd@0: CONSTCD14 year_month_day& operator-=(const years& y) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 date::year year() const NOEXCEPT; ferencd@0: CONSTCD11 date::month month() const NOEXCEPT; ferencd@0: CONSTCD11 date::day day() const NOEXCEPT; ferencd@0: ferencd@0: CONSTCD14 operator sys_days() const NOEXCEPT; ferencd@0: CONSTCD14 explicit operator local_days() const NOEXCEPT; ferencd@0: CONSTCD14 bool ok() const NOEXCEPT; ferencd@0: ferencd@0: private: ferencd@0: static CONSTCD14 year_month_day from_days(days dp) NOEXCEPT; ferencd@0: CONSTCD14 days to_days() const NOEXCEPT; ferencd@0: }; ferencd@0: ferencd@0: CONSTCD11 bool operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator< (const year_month_day& x, const year_month_day& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator> (const year_month_day& x, const year_month_day& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT; ferencd@0: CONSTCD11 bool operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 year_month_day operator+(const year_month_day& ymd, const months& dm) NOEXCEPT; ferencd@0: template ferencd@0: CONSTCD14 year_month_day operator+(const months& dm, const year_month_day& ymd) NOEXCEPT; ferencd@0: template ferencd@0: CONSTCD14 year_month_day operator-(const year_month_day& ymd, const months& dm) NOEXCEPT; ferencd@0: CONSTCD11 year_month_day operator+(const year_month_day& ymd, const years& dy) NOEXCEPT; ferencd@0: CONSTCD11 year_month_day operator+(const years& dy, const year_month_day& ymd) NOEXCEPT; ferencd@0: CONSTCD11 year_month_day operator-(const year_month_day& ymd, const years& dy) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const year_month_day& ymd); ferencd@0: ferencd@0: // year_month_day_last ferencd@0: ferencd@0: class year_month_day_last ferencd@0: { ferencd@0: date::year y_; ferencd@0: date::month_day_last mdl_; ferencd@0: ferencd@0: public: ferencd@0: CONSTCD11 year_month_day_last(const date::year& y, ferencd@0: const date::month_day_last& mdl) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 year_month_day_last& operator+=(const months& m) NOEXCEPT; ferencd@0: template ferencd@0: CONSTCD14 year_month_day_last& operator-=(const months& m) NOEXCEPT; ferencd@0: CONSTCD14 year_month_day_last& operator+=(const years& y) NOEXCEPT; ferencd@0: CONSTCD14 year_month_day_last& operator-=(const years& y) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 date::year year() const NOEXCEPT; ferencd@0: CONSTCD11 date::month month() const NOEXCEPT; ferencd@0: CONSTCD11 date::month_day_last month_day_last() const NOEXCEPT; ferencd@0: CONSTCD14 date::day day() const NOEXCEPT; ferencd@0: ferencd@0: CONSTCD14 operator sys_days() const NOEXCEPT; ferencd@0: CONSTCD14 explicit operator local_days() const NOEXCEPT; ferencd@0: CONSTCD11 bool ok() const NOEXCEPT; ferencd@0: }; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: bool operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; ferencd@0: CONSTCD11 ferencd@0: bool operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; ferencd@0: CONSTCD11 ferencd@0: bool operator< (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; ferencd@0: CONSTCD11 ferencd@0: bool operator> (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; ferencd@0: CONSTCD11 ferencd@0: bool operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; ferencd@0: CONSTCD11 ferencd@0: bool operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: year_month_day_last ferencd@0: operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: year_month_day_last ferencd@0: operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_day_last ferencd@0: operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_day_last ferencd@0: operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: year_month_day_last ferencd@0: operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_day_last ferencd@0: operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const year_month_day_last& ymdl); ferencd@0: ferencd@0: // year_month_weekday ferencd@0: ferencd@0: class year_month_weekday ferencd@0: { ferencd@0: date::year y_; ferencd@0: date::month m_; ferencd@0: date::weekday_indexed wdi_; ferencd@0: ferencd@0: public: ferencd@0: year_month_weekday() = default; ferencd@0: CONSTCD11 year_month_weekday(const date::year& y, const date::month& m, ferencd@0: const date::weekday_indexed& wdi) NOEXCEPT; ferencd@0: CONSTCD14 year_month_weekday(const sys_days& dp) NOEXCEPT; ferencd@0: CONSTCD14 explicit year_month_weekday(const local_days& dp) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 year_month_weekday& operator+=(const months& m) NOEXCEPT; ferencd@0: template ferencd@0: CONSTCD14 year_month_weekday& operator-=(const months& m) NOEXCEPT; ferencd@0: CONSTCD14 year_month_weekday& operator+=(const years& y) NOEXCEPT; ferencd@0: CONSTCD14 year_month_weekday& operator-=(const years& y) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 date::year year() const NOEXCEPT; ferencd@0: CONSTCD11 date::month month() const NOEXCEPT; ferencd@0: CONSTCD11 date::weekday weekday() const NOEXCEPT; ferencd@0: CONSTCD11 unsigned index() const NOEXCEPT; ferencd@0: CONSTCD11 date::weekday_indexed weekday_indexed() const NOEXCEPT; ferencd@0: ferencd@0: CONSTCD14 operator sys_days() const NOEXCEPT; ferencd@0: CONSTCD14 explicit operator local_days() const NOEXCEPT; ferencd@0: CONSTCD14 bool ok() const NOEXCEPT; ferencd@0: ferencd@0: private: ferencd@0: static CONSTCD14 year_month_weekday from_days(days dp) NOEXCEPT; ferencd@0: CONSTCD14 days to_days() const NOEXCEPT; ferencd@0: }; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: bool operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT; ferencd@0: CONSTCD11 ferencd@0: bool operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: year_month_weekday ferencd@0: operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: year_month_weekday ferencd@0: operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_weekday ferencd@0: operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_weekday ferencd@0: operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: year_month_weekday ferencd@0: operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_weekday ferencd@0: operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const year_month_weekday& ymwdi); ferencd@0: ferencd@0: // year_month_weekday_last ferencd@0: ferencd@0: class year_month_weekday_last ferencd@0: { ferencd@0: date::year y_; ferencd@0: date::month m_; ferencd@0: date::weekday_last wdl_; ferencd@0: ferencd@0: public: ferencd@0: CONSTCD11 year_month_weekday_last(const date::year& y, const date::month& m, ferencd@0: const date::weekday_last& wdl) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 year_month_weekday_last& operator+=(const months& m) NOEXCEPT; ferencd@0: template ferencd@0: CONSTCD14 year_month_weekday_last& operator-=(const months& m) NOEXCEPT; ferencd@0: CONSTCD14 year_month_weekday_last& operator+=(const years& y) NOEXCEPT; ferencd@0: CONSTCD14 year_month_weekday_last& operator-=(const years& y) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 date::year year() const NOEXCEPT; ferencd@0: CONSTCD11 date::month month() const NOEXCEPT; ferencd@0: CONSTCD11 date::weekday weekday() const NOEXCEPT; ferencd@0: CONSTCD11 date::weekday_last weekday_last() const NOEXCEPT; ferencd@0: ferencd@0: CONSTCD14 operator sys_days() const NOEXCEPT; ferencd@0: CONSTCD14 explicit operator local_days() const NOEXCEPT; ferencd@0: CONSTCD11 bool ok() const NOEXCEPT; ferencd@0: ferencd@0: private: ferencd@0: CONSTCD14 days to_days() const NOEXCEPT; ferencd@0: }; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: bool ferencd@0: operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: bool ferencd@0: operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: year_month_weekday_last ferencd@0: operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: year_month_weekday_last ferencd@0: operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_weekday_last ferencd@0: operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_weekday_last ferencd@0: operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: year_month_weekday_last ferencd@0: operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT; ferencd@0: ferencd@0: CONSTCD11 ferencd@0: year_month_weekday_last ferencd@0: operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const year_month_weekday_last& ymwdl); ferencd@0: ferencd@0: #if !defined(_MSC_VER) || (_MSC_VER >= 1900) ferencd@0: inline namespace literals ferencd@0: { ferencd@0: ferencd@0: CONSTCD11 date::day operator "" _d(unsigned long long d) NOEXCEPT; ferencd@0: CONSTCD11 date::year operator "" _y(unsigned long long y) NOEXCEPT; ferencd@0: ferencd@0: } // inline namespace literals ferencd@0: #endif // !defined(_MSC_VER) || (_MSC_VER >= 1900) ferencd@0: ferencd@0: // CONSTDATA date::month January{1}; ferencd@0: // CONSTDATA date::month February{2}; ferencd@0: // CONSTDATA date::month March{3}; ferencd@0: // CONSTDATA date::month April{4}; ferencd@0: // CONSTDATA date::month May{5}; ferencd@0: // CONSTDATA date::month June{6}; ferencd@0: // CONSTDATA date::month July{7}; ferencd@0: // CONSTDATA date::month August{8}; ferencd@0: // CONSTDATA date::month September{9}; ferencd@0: // CONSTDATA date::month October{10}; ferencd@0: // CONSTDATA date::month November{11}; ferencd@0: // CONSTDATA date::month December{12}; ferencd@0: // ferencd@0: // CONSTDATA date::weekday Sunday{0u}; ferencd@0: // CONSTDATA date::weekday Monday{1u}; ferencd@0: // CONSTDATA date::weekday Tuesday{2u}; ferencd@0: // CONSTDATA date::weekday Wednesday{3u}; ferencd@0: // CONSTDATA date::weekday Thursday{4u}; ferencd@0: // CONSTDATA date::weekday Friday{5u}; ferencd@0: // CONSTDATA date::weekday Saturday{6u}; ferencd@0: ferencd@0: #if HAS_VOID_T ferencd@0: ferencd@0: template > ferencd@0: struct is_clock ferencd@0: : std::false_type ferencd@0: {}; ferencd@0: ferencd@0: template ferencd@0: struct is_clock> ferencd@0: : std::true_type ferencd@0: {}; ferencd@0: ferencd@0: #endif // HAS_VOID_T ferencd@0: ferencd@0: //----------------+ ferencd@0: // Implementation | ferencd@0: //----------------+ ferencd@0: ferencd@0: // utilities ferencd@0: namespace detail { ferencd@0: ferencd@0: template> ferencd@0: class save_istream ferencd@0: { ferencd@0: protected: ferencd@0: std::basic_ios& is_; ferencd@0: CharT fill_; ferencd@0: std::ios::fmtflags flags_; ferencd@0: std::streamsize width_; ferencd@0: std::basic_ostream* tie_; ferencd@0: std::locale loc_; ferencd@0: ferencd@0: public: ferencd@0: ~save_istream() ferencd@0: { ferencd@0: is_.fill(fill_); ferencd@0: is_.flags(flags_); ferencd@0: is_.width(width_); ferencd@0: is_.imbue(loc_); ferencd@0: is_.tie(tie_); ferencd@0: } ferencd@0: ferencd@0: save_istream(const save_istream&) = delete; ferencd@0: save_istream& operator=(const save_istream&) = delete; ferencd@0: ferencd@0: explicit save_istream(std::basic_ios& is) ferencd@0: : is_(is) ferencd@0: , fill_(is.fill()) ferencd@0: , flags_(is.flags()) ferencd@0: , width_(is.width(0)) ferencd@0: , tie_(is.tie(nullptr)) ferencd@0: , loc_(is.getloc()) ferencd@0: { ferencd@0: if (tie_ != nullptr) ferencd@0: tie_->flush(); ferencd@0: } ferencd@0: }; ferencd@0: ferencd@0: template> ferencd@0: class save_ostream ferencd@0: : private save_istream ferencd@0: { ferencd@0: public: ferencd@0: ~save_ostream() ferencd@0: { ferencd@0: if ((this->flags_ & std::ios::unitbuf) && ferencd@0: #if HAS_UNCAUGHT_EXCEPTIONS ferencd@0: std::uncaught_exceptions() == 0 && ferencd@0: #else ferencd@0: !std::uncaught_exception() && ferencd@0: #endif ferencd@0: this->is_.good()) ferencd@0: this->is_.rdbuf()->pubsync(); ferencd@0: } ferencd@0: ferencd@0: save_ostream(const save_ostream&) = delete; ferencd@0: save_ostream& operator=(const save_ostream&) = delete; ferencd@0: ferencd@0: explicit save_ostream(std::basic_ios& os) ferencd@0: : save_istream(os) ferencd@0: { ferencd@0: } ferencd@0: }; ferencd@0: ferencd@0: template ferencd@0: struct choose_trunc_type ferencd@0: { ferencd@0: static const int digits = std::numeric_limits::digits; ferencd@0: using type = typename std::conditional ferencd@0: < ferencd@0: digits < 32, ferencd@0: std::int32_t, ferencd@0: typename std::conditional ferencd@0: < ferencd@0: digits < 64, ferencd@0: std::int64_t, ferencd@0: #ifdef __SIZEOF_INT128__ ferencd@0: __int128 ferencd@0: #else ferencd@0: std::int64_t ferencd@0: #endif ferencd@0: >::type ferencd@0: >::type; ferencd@0: }; ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: typename std::enable_if ferencd@0: < ferencd@0: !std::chrono::treat_as_floating_point::value, ferencd@0: T ferencd@0: >::type ferencd@0: trunc(T t) NOEXCEPT ferencd@0: { ferencd@0: return t; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: typename std::enable_if ferencd@0: < ferencd@0: std::chrono::treat_as_floating_point::value, ferencd@0: T ferencd@0: >::type ferencd@0: trunc(T t) NOEXCEPT ferencd@0: { ferencd@0: using std::numeric_limits; ferencd@0: using I = typename choose_trunc_type::type; ferencd@0: CONSTDATA auto digits = numeric_limits::digits; ferencd@0: static_assert(digits < numeric_limits::digits, ""); ferencd@0: CONSTDATA auto max = I{1} << (digits-1); ferencd@0: CONSTDATA auto min = -max; ferencd@0: const auto negative = t < T{0}; ferencd@0: if (min <= t && t <= max && t != 0 && t == t) ferencd@0: { ferencd@0: t = static_cast(static_cast(t)); ferencd@0: if (t == 0 && negative) ferencd@0: t = -t; ferencd@0: } ferencd@0: return t; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: struct static_gcd ferencd@0: { ferencd@0: static const std::intmax_t value = static_gcd::value; ferencd@0: }; ferencd@0: ferencd@0: template ferencd@0: struct static_gcd ferencd@0: { ferencd@0: static const std::intmax_t value = Xp; ferencd@0: }; ferencd@0: ferencd@0: template <> ferencd@0: struct static_gcd<0, 0> ferencd@0: { ferencd@0: static const std::intmax_t value = 1; ferencd@0: }; ferencd@0: ferencd@0: template ferencd@0: struct no_overflow ferencd@0: { ferencd@0: private: ferencd@0: static const std::intmax_t gcd_n1_n2 = static_gcd::value; ferencd@0: static const std::intmax_t gcd_d1_d2 = static_gcd::value; ferencd@0: static const std::intmax_t n1 = R1::num / gcd_n1_n2; ferencd@0: static const std::intmax_t d1 = R1::den / gcd_d1_d2; ferencd@0: static const std::intmax_t n2 = R2::num / gcd_n1_n2; ferencd@0: static const std::intmax_t d2 = R2::den / gcd_d1_d2; ferencd@0: static const std::intmax_t max = INTMAX_MAX; ferencd@0: ferencd@0: template ferencd@0: struct mul // overflow == false ferencd@0: { ferencd@0: static const std::intmax_t value = Xp * Yp; ferencd@0: }; ferencd@0: ferencd@0: template ferencd@0: struct mul ferencd@0: { ferencd@0: static const std::intmax_t value = 1; ferencd@0: }; ferencd@0: ferencd@0: public: ferencd@0: static const bool value = (n1 <= max / d2) && (n2 <= max / d1); ferencd@0: typedef std::ratio::value, ferencd@0: mul::value> type; ferencd@0: }; ferencd@0: ferencd@0: } // detail ferencd@0: ferencd@0: // trunc towards zero ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: typename std::enable_if ferencd@0: < ferencd@0: detail::no_overflow::value, ferencd@0: To ferencd@0: >::type ferencd@0: trunc(const std::chrono::duration& d) ferencd@0: { ferencd@0: return To{detail::trunc(std::chrono::duration_cast(d).count())}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: typename std::enable_if ferencd@0: < ferencd@0: !detail::no_overflow::value, ferencd@0: To ferencd@0: >::type ferencd@0: trunc(const std::chrono::duration& d) ferencd@0: { ferencd@0: using std::chrono::duration_cast; ferencd@0: using std::chrono::duration; ferencd@0: using rep = typename std::common_type::type; ferencd@0: return To{detail::trunc(duration_cast(duration_cast>(d)).count())}; ferencd@0: } ferencd@0: ferencd@0: #ifndef HAS_CHRONO_ROUNDING ferencd@0: # if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023918 || (_MSC_FULL_VER >= 190000000 && defined (__clang__))) ferencd@0: # define HAS_CHRONO_ROUNDING 1 ferencd@0: # elif defined(__cpp_lib_chrono) && __cplusplus > 201402 && __cpp_lib_chrono >= 201510 ferencd@0: # define HAS_CHRONO_ROUNDING 1 ferencd@0: # elif defined(_LIBCPP_VERSION) && __cplusplus > 201402 && _LIBCPP_VERSION >= 3800 ferencd@0: # define HAS_CHRONO_ROUNDING 1 ferencd@0: # else ferencd@0: # define HAS_CHRONO_ROUNDING 0 ferencd@0: # endif ferencd@0: #endif // HAS_CHRONO_ROUNDING ferencd@0: ferencd@0: #if HAS_CHRONO_ROUNDING == 0 ferencd@0: ferencd@0: // round down ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: typename std::enable_if ferencd@0: < ferencd@0: detail::no_overflow::value, ferencd@0: To ferencd@0: >::type ferencd@0: floor(const std::chrono::duration& d) ferencd@0: { ferencd@0: auto t = trunc(d); ferencd@0: if (t > d) ferencd@0: return t - To{1}; ferencd@0: return t; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: typename std::enable_if ferencd@0: < ferencd@0: !detail::no_overflow::value, ferencd@0: To ferencd@0: >::type ferencd@0: floor(const std::chrono::duration& d) ferencd@0: { ferencd@0: using rep = typename std::common_type::type; ferencd@0: return floor(floor>(d)); ferencd@0: } ferencd@0: ferencd@0: // round to nearest, to even on tie ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: To ferencd@0: round(const std::chrono::duration& d) ferencd@0: { ferencd@0: auto t0 = floor(d); ferencd@0: auto t1 = t0 + To{1}; ferencd@0: if (t1 == To{0} && t0 < To{0}) ferencd@0: t1 = -t1; ferencd@0: auto diff0 = d - t0; ferencd@0: auto diff1 = t1 - d; ferencd@0: if (diff0 == diff1) ferencd@0: { ferencd@0: if (t0 - trunc(t0/2)*2 == To{0}) ferencd@0: return t0; ferencd@0: return t1; ferencd@0: } ferencd@0: if (diff0 < diff1) ferencd@0: return t0; ferencd@0: return t1; ferencd@0: } ferencd@0: ferencd@0: // round up ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: To ferencd@0: ceil(const std::chrono::duration& d) ferencd@0: { ferencd@0: auto t = trunc(d); ferencd@0: if (t < d) ferencd@0: return t + To{1}; ferencd@0: return t; ferencd@0: } ferencd@0: ferencd@0: template ::is_signed ferencd@0: >::type> ferencd@0: CONSTCD11 ferencd@0: std::chrono::duration ferencd@0: abs(std::chrono::duration d) ferencd@0: { ferencd@0: return d >= d.zero() ? d : -d; ferencd@0: } ferencd@0: ferencd@0: // round down ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: std::chrono::time_point ferencd@0: floor(const std::chrono::time_point& tp) ferencd@0: { ferencd@0: using std::chrono::time_point; ferencd@0: return time_point{date::floor(tp.time_since_epoch())}; ferencd@0: } ferencd@0: ferencd@0: // round to nearest, to even on tie ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: std::chrono::time_point ferencd@0: round(const std::chrono::time_point& tp) ferencd@0: { ferencd@0: using std::chrono::time_point; ferencd@0: return time_point{round(tp.time_since_epoch())}; ferencd@0: } ferencd@0: ferencd@0: // round up ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: std::chrono::time_point ferencd@0: ceil(const std::chrono::time_point& tp) ferencd@0: { ferencd@0: using std::chrono::time_point; ferencd@0: return time_point{ceil(tp.time_since_epoch())}; ferencd@0: } ferencd@0: ferencd@0: #else // HAS_CHRONO_ROUNDING == 1 ferencd@0: ferencd@0: using std::chrono::floor; ferencd@0: using std::chrono::ceil; ferencd@0: using std::chrono::round; ferencd@0: using std::chrono::abs; ferencd@0: ferencd@0: #endif // HAS_CHRONO_ROUNDING ferencd@0: ferencd@0: // trunc towards zero ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: std::chrono::time_point ferencd@0: trunc(const std::chrono::time_point& tp) ferencd@0: { ferencd@0: using std::chrono::time_point; ferencd@0: return time_point{trunc(tp.time_since_epoch())}; ferencd@0: } ferencd@0: ferencd@0: // day ferencd@0: ferencd@0: CONSTCD11 inline day::day(unsigned d) NOEXCEPT : d_(static_cast(d)) {} ferencd@0: CONSTCD14 inline day& day::operator++() NOEXCEPT {++d_; return *this;} ferencd@0: CONSTCD14 inline day day::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} ferencd@0: CONSTCD14 inline day& day::operator--() NOEXCEPT {--d_; return *this;} ferencd@0: CONSTCD14 inline day day::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} ferencd@0: CONSTCD14 inline day& day::operator+=(const days& d) NOEXCEPT {*this = *this + d; return *this;} ferencd@0: CONSTCD14 inline day& day::operator-=(const days& d) NOEXCEPT {*this = *this - d; return *this;} ferencd@0: CONSTCD11 inline day::operator unsigned() const NOEXCEPT {return d_;} ferencd@0: CONSTCD11 inline bool day::ok() const NOEXCEPT {return 1 <= d_ && d_ <= 31;} ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator==(const day& x, const day& y) NOEXCEPT ferencd@0: { ferencd@0: return static_cast(x) == static_cast(y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator!=(const day& x, const day& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x == y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator<(const day& x, const day& y) NOEXCEPT ferencd@0: { ferencd@0: return static_cast(x) < static_cast(y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator>(const day& x, const day& y) NOEXCEPT ferencd@0: { ferencd@0: return y < x; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator<=(const day& x, const day& y) NOEXCEPT ferencd@0: { ferencd@0: return !(y < x); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator>=(const day& x, const day& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x < y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: days ferencd@0: operator-(const day& x, const day& y) NOEXCEPT ferencd@0: { ferencd@0: return days{static_cast(static_cast(x) ferencd@0: - static_cast(y))}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: day ferencd@0: operator+(const day& x, const days& y) NOEXCEPT ferencd@0: { ferencd@0: return day{static_cast(x) + static_cast(y.count())}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: day ferencd@0: operator+(const days& x, const day& y) NOEXCEPT ferencd@0: { ferencd@0: return y + x; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: day ferencd@0: operator-(const day& x, const days& y) NOEXCEPT ferencd@0: { ferencd@0: return x + -y; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const day& d) ferencd@0: { ferencd@0: detail::save_ostream _(os); ferencd@0: os.fill('0'); ferencd@0: os.flags(std::ios::dec | std::ios::right); ferencd@0: os.width(2); ferencd@0: os << static_cast(d); ferencd@0: if (!d.ok()) ferencd@0: os << " is not a valid day"; ferencd@0: return os; ferencd@0: } ferencd@0: ferencd@0: // month ferencd@0: ferencd@0: CONSTCD11 inline month::month(unsigned m) NOEXCEPT : m_(static_cast(m)) {} ferencd@0: CONSTCD14 inline month& month::operator++() NOEXCEPT {*this += months{1}; return *this;} ferencd@0: CONSTCD14 inline month month::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} ferencd@0: CONSTCD14 inline month& month::operator--() NOEXCEPT {*this -= months{1}; return *this;} ferencd@0: CONSTCD14 inline month month::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: month& ferencd@0: month::operator+=(const months& m) NOEXCEPT ferencd@0: { ferencd@0: *this = *this + m; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: month& ferencd@0: month::operator-=(const months& m) NOEXCEPT ferencd@0: { ferencd@0: *this = *this - m; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 inline month::operator unsigned() const NOEXCEPT {return m_;} ferencd@0: CONSTCD11 inline bool month::ok() const NOEXCEPT {return 1 <= m_ && m_ <= 12;} ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator==(const month& x, const month& y) NOEXCEPT ferencd@0: { ferencd@0: return static_cast(x) == static_cast(y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator!=(const month& x, const month& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x == y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator<(const month& x, const month& y) NOEXCEPT ferencd@0: { ferencd@0: return static_cast(x) < static_cast(y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator>(const month& x, const month& y) NOEXCEPT ferencd@0: { ferencd@0: return y < x; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator<=(const month& x, const month& y) NOEXCEPT ferencd@0: { ferencd@0: return !(y < x); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator>=(const month& x, const month& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x < y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: months ferencd@0: operator-(const month& x, const month& y) NOEXCEPT ferencd@0: { ferencd@0: auto const d = static_cast(x) - static_cast(y); ferencd@0: return months(d <= 11 ? d : d + 12); ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: month ferencd@0: operator+(const month& x, const months& y) NOEXCEPT ferencd@0: { ferencd@0: auto const mu = static_cast(static_cast(x)) + (y.count() - 1); ferencd@0: auto const yr = (mu >= 0 ? mu : mu-11) / 12; ferencd@0: return month{static_cast(mu - yr * 12 + 1)}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: month ferencd@0: operator+(const months& x, const month& y) NOEXCEPT ferencd@0: { ferencd@0: return y + x; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: month ferencd@0: operator-(const month& x, const months& y) NOEXCEPT ferencd@0: { ferencd@0: return x + -y; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const month& m) ferencd@0: { ferencd@0: if (m.ok()) ferencd@0: { ferencd@0: CharT fmt[] = {'%', 'b', 0}; ferencd@0: os << format(os.getloc(), fmt, m); ferencd@0: } ferencd@0: else ferencd@0: os << static_cast(m) << " is not a valid month"; ferencd@0: return os; ferencd@0: } ferencd@0: ferencd@0: // year ferencd@0: ferencd@0: CONSTCD11 inline year::year(int y) NOEXCEPT : y_(static_cast(y)) {} ferencd@0: CONSTCD14 inline year& year::operator++() NOEXCEPT {++y_; return *this;} ferencd@0: CONSTCD14 inline year year::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} ferencd@0: CONSTCD14 inline year& year::operator--() NOEXCEPT {--y_; return *this;} ferencd@0: CONSTCD14 inline year year::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} ferencd@0: CONSTCD14 inline year& year::operator+=(const years& y) NOEXCEPT {*this = *this + y; return *this;} ferencd@0: CONSTCD14 inline year& year::operator-=(const years& y) NOEXCEPT {*this = *this - y; return *this;} ferencd@0: CONSTCD11 inline year year::operator-() const NOEXCEPT {return year{-y_};} ferencd@0: CONSTCD11 inline year year::operator+() const NOEXCEPT {return *this;} ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: year::is_leap() const NOEXCEPT ferencd@0: { ferencd@0: return y_ % 4 == 0 && (y_ % 100 != 0 || y_ % 400 == 0); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 inline year::operator int() const NOEXCEPT {return y_;} ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: year::ok() const NOEXCEPT ferencd@0: { ferencd@0: return y_ != std::numeric_limits::min(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator==(const year& x, const year& y) NOEXCEPT ferencd@0: { ferencd@0: return static_cast(x) == static_cast(y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator!=(const year& x, const year& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x == y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator<(const year& x, const year& y) NOEXCEPT ferencd@0: { ferencd@0: return static_cast(x) < static_cast(y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator>(const year& x, const year& y) NOEXCEPT ferencd@0: { ferencd@0: return y < x; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator<=(const year& x, const year& y) NOEXCEPT ferencd@0: { ferencd@0: return !(y < x); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator>=(const year& x, const year& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x < y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: years ferencd@0: operator-(const year& x, const year& y) NOEXCEPT ferencd@0: { ferencd@0: return years{static_cast(x) - static_cast(y)}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year ferencd@0: operator+(const year& x, const years& y) NOEXCEPT ferencd@0: { ferencd@0: return year{static_cast(x) + y.count()}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year ferencd@0: operator+(const years& x, const year& y) NOEXCEPT ferencd@0: { ferencd@0: return y + x; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year ferencd@0: operator-(const year& x, const years& y) NOEXCEPT ferencd@0: { ferencd@0: return year{static_cast(x) - y.count()}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const year& y) ferencd@0: { ferencd@0: detail::save_ostream _(os); ferencd@0: os.fill('0'); ferencd@0: os.flags(std::ios::dec | std::ios::internal); ferencd@0: os.width(4 + (y < year{0})); ferencd@0: os.imbue(std::locale::classic()); ferencd@0: os << static_cast(y); ferencd@0: if (!y.ok()) ferencd@0: os << " is not a valid year"; ferencd@0: return os; ferencd@0: } ferencd@0: ferencd@0: // weekday ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: unsigned char ferencd@0: weekday::weekday_from_days(int z) NOEXCEPT ferencd@0: { ferencd@0: auto u = static_cast(z); ferencd@0: return static_cast(z >= -4 ? (u+4) % 7 : u % 7); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: weekday::weekday(unsigned wd) NOEXCEPT ferencd@0: : wd_(static_cast(wd != 7 ? wd : 0)) ferencd@0: {} ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: weekday::weekday(const sys_days& dp) NOEXCEPT ferencd@0: : wd_(weekday_from_days(dp.time_since_epoch().count())) ferencd@0: {} ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: weekday::weekday(const local_days& dp) NOEXCEPT ferencd@0: : wd_(weekday_from_days(dp.time_since_epoch().count())) ferencd@0: {} ferencd@0: ferencd@0: CONSTCD14 inline weekday& weekday::operator++() NOEXCEPT {*this += days{1}; return *this;} ferencd@0: CONSTCD14 inline weekday weekday::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;} ferencd@0: CONSTCD14 inline weekday& weekday::operator--() NOEXCEPT {*this -= days{1}; return *this;} ferencd@0: CONSTCD14 inline weekday weekday::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;} ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: weekday& ferencd@0: weekday::operator+=(const days& d) NOEXCEPT ferencd@0: { ferencd@0: *this = *this + d; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: weekday& ferencd@0: weekday::operator-=(const days& d) NOEXCEPT ferencd@0: { ferencd@0: *this = *this - d; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 inline bool weekday::ok() const NOEXCEPT {return wd_ <= 6;} ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: unsigned weekday::c_encoding() const NOEXCEPT ferencd@0: { ferencd@0: return unsigned{wd_}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: unsigned weekday::iso_encoding() const NOEXCEPT ferencd@0: { ferencd@0: return unsigned{((wd_ == 0u) ? 7u : wd_)}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator==(const weekday& x, const weekday& y) NOEXCEPT ferencd@0: { ferencd@0: return x.wd_ == y.wd_; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator!=(const weekday& x, const weekday& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x == y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: days ferencd@0: operator-(const weekday& x, const weekday& y) NOEXCEPT ferencd@0: { ferencd@0: auto const wdu = x.wd_ - y.wd_; ferencd@0: auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7; ferencd@0: return days{wdu - wk * 7}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: weekday ferencd@0: operator+(const weekday& x, const days& y) NOEXCEPT ferencd@0: { ferencd@0: auto const wdu = static_cast(static_cast(x.wd_)) + y.count(); ferencd@0: auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7; ferencd@0: return weekday{static_cast(wdu - wk * 7)}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: weekday ferencd@0: operator+(const days& x, const weekday& y) NOEXCEPT ferencd@0: { ferencd@0: return y + x; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: weekday ferencd@0: operator-(const weekday& x, const days& y) NOEXCEPT ferencd@0: { ferencd@0: return x + -y; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const weekday& wd) ferencd@0: { ferencd@0: if (wd.ok()) ferencd@0: { ferencd@0: CharT fmt[] = {'%', 'a', 0}; ferencd@0: os << format(fmt, wd); ferencd@0: } ferencd@0: else ferencd@0: os << static_cast(wd.wd_) << " is not a valid weekday"; ferencd@0: return os; ferencd@0: } ferencd@0: ferencd@0: #if !defined(_MSC_VER) || (_MSC_VER >= 1900) ferencd@0: inline namespace literals ferencd@0: { ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: date::day ferencd@0: operator "" _d(unsigned long long d) NOEXCEPT ferencd@0: { ferencd@0: return date::day{static_cast(d)}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: date::year ferencd@0: operator "" _y(unsigned long long y) NOEXCEPT ferencd@0: { ferencd@0: return date::year(static_cast(y)); ferencd@0: } ferencd@0: #endif // !defined(_MSC_VER) || (_MSC_VER >= 1900) ferencd@0: ferencd@0: CONSTDATA date::last_spec last{}; ferencd@0: ferencd@0: CONSTDATA date::month jan{1}; ferencd@0: CONSTDATA date::month feb{2}; ferencd@0: CONSTDATA date::month mar{3}; ferencd@0: CONSTDATA date::month apr{4}; ferencd@0: CONSTDATA date::month may{5}; ferencd@0: CONSTDATA date::month jun{6}; ferencd@0: CONSTDATA date::month jul{7}; ferencd@0: CONSTDATA date::month aug{8}; ferencd@0: CONSTDATA date::month sep{9}; ferencd@0: CONSTDATA date::month oct{10}; ferencd@0: CONSTDATA date::month nov{11}; ferencd@0: CONSTDATA date::month dec{12}; ferencd@0: ferencd@0: CONSTDATA date::weekday sun{0u}; ferencd@0: CONSTDATA date::weekday mon{1u}; ferencd@0: CONSTDATA date::weekday tue{2u}; ferencd@0: CONSTDATA date::weekday wed{3u}; ferencd@0: CONSTDATA date::weekday thu{4u}; ferencd@0: CONSTDATA date::weekday fri{5u}; ferencd@0: CONSTDATA date::weekday sat{6u}; ferencd@0: ferencd@0: #if !defined(_MSC_VER) || (_MSC_VER >= 1900) ferencd@0: } // inline namespace literals ferencd@0: #endif ferencd@0: ferencd@0: CONSTDATA date::month January{1}; ferencd@0: CONSTDATA date::month February{2}; ferencd@0: CONSTDATA date::month March{3}; ferencd@0: CONSTDATA date::month April{4}; ferencd@0: CONSTDATA date::month May{5}; ferencd@0: CONSTDATA date::month June{6}; ferencd@0: CONSTDATA date::month July{7}; ferencd@0: CONSTDATA date::month August{8}; ferencd@0: CONSTDATA date::month September{9}; ferencd@0: CONSTDATA date::month October{10}; ferencd@0: CONSTDATA date::month November{11}; ferencd@0: CONSTDATA date::month December{12}; ferencd@0: ferencd@0: CONSTDATA date::weekday Monday{1}; ferencd@0: CONSTDATA date::weekday Tuesday{2}; ferencd@0: CONSTDATA date::weekday Wednesday{3}; ferencd@0: CONSTDATA date::weekday Thursday{4}; ferencd@0: CONSTDATA date::weekday Friday{5}; ferencd@0: CONSTDATA date::weekday Saturday{6}; ferencd@0: CONSTDATA date::weekday Sunday{7}; ferencd@0: ferencd@0: // weekday_indexed ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: weekday ferencd@0: weekday_indexed::weekday() const NOEXCEPT ferencd@0: { ferencd@0: return date::weekday{static_cast(wd_)}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 inline unsigned weekday_indexed::index() const NOEXCEPT {return index_;} ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: weekday_indexed::ok() const NOEXCEPT ferencd@0: { ferencd@0: return weekday().ok() && 1 <= index_ && index_ <= 5; ferencd@0: } ferencd@0: ferencd@0: #ifdef __GNUC__ ferencd@0: # pragma GCC diagnostic push ferencd@0: # pragma GCC diagnostic ignored "-Wconversion" ferencd@0: #endif // __GNUC__ ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: weekday_indexed::weekday_indexed(const date::weekday& wd, unsigned index) NOEXCEPT ferencd@0: : wd_(static_cast(static_cast(wd.wd_))) ferencd@0: , index_(static_cast(index)) ferencd@0: {} ferencd@0: ferencd@0: #ifdef __GNUC__ ferencd@0: # pragma GCC diagnostic pop ferencd@0: #endif // __GNUC__ ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const weekday_indexed& wdi) ferencd@0: { ferencd@0: os << wdi.weekday() << '[' << wdi.index(); ferencd@0: if (!(1 <= wdi.index() && wdi.index() <= 5)) ferencd@0: os << " is not a valid index"; ferencd@0: os << ']'; ferencd@0: return os; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: weekday_indexed ferencd@0: weekday::operator[](unsigned index) const NOEXCEPT ferencd@0: { ferencd@0: return {*this, index}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT ferencd@0: { ferencd@0: return x.weekday() == y.weekday() && x.index() == y.index(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x == y); ferencd@0: } ferencd@0: ferencd@0: // weekday_last ferencd@0: ferencd@0: CONSTCD11 inline date::weekday weekday_last::weekday() const NOEXCEPT {return wd_;} ferencd@0: CONSTCD11 inline bool weekday_last::ok() const NOEXCEPT {return wd_.ok();} ferencd@0: CONSTCD11 inline weekday_last::weekday_last(const date::weekday& wd) NOEXCEPT : wd_(wd) {} ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT ferencd@0: { ferencd@0: return x.weekday() == y.weekday(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x == y); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const weekday_last& wdl) ferencd@0: { ferencd@0: return os << wdl.weekday() << "[last]"; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: weekday_last ferencd@0: weekday::operator[](last_spec) const NOEXCEPT ferencd@0: { ferencd@0: return weekday_last{*this}; ferencd@0: } ferencd@0: ferencd@0: // year_month ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month::year_month(const date::year& y, const date::month& m) NOEXCEPT ferencd@0: : y_(y) ferencd@0: , m_(m) ferencd@0: {} ferencd@0: ferencd@0: CONSTCD11 inline year year_month::year() const NOEXCEPT {return y_;} ferencd@0: CONSTCD11 inline month year_month::month() const NOEXCEPT {return m_;} ferencd@0: CONSTCD11 inline bool year_month::ok() const NOEXCEPT {return y_.ok() && m_.ok();} ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month& ferencd@0: year_month::operator+=(const months& dm) NOEXCEPT ferencd@0: { ferencd@0: *this = *this + dm; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month& ferencd@0: year_month::operator-=(const months& dm) NOEXCEPT ferencd@0: { ferencd@0: *this = *this - dm; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month& ferencd@0: year_month::operator+=(const years& dy) NOEXCEPT ferencd@0: { ferencd@0: *this = *this + dy; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month& ferencd@0: year_month::operator-=(const years& dy) NOEXCEPT ferencd@0: { ferencd@0: *this = *this - dy; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator==(const year_month& x, const year_month& y) NOEXCEPT ferencd@0: { ferencd@0: return x.year() == y.year() && x.month() == y.month(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator!=(const year_month& x, const year_month& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x == y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator<(const year_month& x, const year_month& y) NOEXCEPT ferencd@0: { ferencd@0: return x.year() < y.year() ? true ferencd@0: : (x.year() > y.year() ? false ferencd@0: : (x.month() < y.month())); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator>(const year_month& x, const year_month& y) NOEXCEPT ferencd@0: { ferencd@0: return y < x; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator<=(const year_month& x, const year_month& y) NOEXCEPT ferencd@0: { ferencd@0: return !(y < x); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator>=(const year_month& x, const year_month& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x < y); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month ferencd@0: operator+(const year_month& ym, const months& dm) NOEXCEPT ferencd@0: { ferencd@0: auto dmi = static_cast(static_cast(ym.month())) - 1 + dm.count(); ferencd@0: auto dy = (dmi >= 0 ? dmi : dmi-11) / 12; ferencd@0: dmi = dmi - dy * 12 + 1; ferencd@0: return (ym.year() + years(dy)) / month(static_cast(dmi)); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month ferencd@0: operator+(const months& dm, const year_month& ym) NOEXCEPT ferencd@0: { ferencd@0: return ym + dm; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month ferencd@0: operator-(const year_month& ym, const months& dm) NOEXCEPT ferencd@0: { ferencd@0: return ym + -dm; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: months ferencd@0: operator-(const year_month& x, const year_month& y) NOEXCEPT ferencd@0: { ferencd@0: return (x.year() - y.year()) + ferencd@0: months(static_cast(x.month()) - static_cast(y.month())); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month ferencd@0: operator+(const year_month& ym, const years& dy) NOEXCEPT ferencd@0: { ferencd@0: return (ym.year() + dy) / ym.month(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month ferencd@0: operator+(const years& dy, const year_month& ym) NOEXCEPT ferencd@0: { ferencd@0: return ym + dy; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month ferencd@0: operator-(const year_month& ym, const years& dy) NOEXCEPT ferencd@0: { ferencd@0: return ym + -dy; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const year_month& ym) ferencd@0: { ferencd@0: return os << ym.year() << '/' << ym.month(); ferencd@0: } ferencd@0: ferencd@0: // month_day ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_day::month_day(const date::month& m, const date::day& d) NOEXCEPT ferencd@0: : m_(m) ferencd@0: , d_(d) ferencd@0: {} ferencd@0: ferencd@0: CONSTCD11 inline date::month month_day::month() const NOEXCEPT {return m_;} ferencd@0: CONSTCD11 inline date::day month_day::day() const NOEXCEPT {return d_;} ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: bool ferencd@0: month_day::ok() const NOEXCEPT ferencd@0: { ferencd@0: CONSTDATA date::day d[] = ferencd@0: { ferencd@0: date::day(31), date::day(29), date::day(31), ferencd@0: date::day(30), date::day(31), date::day(30), ferencd@0: date::day(31), date::day(31), date::day(30), ferencd@0: date::day(31), date::day(30), date::day(31) ferencd@0: }; ferencd@0: return m_.ok() && date::day{1} <= d_ && d_ <= d[static_cast(m_)-1]; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator==(const month_day& x, const month_day& y) NOEXCEPT ferencd@0: { ferencd@0: return x.month() == y.month() && x.day() == y.day(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator!=(const month_day& x, const month_day& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x == y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator<(const month_day& x, const month_day& y) NOEXCEPT ferencd@0: { ferencd@0: return x.month() < y.month() ? true ferencd@0: : (x.month() > y.month() ? false ferencd@0: : (x.day() < y.day())); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator>(const month_day& x, const month_day& y) NOEXCEPT ferencd@0: { ferencd@0: return y < x; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator<=(const month_day& x, const month_day& y) NOEXCEPT ferencd@0: { ferencd@0: return !(y < x); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator>=(const month_day& x, const month_day& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x < y); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const month_day& md) ferencd@0: { ferencd@0: return os << md.month() << '/' << md.day(); ferencd@0: } ferencd@0: ferencd@0: // month_day_last ferencd@0: ferencd@0: CONSTCD11 inline month month_day_last::month() const NOEXCEPT {return m_;} ferencd@0: CONSTCD11 inline bool month_day_last::ok() const NOEXCEPT {return m_.ok();} ferencd@0: CONSTCD11 inline month_day_last::month_day_last(const date::month& m) NOEXCEPT : m_(m) {} ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT ferencd@0: { ferencd@0: return x.month() == y.month(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x == y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator<(const month_day_last& x, const month_day_last& y) NOEXCEPT ferencd@0: { ferencd@0: return x.month() < y.month(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator>(const month_day_last& x, const month_day_last& y) NOEXCEPT ferencd@0: { ferencd@0: return y < x; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT ferencd@0: { ferencd@0: return !(y < x); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x < y); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const month_day_last& mdl) ferencd@0: { ferencd@0: return os << mdl.month() << "/last"; ferencd@0: } ferencd@0: ferencd@0: // month_weekday ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_weekday::month_weekday(const date::month& m, ferencd@0: const date::weekday_indexed& wdi) NOEXCEPT ferencd@0: : m_(m) ferencd@0: , wdi_(wdi) ferencd@0: {} ferencd@0: ferencd@0: CONSTCD11 inline month month_weekday::month() const NOEXCEPT {return m_;} ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: weekday_indexed ferencd@0: month_weekday::weekday_indexed() const NOEXCEPT ferencd@0: { ferencd@0: return wdi_; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: month_weekday::ok() const NOEXCEPT ferencd@0: { ferencd@0: return m_.ok() && wdi_.ok(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT ferencd@0: { ferencd@0: return x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x == y); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const month_weekday& mwd) ferencd@0: { ferencd@0: return os << mwd.month() << '/' << mwd.weekday_indexed(); ferencd@0: } ferencd@0: ferencd@0: // month_weekday_last ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_weekday_last::month_weekday_last(const date::month& m, ferencd@0: const date::weekday_last& wdl) NOEXCEPT ferencd@0: : m_(m) ferencd@0: , wdl_(wdl) ferencd@0: {} ferencd@0: ferencd@0: CONSTCD11 inline month month_weekday_last::month() const NOEXCEPT {return m_;} ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: weekday_last ferencd@0: month_weekday_last::weekday_last() const NOEXCEPT ferencd@0: { ferencd@0: return wdl_; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: month_weekday_last::ok() const NOEXCEPT ferencd@0: { ferencd@0: return m_.ok() && wdl_.ok(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT ferencd@0: { ferencd@0: return x.month() == y.month() && x.weekday_last() == y.weekday_last(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x == y); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const month_weekday_last& mwdl) ferencd@0: { ferencd@0: return os << mwdl.month() << '/' << mwdl.weekday_last(); ferencd@0: } ferencd@0: ferencd@0: // year_month_day_last ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day_last::year_month_day_last(const date::year& y, ferencd@0: const date::month_day_last& mdl) NOEXCEPT ferencd@0: : y_(y) ferencd@0: , mdl_(mdl) ferencd@0: {} ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day_last& ferencd@0: year_month_day_last::operator+=(const months& m) NOEXCEPT ferencd@0: { ferencd@0: *this = *this + m; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day_last& ferencd@0: year_month_day_last::operator-=(const months& m) NOEXCEPT ferencd@0: { ferencd@0: *this = *this - m; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day_last& ferencd@0: year_month_day_last::operator+=(const years& y) NOEXCEPT ferencd@0: { ferencd@0: *this = *this + y; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day_last& ferencd@0: year_month_day_last::operator-=(const years& y) NOEXCEPT ferencd@0: { ferencd@0: *this = *this - y; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 inline year year_month_day_last::year() const NOEXCEPT {return y_;} ferencd@0: CONSTCD11 inline month year_month_day_last::month() const NOEXCEPT {return mdl_.month();} ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_day_last ferencd@0: year_month_day_last::month_day_last() const NOEXCEPT ferencd@0: { ferencd@0: return mdl_; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: day ferencd@0: year_month_day_last::day() const NOEXCEPT ferencd@0: { ferencd@0: CONSTDATA date::day d[] = ferencd@0: { ferencd@0: date::day(31), date::day(28), date::day(31), ferencd@0: date::day(30), date::day(31), date::day(30), ferencd@0: date::day(31), date::day(31), date::day(30), ferencd@0: date::day(31), date::day(30), date::day(31) ferencd@0: }; ferencd@0: return (month() != February || !y_.is_leap()) && mdl_.ok() ? ferencd@0: d[static_cast(month()) - 1] : date::day{29}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day_last::operator sys_days() const NOEXCEPT ferencd@0: { ferencd@0: return sys_days(year()/month()/day()); ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day_last::operator local_days() const NOEXCEPT ferencd@0: { ferencd@0: return local_days(year()/month()/day()); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: year_month_day_last::ok() const NOEXCEPT ferencd@0: { ferencd@0: return y_.ok() && mdl_.ok(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT ferencd@0: { ferencd@0: return x.year() == y.year() && x.month_day_last() == y.month_day_last(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x == y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator<(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT ferencd@0: { ferencd@0: return x.year() < y.year() ? true ferencd@0: : (x.year() > y.year() ? false ferencd@0: : (x.month_day_last() < y.month_day_last())); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator>(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT ferencd@0: { ferencd@0: return y < x; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT ferencd@0: { ferencd@0: return !(y < x); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x < y); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const year_month_day_last& ymdl) ferencd@0: { ferencd@0: return os << ymdl.year() << '/' << ymdl.month_day_last(); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day_last ferencd@0: operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT ferencd@0: { ferencd@0: return (ymdl.year() / ymdl.month() + dm) / last; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day_last ferencd@0: operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT ferencd@0: { ferencd@0: return ymdl + dm; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day_last ferencd@0: operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT ferencd@0: { ferencd@0: return ymdl + (-dm); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day_last ferencd@0: operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT ferencd@0: { ferencd@0: return {ymdl.year()+dy, ymdl.month_day_last()}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day_last ferencd@0: operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT ferencd@0: { ferencd@0: return ymdl + dy; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day_last ferencd@0: operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT ferencd@0: { ferencd@0: return ymdl + (-dy); ferencd@0: } ferencd@0: ferencd@0: // year_month_day ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day::year_month_day(const date::year& y, const date::month& m, ferencd@0: const date::day& d) NOEXCEPT ferencd@0: : y_(y) ferencd@0: , m_(m) ferencd@0: , d_(d) ferencd@0: {} ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day::year_month_day(const year_month_day_last& ymdl) NOEXCEPT ferencd@0: : y_(ymdl.year()) ferencd@0: , m_(ymdl.month()) ferencd@0: , d_(ymdl.day()) ferencd@0: {} ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day::year_month_day(sys_days dp) NOEXCEPT ferencd@0: : year_month_day(from_days(dp.time_since_epoch())) ferencd@0: {} ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day::year_month_day(local_days dp) NOEXCEPT ferencd@0: : year_month_day(from_days(dp.time_since_epoch())) ferencd@0: {} ferencd@0: ferencd@0: CONSTCD11 inline year year_month_day::year() const NOEXCEPT {return y_;} ferencd@0: CONSTCD11 inline month year_month_day::month() const NOEXCEPT {return m_;} ferencd@0: CONSTCD11 inline day year_month_day::day() const NOEXCEPT {return d_;} ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day& ferencd@0: year_month_day::operator+=(const months& m) NOEXCEPT ferencd@0: { ferencd@0: *this = *this + m; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day& ferencd@0: year_month_day::operator-=(const months& m) NOEXCEPT ferencd@0: { ferencd@0: *this = *this - m; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day& ferencd@0: year_month_day::operator+=(const years& y) NOEXCEPT ferencd@0: { ferencd@0: *this = *this + y; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day& ferencd@0: year_month_day::operator-=(const years& y) NOEXCEPT ferencd@0: { ferencd@0: *this = *this - y; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: days ferencd@0: year_month_day::to_days() const NOEXCEPT ferencd@0: { ferencd@0: static_assert(std::numeric_limits::digits >= 18, ferencd@0: "This algorithm has not been ported to a 16 bit unsigned integer"); ferencd@0: static_assert(std::numeric_limits::digits >= 20, ferencd@0: "This algorithm has not been ported to a 16 bit signed integer"); ferencd@0: auto const y = static_cast(y_) - (m_ <= February); ferencd@0: auto const m = static_cast(m_); ferencd@0: auto const d = static_cast(d_); ferencd@0: auto const era = (y >= 0 ? y : y-399) / 400; ferencd@0: auto const yoe = static_cast(y - era * 400); // [0, 399] ferencd@0: auto const doy = (153*(m > 2 ? m-3 : m+9) + 2)/5 + d-1; // [0, 365] ferencd@0: auto const doe = yoe * 365 + yoe/4 - yoe/100 + doy; // [0, 146096] ferencd@0: return days{era * 146097 + static_cast(doe) - 719468}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day::operator sys_days() const NOEXCEPT ferencd@0: { ferencd@0: return sys_days{to_days()}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day::operator local_days() const NOEXCEPT ferencd@0: { ferencd@0: return local_days{to_days()}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: bool ferencd@0: year_month_day::ok() const NOEXCEPT ferencd@0: { ferencd@0: if (!(y_.ok() && m_.ok())) ferencd@0: return false; ferencd@0: return date::day{1} <= d_ && d_ <= (y_ / m_ / last).day(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT ferencd@0: { ferencd@0: return x.year() == y.year() && x.month() == y.month() && x.day() == y.day(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x == y); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator<(const year_month_day& x, const year_month_day& y) NOEXCEPT ferencd@0: { ferencd@0: return x.year() < y.year() ? true ferencd@0: : (x.year() > y.year() ? false ferencd@0: : (x.month() < y.month() ? true ferencd@0: : (x.month() > y.month() ? false ferencd@0: : (x.day() < y.day())))); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator>(const year_month_day& x, const year_month_day& y) NOEXCEPT ferencd@0: { ferencd@0: return y < x; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT ferencd@0: { ferencd@0: return !(y < x); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x < y); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const year_month_day& ymd) ferencd@0: { ferencd@0: detail::save_ostream _(os); ferencd@0: os.fill('0'); ferencd@0: os.flags(std::ios::dec | std::ios::right); ferencd@0: os << ymd.year() << '-'; ferencd@0: os.width(2); ferencd@0: os << static_cast(ymd.month()) << '-'; ferencd@0: os << ymd.day(); ferencd@0: if (!ymd.ok()) ferencd@0: os << " is not a valid date"; ferencd@0: return os; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day ferencd@0: year_month_day::from_days(days dp) NOEXCEPT ferencd@0: { ferencd@0: static_assert(std::numeric_limits::digits >= 18, ferencd@0: "This algorithm has not been ported to a 16 bit unsigned integer"); ferencd@0: static_assert(std::numeric_limits::digits >= 20, ferencd@0: "This algorithm has not been ported to a 16 bit signed integer"); ferencd@0: auto const z = dp.count() + 719468; ferencd@0: auto const era = (z >= 0 ? z : z - 146096) / 146097; ferencd@0: auto const doe = static_cast(z - era * 146097); // [0, 146096] ferencd@0: auto const yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365; // [0, 399] ferencd@0: auto const y = static_cast(yoe) + era * 400; ferencd@0: auto const doy = doe - (365*yoe + yoe/4 - yoe/100); // [0, 365] ferencd@0: auto const mp = (5*doy + 2)/153; // [0, 11] ferencd@0: auto const d = doy - (153*mp+2)/5 + 1; // [1, 31] ferencd@0: auto const m = mp < 10 ? mp+3 : mp-9; // [1, 12] ferencd@0: return year_month_day{date::year{y + (m <= 2)}, date::month(m), date::day(d)}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day ferencd@0: operator+(const year_month_day& ymd, const months& dm) NOEXCEPT ferencd@0: { ferencd@0: return (ymd.year() / ymd.month() + dm) / ymd.day(); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day ferencd@0: operator+(const months& dm, const year_month_day& ymd) NOEXCEPT ferencd@0: { ferencd@0: return ymd + dm; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_day ferencd@0: operator-(const year_month_day& ymd, const months& dm) NOEXCEPT ferencd@0: { ferencd@0: return ymd + (-dm); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day ferencd@0: operator+(const year_month_day& ymd, const years& dy) NOEXCEPT ferencd@0: { ferencd@0: return (ymd.year() + dy) / ymd.month() / ymd.day(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day ferencd@0: operator+(const years& dy, const year_month_day& ymd) NOEXCEPT ferencd@0: { ferencd@0: return ymd + dy; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day ferencd@0: operator-(const year_month_day& ymd, const years& dy) NOEXCEPT ferencd@0: { ferencd@0: return ymd + (-dy); ferencd@0: } ferencd@0: ferencd@0: // year_month_weekday ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday::year_month_weekday(const date::year& y, const date::month& m, ferencd@0: const date::weekday_indexed& wdi) ferencd@0: NOEXCEPT ferencd@0: : y_(y) ferencd@0: , m_(m) ferencd@0: , wdi_(wdi) ferencd@0: {} ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday::year_month_weekday(const sys_days& dp) NOEXCEPT ferencd@0: : year_month_weekday(from_days(dp.time_since_epoch())) ferencd@0: {} ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday::year_month_weekday(const local_days& dp) NOEXCEPT ferencd@0: : year_month_weekday(from_days(dp.time_since_epoch())) ferencd@0: {} ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday& ferencd@0: year_month_weekday::operator+=(const months& m) NOEXCEPT ferencd@0: { ferencd@0: *this = *this + m; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday& ferencd@0: year_month_weekday::operator-=(const months& m) NOEXCEPT ferencd@0: { ferencd@0: *this = *this - m; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday& ferencd@0: year_month_weekday::operator+=(const years& y) NOEXCEPT ferencd@0: { ferencd@0: *this = *this + y; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday& ferencd@0: year_month_weekday::operator-=(const years& y) NOEXCEPT ferencd@0: { ferencd@0: *this = *this - y; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 inline year year_month_weekday::year() const NOEXCEPT {return y_;} ferencd@0: CONSTCD11 inline month year_month_weekday::month() const NOEXCEPT {return m_;} ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: weekday ferencd@0: year_month_weekday::weekday() const NOEXCEPT ferencd@0: { ferencd@0: return wdi_.weekday(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: unsigned ferencd@0: year_month_weekday::index() const NOEXCEPT ferencd@0: { ferencd@0: return wdi_.index(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: weekday_indexed ferencd@0: year_month_weekday::weekday_indexed() const NOEXCEPT ferencd@0: { ferencd@0: return wdi_; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday::operator sys_days() const NOEXCEPT ferencd@0: { ferencd@0: return sys_days{to_days()}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday::operator local_days() const NOEXCEPT ferencd@0: { ferencd@0: return local_days{to_days()}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: bool ferencd@0: year_month_weekday::ok() const NOEXCEPT ferencd@0: { ferencd@0: if (!y_.ok() || !m_.ok() || !wdi_.weekday().ok() || wdi_.index() < 1) ferencd@0: return false; ferencd@0: if (wdi_.index() <= 4) ferencd@0: return true; ferencd@0: auto d2 = wdi_.weekday() - date::weekday(static_cast(y_/m_/1)) + ferencd@0: days((wdi_.index()-1)*7 + 1); ferencd@0: return static_cast(d2.count()) <= static_cast((y_/m_/last).day()); ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday ferencd@0: year_month_weekday::from_days(days d) NOEXCEPT ferencd@0: { ferencd@0: sys_days dp{d}; ferencd@0: auto const wd = date::weekday(dp); ferencd@0: auto const ymd = year_month_day(dp); ferencd@0: return {ymd.year(), ymd.month(), wd[(static_cast(ymd.day())-1)/7+1]}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: days ferencd@0: year_month_weekday::to_days() const NOEXCEPT ferencd@0: { ferencd@0: auto d = sys_days(y_/m_/1); ferencd@0: return (d + (wdi_.weekday() - date::weekday(d) + days{(wdi_.index()-1)*7}) ferencd@0: ).time_since_epoch(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT ferencd@0: { ferencd@0: return x.year() == y.year() && x.month() == y.month() && ferencd@0: x.weekday_indexed() == y.weekday_indexed(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x == y); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const year_month_weekday& ymwdi) ferencd@0: { ferencd@0: return os << ymwdi.year() << '/' << ymwdi.month() ferencd@0: << '/' << ymwdi.weekday_indexed(); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday ferencd@0: operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT ferencd@0: { ferencd@0: return (ymwd.year() / ymwd.month() + dm) / ymwd.weekday_indexed(); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday ferencd@0: operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT ferencd@0: { ferencd@0: return ymwd + dm; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday ferencd@0: operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT ferencd@0: { ferencd@0: return ymwd + (-dm); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday ferencd@0: operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT ferencd@0: { ferencd@0: return {ymwd.year()+dy, ymwd.month(), ymwd.weekday_indexed()}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday ferencd@0: operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT ferencd@0: { ferencd@0: return ymwd + dy; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday ferencd@0: operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT ferencd@0: { ferencd@0: return ymwd + (-dy); ferencd@0: } ferencd@0: ferencd@0: // year_month_weekday_last ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday_last::year_month_weekday_last(const date::year& y, ferencd@0: const date::month& m, ferencd@0: const date::weekday_last& wdl) NOEXCEPT ferencd@0: : y_(y) ferencd@0: , m_(m) ferencd@0: , wdl_(wdl) ferencd@0: {} ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday_last& ferencd@0: year_month_weekday_last::operator+=(const months& m) NOEXCEPT ferencd@0: { ferencd@0: *this = *this + m; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday_last& ferencd@0: year_month_weekday_last::operator-=(const months& m) NOEXCEPT ferencd@0: { ferencd@0: *this = *this - m; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday_last& ferencd@0: year_month_weekday_last::operator+=(const years& y) NOEXCEPT ferencd@0: { ferencd@0: *this = *this + y; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday_last& ferencd@0: year_month_weekday_last::operator-=(const years& y) NOEXCEPT ferencd@0: { ferencd@0: *this = *this - y; ferencd@0: return *this; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 inline year year_month_weekday_last::year() const NOEXCEPT {return y_;} ferencd@0: CONSTCD11 inline month year_month_weekday_last::month() const NOEXCEPT {return m_;} ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: weekday ferencd@0: year_month_weekday_last::weekday() const NOEXCEPT ferencd@0: { ferencd@0: return wdl_.weekday(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: weekday_last ferencd@0: year_month_weekday_last::weekday_last() const NOEXCEPT ferencd@0: { ferencd@0: return wdl_; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday_last::operator sys_days() const NOEXCEPT ferencd@0: { ferencd@0: return sys_days{to_days()}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday_last::operator local_days() const NOEXCEPT ferencd@0: { ferencd@0: return local_days{to_days()}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: year_month_weekday_last::ok() const NOEXCEPT ferencd@0: { ferencd@0: return y_.ok() && m_.ok() && wdl_.ok(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: days ferencd@0: year_month_weekday_last::to_days() const NOEXCEPT ferencd@0: { ferencd@0: auto const d = sys_days(y_/m_/last); ferencd@0: return (d - (date::weekday{d} - wdl_.weekday())).time_since_epoch(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT ferencd@0: { ferencd@0: return x.year() == y.year() && x.month() == y.month() && ferencd@0: x.weekday_last() == y.weekday_last(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: bool ferencd@0: operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT ferencd@0: { ferencd@0: return !(x == y); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const year_month_weekday_last& ymwdl) ferencd@0: { ferencd@0: return os << ymwdl.year() << '/' << ymwdl.month() << '/' << ymwdl.weekday_last(); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday_last ferencd@0: operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT ferencd@0: { ferencd@0: return (ymwdl.year() / ymwdl.month() + dm) / ymwdl.weekday_last(); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday_last ferencd@0: operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT ferencd@0: { ferencd@0: return ymwdl + dm; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: year_month_weekday_last ferencd@0: operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT ferencd@0: { ferencd@0: return ymwdl + (-dm); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday_last ferencd@0: operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT ferencd@0: { ferencd@0: return {ymwdl.year()+dy, ymwdl.month(), ymwdl.weekday_last()}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday_last ferencd@0: operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT ferencd@0: { ferencd@0: return ymwdl + dy; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday_last ferencd@0: operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT ferencd@0: { ferencd@0: return ymwdl + (-dy); ferencd@0: } ferencd@0: ferencd@0: // year_month from operator/() ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month ferencd@0: operator/(const year& y, const month& m) NOEXCEPT ferencd@0: { ferencd@0: return {y, m}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month ferencd@0: operator/(const year& y, int m) NOEXCEPT ferencd@0: { ferencd@0: return y / month(static_cast(m)); ferencd@0: } ferencd@0: ferencd@0: // month_day from operator/() ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_day ferencd@0: operator/(const month& m, const day& d) NOEXCEPT ferencd@0: { ferencd@0: return {m, d}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_day ferencd@0: operator/(const day& d, const month& m) NOEXCEPT ferencd@0: { ferencd@0: return m / d; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_day ferencd@0: operator/(const month& m, int d) NOEXCEPT ferencd@0: { ferencd@0: return m / day(static_cast(d)); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_day ferencd@0: operator/(int m, const day& d) NOEXCEPT ferencd@0: { ferencd@0: return month(static_cast(m)) / d; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 inline month_day operator/(const day& d, int m) NOEXCEPT {return m / d;} ferencd@0: ferencd@0: // month_day_last from operator/() ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_day_last ferencd@0: operator/(const month& m, last_spec) NOEXCEPT ferencd@0: { ferencd@0: return month_day_last{m}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_day_last ferencd@0: operator/(last_spec, const month& m) NOEXCEPT ferencd@0: { ferencd@0: return m/last; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_day_last ferencd@0: operator/(int m, last_spec) NOEXCEPT ferencd@0: { ferencd@0: return month(static_cast(m))/last; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_day_last ferencd@0: operator/(last_spec, int m) NOEXCEPT ferencd@0: { ferencd@0: return m/last; ferencd@0: } ferencd@0: ferencd@0: // month_weekday from operator/() ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_weekday ferencd@0: operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT ferencd@0: { ferencd@0: return {m, wdi}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_weekday ferencd@0: operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT ferencd@0: { ferencd@0: return m / wdi; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_weekday ferencd@0: operator/(int m, const weekday_indexed& wdi) NOEXCEPT ferencd@0: { ferencd@0: return month(static_cast(m)) / wdi; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_weekday ferencd@0: operator/(const weekday_indexed& wdi, int m) NOEXCEPT ferencd@0: { ferencd@0: return m / wdi; ferencd@0: } ferencd@0: ferencd@0: // month_weekday_last from operator/() ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_weekday_last ferencd@0: operator/(const month& m, const weekday_last& wdl) NOEXCEPT ferencd@0: { ferencd@0: return {m, wdl}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_weekday_last ferencd@0: operator/(const weekday_last& wdl, const month& m) NOEXCEPT ferencd@0: { ferencd@0: return m / wdl; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_weekday_last ferencd@0: operator/(int m, const weekday_last& wdl) NOEXCEPT ferencd@0: { ferencd@0: return month(static_cast(m)) / wdl; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: month_weekday_last ferencd@0: operator/(const weekday_last& wdl, int m) NOEXCEPT ferencd@0: { ferencd@0: return m / wdl; ferencd@0: } ferencd@0: ferencd@0: // year_month_day from operator/() ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day ferencd@0: operator/(const year_month& ym, const day& d) NOEXCEPT ferencd@0: { ferencd@0: return {ym.year(), ym.month(), d}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day ferencd@0: operator/(const year_month& ym, int d) NOEXCEPT ferencd@0: { ferencd@0: return ym / day(static_cast(d)); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day ferencd@0: operator/(const year& y, const month_day& md) NOEXCEPT ferencd@0: { ferencd@0: return y / md.month() / md.day(); ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day ferencd@0: operator/(int y, const month_day& md) NOEXCEPT ferencd@0: { ferencd@0: return year(y) / md; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day ferencd@0: operator/(const month_day& md, const year& y) NOEXCEPT ferencd@0: { ferencd@0: return y / md; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day ferencd@0: operator/(const month_day& md, int y) NOEXCEPT ferencd@0: { ferencd@0: return year(y) / md; ferencd@0: } ferencd@0: ferencd@0: // year_month_day_last from operator/() ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day_last ferencd@0: operator/(const year_month& ym, last_spec) NOEXCEPT ferencd@0: { ferencd@0: return {ym.year(), month_day_last{ym.month()}}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day_last ferencd@0: operator/(const year& y, const month_day_last& mdl) NOEXCEPT ferencd@0: { ferencd@0: return {y, mdl}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day_last ferencd@0: operator/(int y, const month_day_last& mdl) NOEXCEPT ferencd@0: { ferencd@0: return year(y) / mdl; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day_last ferencd@0: operator/(const month_day_last& mdl, const year& y) NOEXCEPT ferencd@0: { ferencd@0: return y / mdl; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_day_last ferencd@0: operator/(const month_day_last& mdl, int y) NOEXCEPT ferencd@0: { ferencd@0: return year(y) / mdl; ferencd@0: } ferencd@0: ferencd@0: // year_month_weekday from operator/() ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday ferencd@0: operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT ferencd@0: { ferencd@0: return {ym.year(), ym.month(), wdi}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday ferencd@0: operator/(const year& y, const month_weekday& mwd) NOEXCEPT ferencd@0: { ferencd@0: return {y, mwd.month(), mwd.weekday_indexed()}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday ferencd@0: operator/(int y, const month_weekday& mwd) NOEXCEPT ferencd@0: { ferencd@0: return year(y) / mwd; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday ferencd@0: operator/(const month_weekday& mwd, const year& y) NOEXCEPT ferencd@0: { ferencd@0: return y / mwd; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday ferencd@0: operator/(const month_weekday& mwd, int y) NOEXCEPT ferencd@0: { ferencd@0: return year(y) / mwd; ferencd@0: } ferencd@0: ferencd@0: // year_month_weekday_last from operator/() ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday_last ferencd@0: operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT ferencd@0: { ferencd@0: return {ym.year(), ym.month(), wdl}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday_last ferencd@0: operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT ferencd@0: { ferencd@0: return {y, mwdl.month(), mwdl.weekday_last()}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday_last ferencd@0: operator/(int y, const month_weekday_last& mwdl) NOEXCEPT ferencd@0: { ferencd@0: return year(y) / mwdl; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday_last ferencd@0: operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT ferencd@0: { ferencd@0: return y / mwdl; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: year_month_weekday_last ferencd@0: operator/(const month_weekday_last& mwdl, int y) NOEXCEPT ferencd@0: { ferencd@0: return year(y) / mwdl; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: struct fields; ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: to_stream(std::basic_ostream& os, const CharT* fmt, ferencd@0: const fields& fds, const std::string* abbrev = nullptr, ferencd@0: const std::chrono::seconds* offset_sec = nullptr); ferencd@0: ferencd@0: template ferencd@0: std::basic_istream& ferencd@0: from_stream(std::basic_istream& is, const CharT* fmt, ferencd@0: fields& fds, std::basic_string* abbrev = nullptr, ferencd@0: std::chrono::minutes* offset = nullptr); ferencd@0: ferencd@0: // hh_mm_ss ferencd@0: ferencd@0: namespace detail ferencd@0: { ferencd@0: ferencd@0: struct undocumented {explicit undocumented() = default;}; ferencd@0: ferencd@0: // width::value is the number of fractional decimal digits in 1/n ferencd@0: // width<0>::value and width<1>::value are defined to be 0 ferencd@0: // If 1/n takes more than 18 fractional decimal digits, ferencd@0: // the result is truncated to 19. ferencd@0: // Example: width<2>::value == 1 ferencd@0: // Example: width<3>::value == 19 ferencd@0: // Example: width<4>::value == 2 ferencd@0: // Example: width<10>::value == 1 ferencd@0: // Example: width<1000>::value == 3 ferencd@0: template ferencd@0: struct width ferencd@0: { ferencd@0: static CONSTDATA unsigned value = 1 + width::value; ferencd@0: }; ferencd@0: ferencd@0: template ferencd@0: struct width ferencd@0: { ferencd@0: static CONSTDATA unsigned value = 0; ferencd@0: }; ferencd@0: ferencd@0: template ferencd@0: struct static_pow10 ferencd@0: { ferencd@0: private: ferencd@0: static CONSTDATA std::uint64_t h = static_pow10::value; ferencd@0: public: ferencd@0: static CONSTDATA std::uint64_t value = h * h * (exp % 2 ? 10 : 1); ferencd@0: }; ferencd@0: ferencd@0: template <> ferencd@0: struct static_pow10<0> ferencd@0: { ferencd@0: static CONSTDATA std::uint64_t value = 1; ferencd@0: }; ferencd@0: ferencd@0: template ferencd@0: class decimal_format_seconds ferencd@0: { ferencd@0: using CT = typename std::common_type::type; ferencd@0: using rep = typename CT::rep; ferencd@0: public: ferencd@0: static unsigned constexpr width = detail::width::value < 19 ? ferencd@0: detail::width::value : 6u; ferencd@0: using precision = std::chrono::duration::value>>; ferencd@0: ferencd@0: private: ferencd@0: std::chrono::seconds s_; ferencd@0: precision sub_s_; ferencd@0: ferencd@0: public: ferencd@0: CONSTCD11 decimal_format_seconds() ferencd@0: : s_() ferencd@0: , sub_s_() ferencd@0: {} ferencd@0: ferencd@0: CONSTCD11 explicit decimal_format_seconds(const Duration& d) NOEXCEPT ferencd@0: : s_(std::chrono::duration_cast(d)) ferencd@0: , sub_s_(std::chrono::treat_as_floating_point::value ? d - s_ : ferencd@0: std::chrono::duration_cast(d - s_)) ferencd@0: {} ferencd@0: ferencd@0: CONSTCD14 std::chrono::seconds& seconds() NOEXCEPT {return s_;} ferencd@0: CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_;} ferencd@0: CONSTCD11 precision subseconds() const NOEXCEPT {return sub_s_;} ferencd@0: ferencd@0: CONSTCD14 precision to_duration() const NOEXCEPT ferencd@0: { ferencd@0: return s_ + sub_s_; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 bool in_conventional_range() const NOEXCEPT ferencd@0: { ferencd@0: return sub_s_ < std::chrono::seconds{1} && s_ < std::chrono::minutes{1}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: friend ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const decimal_format_seconds& x) ferencd@0: { ferencd@0: return x.print(os, std::chrono::treat_as_floating_point{}); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: print(std::basic_ostream& os, std::true_type) const ferencd@0: { ferencd@0: date::detail::save_ostream _(os); ferencd@0: std::chrono::duration d = s_ + sub_s_; ferencd@0: if (d < std::chrono::seconds{10}) ferencd@0: os << '0'; ferencd@0: os << std::fixed << d.count(); ferencd@0: return os; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: print(std::basic_ostream& os, std::false_type) const ferencd@0: { ferencd@0: date::detail::save_ostream _(os); ferencd@0: os.fill('0'); ferencd@0: os.flags(std::ios::dec | std::ios::right); ferencd@0: os.width(2); ferencd@0: os << s_.count(); ferencd@0: if (width > 0) ferencd@0: { ferencd@0: #if !ONLY_C_LOCALE ferencd@0: os << std::use_facet>(os.getloc()).decimal_point(); ferencd@0: #else ferencd@0: os << '.'; ferencd@0: #endif ferencd@0: os.width(width); ferencd@0: os << sub_s_.count(); ferencd@0: } ferencd@0: return os; ferencd@0: } ferencd@0: }; ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: CONSTCD11 ferencd@0: typename std::enable_if ferencd@0: < ferencd@0: std::numeric_limits::is_signed, ferencd@0: std::chrono::duration ferencd@0: >::type ferencd@0: abs(std::chrono::duration d) ferencd@0: { ferencd@0: return d >= d.zero() ? +d : -d; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: CONSTCD11 ferencd@0: typename std::enable_if ferencd@0: < ferencd@0: !std::numeric_limits::is_signed, ferencd@0: std::chrono::duration ferencd@0: >::type ferencd@0: abs(std::chrono::duration d) ferencd@0: { ferencd@0: return d; ferencd@0: } ferencd@0: ferencd@0: } // namespace detail ferencd@0: ferencd@0: template ferencd@0: class hh_mm_ss ferencd@0: { ferencd@0: using dfs = detail::decimal_format_seconds::type>; ferencd@0: ferencd@0: std::chrono::hours h_; ferencd@0: std::chrono::minutes m_; ferencd@0: dfs s_; ferencd@0: bool neg_; ferencd@0: ferencd@0: public: ferencd@0: static unsigned CONSTDATA fractional_width = dfs::width; ferencd@0: using precision = typename dfs::precision; ferencd@0: ferencd@0: CONSTCD11 hh_mm_ss() NOEXCEPT ferencd@0: : hh_mm_ss(Duration::zero()) ferencd@0: {} ferencd@0: ferencd@0: CONSTCD11 explicit hh_mm_ss(Duration d) NOEXCEPT ferencd@0: : h_(std::chrono::duration_cast(detail::abs(d))) ferencd@0: , m_(std::chrono::duration_cast(detail::abs(d)) - h_) ferencd@0: , s_(detail::abs(d) - h_ - m_) ferencd@0: , neg_(d < Duration::zero()) ferencd@0: {} ferencd@0: ferencd@0: CONSTCD11 std::chrono::hours hours() const NOEXCEPT {return h_;} ferencd@0: CONSTCD11 std::chrono::minutes minutes() const NOEXCEPT {return m_;} ferencd@0: CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_.seconds();} ferencd@0: CONSTCD14 std::chrono::seconds& ferencd@0: seconds(detail::undocumented) NOEXCEPT {return s_.seconds();} ferencd@0: CONSTCD11 precision subseconds() const NOEXCEPT {return s_.subseconds();} ferencd@0: CONSTCD11 bool is_negative() const NOEXCEPT {return neg_;} ferencd@0: ferencd@0: CONSTCD11 explicit operator precision() const NOEXCEPT {return to_duration();} ferencd@0: CONSTCD11 precision to_duration() const NOEXCEPT ferencd@0: {return (h_ + m_ + s_.to_duration()) * (1-2*neg_);} ferencd@0: ferencd@0: CONSTCD11 bool in_conventional_range() const NOEXCEPT ferencd@0: { ferencd@0: return !neg_ && h_ < days{1} && m_ < std::chrono::hours{1} && ferencd@0: s_.in_conventional_range(); ferencd@0: } ferencd@0: ferencd@0: private: ferencd@0: ferencd@0: template ferencd@0: friend ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, hh_mm_ss const& tod) ferencd@0: { ferencd@0: if (tod.is_negative()) ferencd@0: os << '-'; ferencd@0: if (tod.h_ < std::chrono::hours{10}) ferencd@0: os << '0'; ferencd@0: os << tod.h_.count() << ':'; ferencd@0: if (tod.m_ < std::chrono::minutes{10}) ferencd@0: os << '0'; ferencd@0: os << tod.m_.count() << ':' << tod.s_; ferencd@0: return os; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: friend ferencd@0: std::basic_ostream& ferencd@0: date::to_stream(std::basic_ostream& os, const CharT* fmt, ferencd@0: const fields& fds, const std::string* abbrev, ferencd@0: const std::chrono::seconds* offset_sec); ferencd@0: ferencd@0: template ferencd@0: friend ferencd@0: std::basic_istream& ferencd@0: date::from_stream(std::basic_istream& is, const CharT* fmt, ferencd@0: fields& fds, ferencd@0: std::basic_string* abbrev, std::chrono::minutes* offset); ferencd@0: }; ferencd@0: ferencd@0: inline ferencd@0: CONSTCD14 ferencd@0: bool ferencd@0: is_am(std::chrono::hours const& h) NOEXCEPT ferencd@0: { ferencd@0: using std::chrono::hours; ferencd@0: return hours{0} <= h && h < hours{12}; ferencd@0: } ferencd@0: ferencd@0: inline ferencd@0: CONSTCD14 ferencd@0: bool ferencd@0: is_pm(std::chrono::hours const& h) NOEXCEPT ferencd@0: { ferencd@0: using std::chrono::hours; ferencd@0: return hours{12} <= h && h < hours{24}; ferencd@0: } ferencd@0: ferencd@0: inline ferencd@0: CONSTCD14 ferencd@0: std::chrono::hours ferencd@0: make12(std::chrono::hours h) NOEXCEPT ferencd@0: { ferencd@0: using std::chrono::hours; ferencd@0: if (h < hours{12}) ferencd@0: { ferencd@0: if (h == hours{0}) ferencd@0: h = hours{12}; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: if (h != hours{12}) ferencd@0: h = h - hours{12}; ferencd@0: } ferencd@0: return h; ferencd@0: } ferencd@0: ferencd@0: inline ferencd@0: CONSTCD14 ferencd@0: std::chrono::hours ferencd@0: make24(std::chrono::hours h, bool is_pm) NOEXCEPT ferencd@0: { ferencd@0: using std::chrono::hours; ferencd@0: if (is_pm) ferencd@0: { ferencd@0: if (h != hours{12}) ferencd@0: h = h + hours{12}; ferencd@0: } ferencd@0: else if (h == hours{12}) ferencd@0: h = hours{0}; ferencd@0: return h; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: using time_of_day = hh_mm_ss; ferencd@0: ferencd@0: template ::value>::type> ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: hh_mm_ss> ferencd@0: make_time(const std::chrono::duration& d) ferencd@0: { ferencd@0: return hh_mm_ss>(d); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: typename std::enable_if ferencd@0: < ferencd@0: !std::chrono::treat_as_floating_point::value && ferencd@0: std::ratio_less::value ferencd@0: , std::basic_ostream& ferencd@0: >::type ferencd@0: operator<<(std::basic_ostream& os, const sys_time& tp) ferencd@0: { ferencd@0: auto const dp = date::floor(tp); ferencd@0: return os << year_month_day(dp) << ' ' << make_time(tp-dp); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const sys_days& dp) ferencd@0: { ferencd@0: return os << year_month_day(dp); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const local_time& ut) ferencd@0: { ferencd@0: return (os << sys_time{ut.time_since_epoch()}); ferencd@0: } ferencd@0: ferencd@0: namespace detail ferencd@0: { ferencd@0: ferencd@0: template ferencd@0: class string_literal; ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: CONSTCD14 ferencd@0: string_literal::type, ferencd@0: N1 + N2 - 1> ferencd@0: operator+(const string_literal& x, const string_literal& y) NOEXCEPT; ferencd@0: ferencd@0: template ferencd@0: class string_literal ferencd@0: { ferencd@0: CharT p_[N]; ferencd@0: ferencd@0: CONSTCD11 string_literal() NOEXCEPT ferencd@0: : p_{} ferencd@0: {} ferencd@0: ferencd@0: public: ferencd@0: using const_iterator = const CharT*; ferencd@0: ferencd@0: string_literal(string_literal const&) = default; ferencd@0: string_literal& operator=(string_literal const&) = delete; ferencd@0: ferencd@0: template ::type> ferencd@0: CONSTCD11 string_literal(CharT c) NOEXCEPT ferencd@0: : p_{c} ferencd@0: { ferencd@0: } ferencd@0: ferencd@0: template ::type> ferencd@0: CONSTCD11 string_literal(CharT c1, CharT c2) NOEXCEPT ferencd@0: : p_{c1, c2} ferencd@0: { ferencd@0: } ferencd@0: ferencd@0: template ::type> ferencd@0: CONSTCD11 string_literal(CharT c1, CharT c2, CharT c3) NOEXCEPT ferencd@0: : p_{c1, c2, c3} ferencd@0: { ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 string_literal(const CharT(&a)[N]) NOEXCEPT ferencd@0: : p_{} ferencd@0: { ferencd@0: for (std::size_t i = 0; i < N; ++i) ferencd@0: p_[i] = a[i]; ferencd@0: } ferencd@0: ferencd@0: template ::type> ferencd@0: CONSTCD14 string_literal(const char(&a)[N]) NOEXCEPT ferencd@0: : p_{} ferencd@0: { ferencd@0: for (std::size_t i = 0; i < N; ++i) ferencd@0: p_[i] = a[i]; ferencd@0: } ferencd@0: ferencd@0: template ::value>::type> ferencd@0: CONSTCD14 string_literal(string_literal const& a) NOEXCEPT ferencd@0: : p_{} ferencd@0: { ferencd@0: for (std::size_t i = 0; i < N; ++i) ferencd@0: p_[i] = a[i]; ferencd@0: } ferencd@0: ferencd@0: CONSTCD11 const CharT* data() const NOEXCEPT {return p_;} ferencd@0: CONSTCD11 std::size_t size() const NOEXCEPT {return N-1;} ferencd@0: ferencd@0: CONSTCD11 const_iterator begin() const NOEXCEPT {return p_;} ferencd@0: CONSTCD11 const_iterator end() const NOEXCEPT {return p_ + N-1;} ferencd@0: ferencd@0: CONSTCD11 CharT const& operator[](std::size_t n) const NOEXCEPT ferencd@0: { ferencd@0: return p_[n]; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: friend ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, const string_literal& s) ferencd@0: { ferencd@0: return os << s.p_; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: friend ferencd@0: CONSTCD14 ferencd@0: string_literal::type, ferencd@0: N1 + N2 - 1> ferencd@0: operator+(const string_literal& x, const string_literal& y) NOEXCEPT; ferencd@0: }; ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: operator+(const string_literal& x, const string_literal& y) NOEXCEPT ferencd@0: { ferencd@0: return string_literal(x[0], y[0]); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: operator+(const string_literal& x, const string_literal& y) NOEXCEPT ferencd@0: { ferencd@0: return string_literal(x[0], x[1], y[0]); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: string_literal::type, ferencd@0: N1 + N2 - 1> ferencd@0: operator+(const string_literal& x, const string_literal& y) NOEXCEPT ferencd@0: { ferencd@0: using CT = typename std::conditional::type; ferencd@0: ferencd@0: string_literal r; ferencd@0: std::size_t i = 0; ferencd@0: for (; i < N1-1; ++i) ferencd@0: r.p_[i] = CT(x.p_[i]); ferencd@0: for (std::size_t j = 0; j < N2; ++j, ++i) ferencd@0: r.p_[i] = CT(y.p_[j]); ferencd@0: ferencd@0: return r; ferencd@0: } ferencd@0: ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_string ferencd@0: operator+(std::basic_string x, const string_literal& y) ferencd@0: { ferencd@0: x.append(y.data(), y.size()); ferencd@0: return x; ferencd@0: } ferencd@0: ferencd@0: #if __cplusplus >= 201402 && (!defined(__EDG_VERSION__) || __EDG_VERSION__ > 411) \ ferencd@0: && (!defined(__SUNPRO_CC) || __SUNPRO_CC > 0x5150) ferencd@0: ferencd@0: template {} || ferencd@0: std::is_same{} || ferencd@0: std::is_same{} || ferencd@0: std::is_same{}>> ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: string_literal ferencd@0: msl(CharT c) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{c}; ferencd@0: } ferencd@0: ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: std::size_t ferencd@0: to_string_len(std::intmax_t i) ferencd@0: { ferencd@0: std::size_t r = 0; ferencd@0: do ferencd@0: { ferencd@0: i /= 10; ferencd@0: ++r; ferencd@0: } while (i > 0); ferencd@0: return r; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: std::enable_if_t ferencd@0: < ferencd@0: N < 10, ferencd@0: string_literal ferencd@0: > ferencd@0: msl() NOEXCEPT ferencd@0: { ferencd@0: return msl(char(N % 10 + '0')); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: std::enable_if_t ferencd@0: < ferencd@0: 10 <= N, ferencd@0: string_literal ferencd@0: > ferencd@0: msl() NOEXCEPT ferencd@0: { ferencd@0: return msl() + msl(char(N % 10 + '0')); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: std::enable_if_t ferencd@0: < ferencd@0: std::ratio::type::den != 1, ferencd@0: string_literal::type::num) + ferencd@0: to_string_len(std::ratio::type::den) + 4> ferencd@0: > ferencd@0: msl(std::ratio) NOEXCEPT ferencd@0: { ferencd@0: using R = typename std::ratio::type; ferencd@0: return msl(CharT{'['}) + msl() + msl(CharT{'/'}) + ferencd@0: msl() + msl(CharT{']'}); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD14 ferencd@0: inline ferencd@0: std::enable_if_t ferencd@0: < ferencd@0: std::ratio::type::den == 1, ferencd@0: string_literal::type::num) + 3> ferencd@0: > ferencd@0: msl(std::ratio) NOEXCEPT ferencd@0: { ferencd@0: using R = typename std::ratio::type; ferencd@0: return msl(CharT{'['}) + msl() + msl(CharT{']'}); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: #else // __cplusplus < 201402 || (defined(__EDG_VERSION__) && __EDG_VERSION__ <= 411) ferencd@0: ferencd@0: inline ferencd@0: std::string ferencd@0: to_string(std::uint64_t x) ferencd@0: { ferencd@0: return std::to_string(x); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_string ferencd@0: to_string(std::uint64_t x) ferencd@0: { ferencd@0: auto y = std::to_string(x); ferencd@0: return std::basic_string(y.begin(), y.end()); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: typename std::enable_if ferencd@0: < ferencd@0: std::ratio::type::den != 1, ferencd@0: std::basic_string ferencd@0: >::type ferencd@0: msl(std::ratio) ferencd@0: { ferencd@0: using R = typename std::ratio::type; ferencd@0: return std::basic_string(1, '[') + to_string(R::num) + CharT{'/'} + ferencd@0: to_string(R::den) + CharT{']'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: typename std::enable_if ferencd@0: < ferencd@0: std::ratio::type::den == 1, ferencd@0: std::basic_string ferencd@0: >::type ferencd@0: msl(std::ratio) ferencd@0: { ferencd@0: using R = typename std::ratio::type; ferencd@0: return std::basic_string(1, '[') + to_string(R::num) + CharT{']'}; ferencd@0: } ferencd@0: ferencd@0: #endif // __cplusplus < 201402 || (defined(__EDG_VERSION__) && __EDG_VERSION__ <= 411) ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: msl(std::atto) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{'a'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: msl(std::femto) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{'f'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: msl(std::pico) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{'p'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: msl(std::nano) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{'n'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: typename std::enable_if ferencd@0: < ferencd@0: std::is_same::value, ferencd@0: string_literal ferencd@0: >::type ferencd@0: msl(std::micro) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{'\xC2', '\xB5'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: typename std::enable_if ferencd@0: < ferencd@0: !std::is_same::value, ferencd@0: string_literal ferencd@0: >::type ferencd@0: msl(std::micro) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{CharT{static_cast('\xB5')}}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: msl(std::milli) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{'m'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: msl(std::centi) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{'c'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: msl(std::deca) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{'d', 'a'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: msl(std::deci) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{'d'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: msl(std::hecto) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{'h'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: msl(std::kilo) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{'k'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: msl(std::mega) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{'M'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: msl(std::giga) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{'G'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: msl(std::tera) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{'T'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: msl(std::peta) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{'P'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: msl(std::exa) NOEXCEPT ferencd@0: { ferencd@0: return string_literal{'E'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: auto ferencd@0: get_units(Period p) ferencd@0: -> decltype(msl(p) + string_literal{'s'}) ferencd@0: { ferencd@0: return msl(p) + string_literal{'s'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: get_units(std::ratio<1>) ferencd@0: { ferencd@0: return string_literal{'s'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: get_units(std::ratio<3600>) ferencd@0: { ferencd@0: return string_literal{'h'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: get_units(std::ratio<60>) ferencd@0: { ferencd@0: return string_literal{'m', 'i', 'n'}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: CONSTCD11 ferencd@0: inline ferencd@0: string_literal ferencd@0: get_units(std::ratio<86400>) ferencd@0: { ferencd@0: return string_literal{'d'}; ferencd@0: } ferencd@0: ferencd@0: template > ferencd@0: struct make_string; ferencd@0: ferencd@0: template <> ferencd@0: struct make_string ferencd@0: { ferencd@0: template ferencd@0: static ferencd@0: std::string ferencd@0: from(Rep n) ferencd@0: { ferencd@0: return std::to_string(n); ferencd@0: } ferencd@0: }; ferencd@0: ferencd@0: template ferencd@0: struct make_string ferencd@0: { ferencd@0: template ferencd@0: static ferencd@0: std::basic_string ferencd@0: from(Rep n) ferencd@0: { ferencd@0: auto s = std::to_string(n); ferencd@0: return std::basic_string(s.begin(), s.end()); ferencd@0: } ferencd@0: }; ferencd@0: ferencd@0: template <> ferencd@0: struct make_string ferencd@0: { ferencd@0: template ferencd@0: static ferencd@0: std::wstring ferencd@0: from(Rep n) ferencd@0: { ferencd@0: return std::to_wstring(n); ferencd@0: } ferencd@0: }; ferencd@0: ferencd@0: template ferencd@0: struct make_string ferencd@0: { ferencd@0: template ferencd@0: static ferencd@0: std::basic_string ferencd@0: from(Rep n) ferencd@0: { ferencd@0: auto s = std::to_wstring(n); ferencd@0: return std::basic_string(s.begin(), s.end()); ferencd@0: } ferencd@0: }; ferencd@0: ferencd@0: } // namespace detail ferencd@0: ferencd@0: // to_stream ferencd@0: ferencd@0: CONSTDATA year nanyear{-32768}; ferencd@0: ferencd@0: template ferencd@0: struct fields ferencd@0: { ferencd@0: year_month_day ymd{nanyear/0/0}; ferencd@0: weekday wd{8u}; ferencd@0: hh_mm_ss tod{}; ferencd@0: bool has_tod = false; ferencd@0: ferencd@0: fields() = default; ferencd@0: ferencd@0: fields(year_month_day ymd_) : ymd(ymd_) {} ferencd@0: fields(weekday wd_) : wd(wd_) {} ferencd@0: fields(hh_mm_ss tod_) : tod(tod_), has_tod(true) {} ferencd@0: ferencd@0: fields(year_month_day ymd_, weekday wd_) : ymd(ymd_), wd(wd_) {} ferencd@0: fields(year_month_day ymd_, hh_mm_ss tod_) : ymd(ymd_), tod(tod_), ferencd@0: has_tod(true) {} ferencd@0: ferencd@0: fields(weekday wd_, hh_mm_ss tod_) : wd(wd_), tod(tod_), has_tod(true) {} ferencd@0: ferencd@0: fields(year_month_day ymd_, weekday wd_, hh_mm_ss tod_) ferencd@0: : ymd(ymd_) ferencd@0: , wd(wd_) ferencd@0: , tod(tod_) ferencd@0: , has_tod(true) ferencd@0: {} ferencd@0: }; ferencd@0: ferencd@0: namespace detail ferencd@0: { ferencd@0: ferencd@0: template ferencd@0: unsigned ferencd@0: extract_weekday(std::basic_ostream& os, const fields& fds) ferencd@0: { ferencd@0: if (!fds.ymd.ok() && !fds.wd.ok()) ferencd@0: { ferencd@0: // fds does not contain a valid weekday ferencd@0: os.setstate(std::ios::failbit); ferencd@0: return 8; ferencd@0: } ferencd@0: weekday wd; ferencd@0: if (fds.ymd.ok()) ferencd@0: { ferencd@0: wd = weekday{sys_days(fds.ymd)}; ferencd@0: if (fds.wd.ok() && wd != fds.wd) ferencd@0: { ferencd@0: // fds.ymd and fds.wd are inconsistent ferencd@0: os.setstate(std::ios::failbit); ferencd@0: return 8; ferencd@0: } ferencd@0: } ferencd@0: else ferencd@0: wd = fds.wd; ferencd@0: return static_cast((wd - Sunday).count()); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: unsigned ferencd@0: extract_month(std::basic_ostream& os, const fields& fds) ferencd@0: { ferencd@0: if (!fds.ymd.month().ok()) ferencd@0: { ferencd@0: // fds does not contain a valid month ferencd@0: os.setstate(std::ios::failbit); ferencd@0: return 0; ferencd@0: } ferencd@0: return static_cast(fds.ymd.month()); ferencd@0: } ferencd@0: ferencd@0: } // namespace detail ferencd@0: ferencd@0: #if ONLY_C_LOCALE ferencd@0: ferencd@0: namespace detail ferencd@0: { ferencd@0: ferencd@0: inline ferencd@0: std::pair ferencd@0: weekday_names() ferencd@0: { ferencd@0: static const std::string nm[] = ferencd@0: { ferencd@0: "Sunday", ferencd@0: "Monday", ferencd@0: "Tuesday", ferencd@0: "Wednesday", ferencd@0: "Thursday", ferencd@0: "Friday", ferencd@0: "Saturday", ferencd@0: "Sun", ferencd@0: "Mon", ferencd@0: "Tue", ferencd@0: "Wed", ferencd@0: "Thu", ferencd@0: "Fri", ferencd@0: "Sat" ferencd@0: }; ferencd@0: return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0])); ferencd@0: } ferencd@0: ferencd@0: inline ferencd@0: std::pair ferencd@0: month_names() ferencd@0: { ferencd@0: static const std::string nm[] = ferencd@0: { ferencd@0: "January", ferencd@0: "February", ferencd@0: "March", ferencd@0: "April", ferencd@0: "May", ferencd@0: "June", ferencd@0: "July", ferencd@0: "August", ferencd@0: "September", ferencd@0: "October", ferencd@0: "November", ferencd@0: "December", ferencd@0: "Jan", ferencd@0: "Feb", ferencd@0: "Mar", ferencd@0: "Apr", ferencd@0: "May", ferencd@0: "Jun", ferencd@0: "Jul", ferencd@0: "Aug", ferencd@0: "Sep", ferencd@0: "Oct", ferencd@0: "Nov", ferencd@0: "Dec" ferencd@0: }; ferencd@0: return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0])); ferencd@0: } ferencd@0: ferencd@0: inline ferencd@0: std::pair ferencd@0: ampm_names() ferencd@0: { ferencd@0: static const std::string nm[] = ferencd@0: { ferencd@0: "AM", ferencd@0: "PM" ferencd@0: }; ferencd@0: return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0])); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: FwdIter ferencd@0: scan_keyword(std::basic_istream& is, FwdIter kb, FwdIter ke) ferencd@0: { ferencd@0: size_t nkw = static_cast(std::distance(kb, ke)); ferencd@0: const unsigned char doesnt_match = '\0'; ferencd@0: const unsigned char might_match = '\1'; ferencd@0: const unsigned char does_match = '\2'; ferencd@0: unsigned char statbuf[100]; ferencd@0: unsigned char* status = statbuf; ferencd@0: std::unique_ptr stat_hold(0, free); ferencd@0: if (nkw > sizeof(statbuf)) ferencd@0: { ferencd@0: status = (unsigned char*)std::malloc(nkw); ferencd@0: if (status == nullptr) ferencd@0: throw std::bad_alloc(); ferencd@0: stat_hold.reset(status); ferencd@0: } ferencd@0: size_t n_might_match = nkw; // At this point, any keyword might match ferencd@0: size_t n_does_match = 0; // but none of them definitely do ferencd@0: // Initialize all statuses to might_match, except for "" keywords are does_match ferencd@0: unsigned char* st = status; ferencd@0: for (auto ky = kb; ky != ke; ++ky, ++st) ferencd@0: { ferencd@0: if (!ky->empty()) ferencd@0: *st = might_match; ferencd@0: else ferencd@0: { ferencd@0: *st = does_match; ferencd@0: --n_might_match; ferencd@0: ++n_does_match; ferencd@0: } ferencd@0: } ferencd@0: // While there might be a match, test keywords against the next CharT ferencd@0: for (size_t indx = 0; is && n_might_match > 0; ++indx) ferencd@0: { ferencd@0: // Peek at the next CharT but don't consume it ferencd@0: auto ic = is.peek(); ferencd@0: if (ic == EOF) ferencd@0: { ferencd@0: is.setstate(std::ios::eofbit); ferencd@0: break; ferencd@0: } ferencd@0: auto c = static_cast(toupper(ic)); ferencd@0: bool consume = false; ferencd@0: // For each keyword which might match, see if the indx character is c ferencd@0: // If a match if found, consume c ferencd@0: // If a match is found, and that is the last character in the keyword, ferencd@0: // then that keyword matches. ferencd@0: // If the keyword doesn't match this character, then change the keyword ferencd@0: // to doesn't match ferencd@0: st = status; ferencd@0: for (auto ky = kb; ky != ke; ++ky, ++st) ferencd@0: { ferencd@0: if (*st == might_match) ferencd@0: { ferencd@0: if (c == static_cast(toupper((*ky)[indx]))) ferencd@0: { ferencd@0: consume = true; ferencd@0: if (ky->size() == indx+1) ferencd@0: { ferencd@0: *st = does_match; ferencd@0: --n_might_match; ferencd@0: ++n_does_match; ferencd@0: } ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: *st = doesnt_match; ferencd@0: --n_might_match; ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: // consume if we matched a character ferencd@0: if (consume) ferencd@0: { ferencd@0: (void)is.get(); ferencd@0: // If we consumed a character and there might be a matched keyword that ferencd@0: // was marked matched on a previous iteration, then such keywords ferencd@0: // are now marked as not matching. ferencd@0: if (n_might_match + n_does_match > 1) ferencd@0: { ferencd@0: st = status; ferencd@0: for (auto ky = kb; ky != ke; ++ky, ++st) ferencd@0: { ferencd@0: if (*st == does_match && ky->size() != indx+1) ferencd@0: { ferencd@0: *st = doesnt_match; ferencd@0: --n_does_match; ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: // We've exited the loop because we hit eof and/or we have no more "might matches". ferencd@0: // Return the first matching result ferencd@0: for (st = status; kb != ke; ++kb, ++st) ferencd@0: if (*st == does_match) ferencd@0: break; ferencd@0: if (kb == ke) ferencd@0: is.setstate(std::ios::failbit); ferencd@0: return kb; ferencd@0: } ferencd@0: ferencd@0: } // namespace detail ferencd@0: ferencd@0: #endif // ONLY_C_LOCALE ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: to_stream(std::basic_ostream& os, const CharT* fmt, ferencd@0: const fields& fds, const std::string* abbrev, ferencd@0: const std::chrono::seconds* offset_sec) ferencd@0: { ferencd@0: #if ONLY_C_LOCALE ferencd@0: using detail::weekday_names; ferencd@0: using detail::month_names; ferencd@0: using detail::ampm_names; ferencd@0: #endif ferencd@0: using detail::save_ostream; ferencd@0: using detail::get_units; ferencd@0: using detail::extract_weekday; ferencd@0: using detail::extract_month; ferencd@0: using std::ios; ferencd@0: using std::chrono::duration_cast; ferencd@0: using std::chrono::seconds; ferencd@0: using std::chrono::minutes; ferencd@0: using std::chrono::hours; ferencd@0: date::detail::save_ostream ss(os); ferencd@0: os.fill(' '); ferencd@0: os.flags(std::ios::skipws | std::ios::dec); ferencd@0: os.width(0); ferencd@0: tm tm{}; ferencd@0: bool insert_negative = fds.has_tod && fds.tod.to_duration() < Duration::zero(); ferencd@0: #if !ONLY_C_LOCALE ferencd@0: auto& facet = std::use_facet>(os.getloc()); ferencd@0: #endif ferencd@0: const CharT* command = nullptr; ferencd@0: CharT modified = CharT{}; ferencd@0: for (; *fmt; ++fmt) ferencd@0: { ferencd@0: switch (*fmt) ferencd@0: { ferencd@0: case 'a': ferencd@0: case 'A': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: tm.tm_wday = static_cast(extract_weekday(os, fds)); ferencd@0: if (os.fail()) ferencd@0: return os; ferencd@0: #if !ONLY_C_LOCALE ferencd@0: const CharT f[] = {'%', *fmt}; ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: #else // ONLY_C_LOCALE ferencd@0: os << weekday_names().first[tm.tm_wday+7*(*fmt == 'a')]; ferencd@0: #endif // ONLY_C_LOCALE ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'b': ferencd@0: case 'B': ferencd@0: case 'h': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: tm.tm_mon = static_cast(extract_month(os, fds)) - 1; ferencd@0: #if !ONLY_C_LOCALE ferencd@0: const CharT f[] = {'%', *fmt}; ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: #else // ONLY_C_LOCALE ferencd@0: os << month_names().first[tm.tm_mon+12*(*fmt != 'B')]; ferencd@0: #endif // ONLY_C_LOCALE ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'c': ferencd@0: case 'x': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{'O'}) ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: else ferencd@0: { ferencd@0: if (!fds.ymd.ok()) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: if (*fmt == 'c' && !fds.has_tod) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: #if !ONLY_C_LOCALE ferencd@0: tm = std::tm{}; ferencd@0: auto const& ymd = fds.ymd; ferencd@0: auto ld = local_days(ymd); ferencd@0: if (*fmt == 'c') ferencd@0: { ferencd@0: tm.tm_sec = static_cast(fds.tod.seconds().count()); ferencd@0: tm.tm_min = static_cast(fds.tod.minutes().count()); ferencd@0: tm.tm_hour = static_cast(fds.tod.hours().count()); ferencd@0: } ferencd@0: tm.tm_mday = static_cast(static_cast(ymd.day())); ferencd@0: tm.tm_mon = static_cast(extract_month(os, fds) - 1); ferencd@0: tm.tm_year = static_cast(ymd.year()) - 1900; ferencd@0: tm.tm_wday = static_cast(extract_weekday(os, fds)); ferencd@0: if (os.fail()) ferencd@0: return os; ferencd@0: tm.tm_yday = static_cast((ld - local_days(ymd.year()/1/1)).count()); ferencd@0: CharT f[3] = {'%'}; ferencd@0: auto fe = std::begin(f) + 1; ferencd@0: if (modified == CharT{'E'}) ferencd@0: *fe++ = modified; ferencd@0: *fe++ = *fmt; ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), fe); ferencd@0: #else // ONLY_C_LOCALE ferencd@0: if (*fmt == 'c') ferencd@0: { ferencd@0: auto wd = static_cast(extract_weekday(os, fds)); ferencd@0: os << weekday_names().first[static_cast(wd)+7] ferencd@0: << ' '; ferencd@0: os << month_names().first[extract_month(os, fds)-1+12] << ' '; ferencd@0: auto d = static_cast(static_cast(fds.ymd.day())); ferencd@0: if (d < 10) ferencd@0: os << ' '; ferencd@0: os << d << ' ' ferencd@0: << make_time(duration_cast(fds.tod.to_duration())) ferencd@0: << ' ' << fds.ymd.year(); ferencd@0: ferencd@0: } ferencd@0: else // *fmt == 'x' ferencd@0: { ferencd@0: auto const& ymd = fds.ymd; ferencd@0: save_ostream _(os); ferencd@0: os.fill('0'); ferencd@0: os.flags(std::ios::dec | std::ios::right); ferencd@0: os.width(2); ferencd@0: os << static_cast(ymd.month()) << CharT{'/'}; ferencd@0: os.width(2); ferencd@0: os << static_cast(ymd.day()) << CharT{'/'}; ferencd@0: os.width(2); ferencd@0: os << static_cast(ymd.year()) % 100; ferencd@0: } ferencd@0: #endif // ONLY_C_LOCALE ferencd@0: } ferencd@0: command = nullptr; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'C': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{'O'}) ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: else ferencd@0: { ferencd@0: if (!fds.ymd.year().ok()) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: auto y = static_cast(fds.ymd.year()); ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #endif ferencd@0: { ferencd@0: save_ostream _(os); ferencd@0: os.fill('0'); ferencd@0: os.flags(std::ios::dec | std::ios::right); ferencd@0: if (y >= 0) ferencd@0: { ferencd@0: os.width(2); ferencd@0: os << y/100; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'-'}; ferencd@0: os.width(2); ferencd@0: os << -(y-99)/100; ferencd@0: } ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'E'}) ferencd@0: { ferencd@0: tm.tm_year = y - 1900; ferencd@0: CharT f[3] = {'%', 'E', 'C'}; ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: } ferencd@0: #endif ferencd@0: } ferencd@0: command = nullptr; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'd': ferencd@0: case 'e': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{'E'}) ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: else ferencd@0: { ferencd@0: if (!fds.ymd.day().ok()) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: auto d = static_cast(static_cast(fds.ymd.day())); ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #endif ferencd@0: { ferencd@0: save_ostream _(os); ferencd@0: if (*fmt == CharT{'d'}) ferencd@0: os.fill('0'); ferencd@0: else ferencd@0: os.fill(' '); ferencd@0: os.flags(std::ios::dec | std::ios::right); ferencd@0: os.width(2); ferencd@0: os << d; ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'O'}) ferencd@0: { ferencd@0: tm.tm_mday = d; ferencd@0: CharT f[3] = {'%', 'O', *fmt}; ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: } ferencd@0: #endif ferencd@0: } ferencd@0: command = nullptr; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'D': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: if (!fds.ymd.ok()) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: auto const& ymd = fds.ymd; ferencd@0: save_ostream _(os); ferencd@0: os.fill('0'); ferencd@0: os.flags(std::ios::dec | std::ios::right); ferencd@0: os.width(2); ferencd@0: os << static_cast(ymd.month()) << CharT{'/'}; ferencd@0: os.width(2); ferencd@0: os << static_cast(ymd.day()) << CharT{'/'}; ferencd@0: os.width(2); ferencd@0: os << static_cast(ymd.year()) % 100; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'F': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: if (!fds.ymd.ok()) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: auto const& ymd = fds.ymd; ferencd@0: save_ostream _(os); ferencd@0: os.fill('0'); ferencd@0: os.flags(std::ios::dec | std::ios::right); ferencd@0: os.width(4); ferencd@0: os << static_cast(ymd.year()) << CharT{'-'}; ferencd@0: os.width(2); ferencd@0: os << static_cast(ymd.month()) << CharT{'-'}; ferencd@0: os.width(2); ferencd@0: os << static_cast(ymd.day()); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'g': ferencd@0: case 'G': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: if (!fds.ymd.ok()) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: auto ld = local_days(fds.ymd); ferencd@0: auto y = year_month_day{ld + days{3}}.year(); ferencd@0: auto start = local_days((y-years{1})/December/Thursday[last]) + ferencd@0: (Monday-Thursday); ferencd@0: if (ld < start) ferencd@0: --y; ferencd@0: if (*fmt == CharT{'G'}) ferencd@0: os << y; ferencd@0: else ferencd@0: { ferencd@0: save_ostream _(os); ferencd@0: os.fill('0'); ferencd@0: os.flags(std::ios::dec | std::ios::right); ferencd@0: os.width(2); ferencd@0: os << std::abs(static_cast(y)) % 100; ferencd@0: } ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'H': ferencd@0: case 'I': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{'E'}) ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: else ferencd@0: { ferencd@0: if (!fds.has_tod) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: if (insert_negative) ferencd@0: { ferencd@0: os << '-'; ferencd@0: insert_negative = false; ferencd@0: } ferencd@0: auto hms = fds.tod; ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #endif ferencd@0: { ferencd@0: auto h = *fmt == CharT{'I'} ? date::make12(hms.hours()) : hms.hours(); ferencd@0: if (h < hours{10}) ferencd@0: os << CharT{'0'}; ferencd@0: os << h.count(); ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'O'}) ferencd@0: { ferencd@0: const CharT f[] = {'%', modified, *fmt}; ferencd@0: tm.tm_hour = static_cast(hms.hours().count()); ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: } ferencd@0: #endif ferencd@0: } ferencd@0: modified = CharT{}; ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'j': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: if (fds.ymd.ok() || fds.has_tod) ferencd@0: { ferencd@0: days doy; ferencd@0: if (fds.ymd.ok()) ferencd@0: { ferencd@0: auto ld = local_days(fds.ymd); ferencd@0: auto y = fds.ymd.year(); ferencd@0: doy = ld - local_days(y/January/1) + days{1}; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: doy = duration_cast(fds.tod.to_duration()); ferencd@0: } ferencd@0: save_ostream _(os); ferencd@0: os.fill('0'); ferencd@0: os.flags(std::ios::dec | std::ios::right); ferencd@0: os.width(3); ferencd@0: os << doy.count(); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: os.setstate(std::ios::failbit); ferencd@0: } ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'm': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{'E'}) ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: else ferencd@0: { ferencd@0: if (!fds.ymd.month().ok()) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: auto m = static_cast(fds.ymd.month()); ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #endif ferencd@0: { ferencd@0: if (m < 10) ferencd@0: os << CharT{'0'}; ferencd@0: os << m; ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'O'}) ferencd@0: { ferencd@0: const CharT f[] = {'%', modified, *fmt}; ferencd@0: tm.tm_mon = static_cast(m-1); ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: } ferencd@0: #endif ferencd@0: } ferencd@0: modified = CharT{}; ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'M': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{'E'}) ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: else ferencd@0: { ferencd@0: if (!fds.has_tod) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: if (insert_negative) ferencd@0: { ferencd@0: os << '-'; ferencd@0: insert_negative = false; ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #endif ferencd@0: { ferencd@0: if (fds.tod.minutes() < minutes{10}) ferencd@0: os << CharT{'0'}; ferencd@0: os << fds.tod.minutes().count(); ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'O'}) ferencd@0: { ferencd@0: const CharT f[] = {'%', modified, *fmt}; ferencd@0: tm.tm_min = static_cast(fds.tod.minutes().count()); ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: } ferencd@0: #endif ferencd@0: } ferencd@0: modified = CharT{}; ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'n': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: os << CharT{'\n'}; ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'p': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: if (!fds.has_tod) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: #if !ONLY_C_LOCALE ferencd@0: const CharT f[] = {'%', *fmt}; ferencd@0: tm.tm_hour = static_cast(fds.tod.hours().count()); ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: #else ferencd@0: if (date::is_am(fds.tod.hours())) ferencd@0: os << ampm_names().first[0]; ferencd@0: else ferencd@0: os << ampm_names().first[1]; ferencd@0: #endif ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: } ferencd@0: modified = CharT{}; ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'Q': ferencd@0: case 'q': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: if (!fds.has_tod) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: auto d = fds.tod.to_duration(); ferencd@0: if (*fmt == 'q') ferencd@0: os << get_units(typename decltype(d)::period::type{}); ferencd@0: else ferencd@0: os << d.count(); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: } ferencd@0: modified = CharT{}; ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'r': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: if (!fds.has_tod) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: #if !ONLY_C_LOCALE ferencd@0: const CharT f[] = {'%', *fmt}; ferencd@0: tm.tm_hour = static_cast(fds.tod.hours().count()); ferencd@0: tm.tm_min = static_cast(fds.tod.minutes().count()); ferencd@0: tm.tm_sec = static_cast(fds.tod.seconds().count()); ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: #else ferencd@0: hh_mm_ss tod(duration_cast(fds.tod.to_duration())); ferencd@0: save_ostream _(os); ferencd@0: os.fill('0'); ferencd@0: os.width(2); ferencd@0: os << date::make12(tod.hours()).count() << CharT{':'}; ferencd@0: os.width(2); ferencd@0: os << tod.minutes().count() << CharT{':'}; ferencd@0: os.width(2); ferencd@0: os << tod.seconds().count() << CharT{' '}; ferencd@0: if (date::is_am(tod.hours())) ferencd@0: os << ampm_names().first[0]; ferencd@0: else ferencd@0: os << ampm_names().first[1]; ferencd@0: #endif ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: } ferencd@0: modified = CharT{}; ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'R': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: if (!fds.has_tod) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: if (fds.tod.hours() < hours{10}) ferencd@0: os << CharT{'0'}; ferencd@0: os << fds.tod.hours().count() << CharT{':'}; ferencd@0: if (fds.tod.minutes() < minutes{10}) ferencd@0: os << CharT{'0'}; ferencd@0: os << fds.tod.minutes().count(); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'S': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{'E'}) ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: else ferencd@0: { ferencd@0: if (!fds.has_tod) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: if (insert_negative) ferencd@0: { ferencd@0: os << '-'; ferencd@0: insert_negative = false; ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #endif ferencd@0: { ferencd@0: os << fds.tod.s_; ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'O'}) ferencd@0: { ferencd@0: const CharT f[] = {'%', modified, *fmt}; ferencd@0: tm.tm_sec = static_cast(fds.tod.s_.seconds().count()); ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: } ferencd@0: #endif ferencd@0: } ferencd@0: modified = CharT{}; ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 't': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: os << CharT{'\t'}; ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'T': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: if (!fds.has_tod) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: os << fds.tod; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'u': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{'E'}) ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: else ferencd@0: { ferencd@0: auto wd = extract_weekday(os, fds); ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #endif ferencd@0: { ferencd@0: os << (wd != 0 ? wd : 7u); ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'O'}) ferencd@0: { ferencd@0: const CharT f[] = {'%', modified, *fmt}; ferencd@0: tm.tm_wday = static_cast(wd); ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: } ferencd@0: #endif ferencd@0: } ferencd@0: modified = CharT{}; ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'U': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{'E'}) ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: else ferencd@0: { ferencd@0: auto const& ymd = fds.ymd; ferencd@0: if (!ymd.ok()) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: auto ld = local_days(ymd); ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #endif ferencd@0: { ferencd@0: auto st = local_days(Sunday[1]/January/ymd.year()); ferencd@0: if (ld < st) ferencd@0: os << CharT{'0'} << CharT{'0'}; ferencd@0: else ferencd@0: { ferencd@0: auto wn = duration_cast(ld - st).count() + 1; ferencd@0: if (wn < 10) ferencd@0: os << CharT{'0'}; ferencd@0: os << wn; ferencd@0: } ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'O'}) ferencd@0: { ferencd@0: const CharT f[] = {'%', modified, *fmt}; ferencd@0: tm.tm_year = static_cast(ymd.year()) - 1900; ferencd@0: tm.tm_wday = static_cast(extract_weekday(os, fds)); ferencd@0: if (os.fail()) ferencd@0: return os; ferencd@0: tm.tm_yday = static_cast((ld - local_days(ymd.year()/1/1)).count()); ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: } ferencd@0: #endif ferencd@0: } ferencd@0: modified = CharT{}; ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'V': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{'E'}) ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: else ferencd@0: { ferencd@0: if (!fds.ymd.ok()) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: auto ld = local_days(fds.ymd); ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #endif ferencd@0: { ferencd@0: auto y = year_month_day{ld + days{3}}.year(); ferencd@0: auto st = local_days((y-years{1})/12/Thursday[last]) + ferencd@0: (Monday-Thursday); ferencd@0: if (ld < st) ferencd@0: { ferencd@0: --y; ferencd@0: st = local_days((y - years{1})/12/Thursday[last]) + ferencd@0: (Monday-Thursday); ferencd@0: } ferencd@0: auto wn = duration_cast(ld - st).count() + 1; ferencd@0: if (wn < 10) ferencd@0: os << CharT{'0'}; ferencd@0: os << wn; ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'O'}) ferencd@0: { ferencd@0: const CharT f[] = {'%', modified, *fmt}; ferencd@0: auto const& ymd = fds.ymd; ferencd@0: tm.tm_year = static_cast(ymd.year()) - 1900; ferencd@0: tm.tm_wday = static_cast(extract_weekday(os, fds)); ferencd@0: if (os.fail()) ferencd@0: return os; ferencd@0: tm.tm_yday = static_cast((ld - local_days(ymd.year()/1/1)).count()); ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: } ferencd@0: #endif ferencd@0: } ferencd@0: modified = CharT{}; ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'w': ferencd@0: if (command) ferencd@0: { ferencd@0: auto wd = extract_weekday(os, fds); ferencd@0: if (os.fail()) ferencd@0: return os; ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #else ferencd@0: if (modified != CharT{'E'}) ferencd@0: #endif ferencd@0: { ferencd@0: os << wd; ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'O'}) ferencd@0: { ferencd@0: const CharT f[] = {'%', modified, *fmt}; ferencd@0: tm.tm_wday = static_cast(wd); ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: } ferencd@0: #endif ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: } ferencd@0: modified = CharT{}; ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'W': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{'E'}) ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: else ferencd@0: { ferencd@0: auto const& ymd = fds.ymd; ferencd@0: if (!ymd.ok()) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: auto ld = local_days(ymd); ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #endif ferencd@0: { ferencd@0: auto st = local_days(Monday[1]/January/ymd.year()); ferencd@0: if (ld < st) ferencd@0: os << CharT{'0'} << CharT{'0'}; ferencd@0: else ferencd@0: { ferencd@0: auto wn = duration_cast(ld - st).count() + 1; ferencd@0: if (wn < 10) ferencd@0: os << CharT{'0'}; ferencd@0: os << wn; ferencd@0: } ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'O'}) ferencd@0: { ferencd@0: const CharT f[] = {'%', modified, *fmt}; ferencd@0: tm.tm_year = static_cast(ymd.year()) - 1900; ferencd@0: tm.tm_wday = static_cast(extract_weekday(os, fds)); ferencd@0: if (os.fail()) ferencd@0: return os; ferencd@0: tm.tm_yday = static_cast((ld - local_days(ymd.year()/1/1)).count()); ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: } ferencd@0: #endif ferencd@0: } ferencd@0: modified = CharT{}; ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'X': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{'O'}) ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: else ferencd@0: { ferencd@0: if (!fds.has_tod) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: #if !ONLY_C_LOCALE ferencd@0: tm = std::tm{}; ferencd@0: tm.tm_sec = static_cast(fds.tod.seconds().count()); ferencd@0: tm.tm_min = static_cast(fds.tod.minutes().count()); ferencd@0: tm.tm_hour = static_cast(fds.tod.hours().count()); ferencd@0: CharT f[3] = {'%'}; ferencd@0: auto fe = std::begin(f) + 1; ferencd@0: if (modified == CharT{'E'}) ferencd@0: *fe++ = modified; ferencd@0: *fe++ = *fmt; ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), fe); ferencd@0: #else ferencd@0: os << fds.tod; ferencd@0: #endif ferencd@0: } ferencd@0: command = nullptr; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'y': ferencd@0: if (command) ferencd@0: { ferencd@0: if (!fds.ymd.year().ok()) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: auto y = static_cast(fds.ymd.year()); ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: #endif ferencd@0: y = std::abs(y) % 100; ferencd@0: if (y < 10) ferencd@0: os << CharT{'0'}; ferencd@0: os << y; ferencd@0: #if !ONLY_C_LOCALE ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: const CharT f[] = {'%', modified, *fmt}; ferencd@0: tm.tm_year = y - 1900; ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: } ferencd@0: #endif ferencd@0: modified = CharT{}; ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'Y': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{'O'}) ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: else ferencd@0: { ferencd@0: if (!fds.ymd.year().ok()) ferencd@0: os.setstate(std::ios::failbit); ferencd@0: auto y = fds.ymd.year(); ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #endif ferencd@0: { ferencd@0: os << y; ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'E'}) ferencd@0: { ferencd@0: const CharT f[] = {'%', modified, *fmt}; ferencd@0: tm.tm_year = static_cast(y) - 1900; ferencd@0: facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f)); ferencd@0: } ferencd@0: #endif ferencd@0: } ferencd@0: modified = CharT{}; ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'z': ferencd@0: if (command) ferencd@0: { ferencd@0: if (offset_sec == nullptr) ferencd@0: { ferencd@0: // Can not format %z with unknown offset ferencd@0: os.setstate(ios::failbit); ferencd@0: return os; ferencd@0: } ferencd@0: auto m = duration_cast(*offset_sec); ferencd@0: auto neg = m < minutes{0}; ferencd@0: m = date::abs(m); ferencd@0: auto h = duration_cast(m); ferencd@0: m -= h; ferencd@0: if (neg) ferencd@0: os << CharT{'-'}; ferencd@0: else ferencd@0: os << CharT{'+'}; ferencd@0: if (h < hours{10}) ferencd@0: os << CharT{'0'}; ferencd@0: os << h.count(); ferencd@0: if (modified != CharT{}) ferencd@0: os << CharT{':'}; ferencd@0: if (m < minutes{10}) ferencd@0: os << CharT{'0'}; ferencd@0: os << m.count(); ferencd@0: command = nullptr; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'Z': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: if (abbrev == nullptr) ferencd@0: { ferencd@0: // Can not format %Z with unknown time_zone ferencd@0: os.setstate(ios::failbit); ferencd@0: return os; ferencd@0: } ferencd@0: for (auto c : *abbrev) ferencd@0: os << CharT(c); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case 'E': ferencd@0: case 'O': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: modified = *fmt; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << *fmt; ferencd@0: command = nullptr; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: } ferencd@0: else ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: case '%': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: os << CharT{'%'}; ferencd@0: command = nullptr; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: os << CharT{'%'} << modified << CharT{'%'}; ferencd@0: command = nullptr; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: } ferencd@0: else ferencd@0: command = fmt; ferencd@0: break; ferencd@0: default: ferencd@0: if (command) ferencd@0: { ferencd@0: os << CharT{'%'}; ferencd@0: command = nullptr; ferencd@0: } ferencd@0: if (modified != CharT{}) ferencd@0: { ferencd@0: os << modified; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: os << *fmt; ferencd@0: break; ferencd@0: } ferencd@0: } ferencd@0: if (command) ferencd@0: os << CharT{'%'}; ferencd@0: if (modified != CharT{}) ferencd@0: os << modified; ferencd@0: return os; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: to_stream(std::basic_ostream& os, const CharT* fmt, const year& y) ferencd@0: { ferencd@0: using CT = std::chrono::seconds; ferencd@0: fields fds{y/0/0}; ferencd@0: return to_stream(os, fmt, fds); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: to_stream(std::basic_ostream& os, const CharT* fmt, const month& m) ferencd@0: { ferencd@0: using CT = std::chrono::seconds; ferencd@0: fields fds{m/0/nanyear}; ferencd@0: return to_stream(os, fmt, fds); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: to_stream(std::basic_ostream& os, const CharT* fmt, const day& d) ferencd@0: { ferencd@0: using CT = std::chrono::seconds; ferencd@0: fields fds{d/0/nanyear}; ferencd@0: return to_stream(os, fmt, fds); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: to_stream(std::basic_ostream& os, const CharT* fmt, const weekday& wd) ferencd@0: { ferencd@0: using CT = std::chrono::seconds; ferencd@0: fields fds{wd}; ferencd@0: return to_stream(os, fmt, fds); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: to_stream(std::basic_ostream& os, const CharT* fmt, const year_month& ym) ferencd@0: { ferencd@0: using CT = std::chrono::seconds; ferencd@0: fields fds{ym/0}; ferencd@0: return to_stream(os, fmt, fds); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: to_stream(std::basic_ostream& os, const CharT* fmt, const month_day& md) ferencd@0: { ferencd@0: using CT = std::chrono::seconds; ferencd@0: fields fds{md/nanyear}; ferencd@0: return to_stream(os, fmt, fds); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: to_stream(std::basic_ostream& os, const CharT* fmt, ferencd@0: const year_month_day& ymd) ferencd@0: { ferencd@0: using CT = std::chrono::seconds; ferencd@0: fields fds{ymd}; ferencd@0: return to_stream(os, fmt, fds); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: to_stream(std::basic_ostream& os, const CharT* fmt, ferencd@0: const std::chrono::duration& d) ferencd@0: { ferencd@0: using Duration = std::chrono::duration; ferencd@0: using CT = typename std::common_type::type; ferencd@0: fields fds{hh_mm_ss{d}}; ferencd@0: return to_stream(os, fmt, fds); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: to_stream(std::basic_ostream& os, const CharT* fmt, ferencd@0: const local_time& tp, const std::string* abbrev = nullptr, ferencd@0: const std::chrono::seconds* offset_sec = nullptr) ferencd@0: { ferencd@0: using CT = typename std::common_type::type; ferencd@0: auto ld = floor(tp); ferencd@0: fields fds{year_month_day{ld}, hh_mm_ss{tp-local_seconds{ld}}}; ferencd@0: return to_stream(os, fmt, fds, abbrev, offset_sec); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: std::basic_ostream& ferencd@0: to_stream(std::basic_ostream& os, const CharT* fmt, ferencd@0: const sys_time& tp) ferencd@0: { ferencd@0: using std::chrono::seconds; ferencd@0: using CT = typename std::common_type::type; ferencd@0: const std::string abbrev("UTC"); ferencd@0: CONSTDATA seconds offset{0}; ferencd@0: auto sd = floor(tp); ferencd@0: fields fds{year_month_day{sd}, hh_mm_ss{tp-sys_seconds{sd}}}; ferencd@0: return to_stream(os, fmt, fds, &abbrev, &offset); ferencd@0: } ferencd@0: ferencd@0: // format ferencd@0: ferencd@0: template ferencd@0: auto ferencd@0: format(const std::locale& loc, const CharT* fmt, const Streamable& tp) ferencd@0: -> decltype(to_stream(std::declval&>(), fmt, tp), ferencd@0: std::basic_string{}) ferencd@0: { ferencd@0: std::basic_ostringstream os; ferencd@0: os.exceptions(std::ios::failbit | std::ios::badbit); ferencd@0: os.imbue(loc); ferencd@0: to_stream(os, fmt, tp); ferencd@0: return os.str(); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: auto ferencd@0: format(const CharT* fmt, const Streamable& tp) ferencd@0: -> decltype(to_stream(std::declval&>(), fmt, tp), ferencd@0: std::basic_string{}) ferencd@0: { ferencd@0: std::basic_ostringstream os; ferencd@0: os.exceptions(std::ios::failbit | std::ios::badbit); ferencd@0: to_stream(os, fmt, tp); ferencd@0: return os.str(); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: auto ferencd@0: format(const std::locale& loc, const std::basic_string& fmt, ferencd@0: const Streamable& tp) ferencd@0: -> decltype(to_stream(std::declval&>(), fmt.c_str(), tp), ferencd@0: std::basic_string{}) ferencd@0: { ferencd@0: std::basic_ostringstream os; ferencd@0: os.exceptions(std::ios::failbit | std::ios::badbit); ferencd@0: os.imbue(loc); ferencd@0: to_stream(os, fmt.c_str(), tp); ferencd@0: return os.str(); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: auto ferencd@0: format(const std::basic_string& fmt, const Streamable& tp) ferencd@0: -> decltype(to_stream(std::declval&>(), fmt.c_str(), tp), ferencd@0: std::basic_string{}) ferencd@0: { ferencd@0: std::basic_ostringstream os; ferencd@0: os.exceptions(std::ios::failbit | std::ios::badbit); ferencd@0: to_stream(os, fmt.c_str(), tp); ferencd@0: return os.str(); ferencd@0: } ferencd@0: ferencd@0: // parse ferencd@0: ferencd@0: namespace detail ferencd@0: { ferencd@0: ferencd@0: template ferencd@0: bool ferencd@0: read_char(std::basic_istream& is, CharT fmt, std::ios::iostate& err) ferencd@0: { ferencd@0: auto ic = is.get(); ferencd@0: if (Traits::eq_int_type(ic, Traits::eof()) || ferencd@0: !Traits::eq(Traits::to_char_type(ic), fmt)) ferencd@0: { ferencd@0: err |= std::ios::failbit; ferencd@0: is.setstate(std::ios::failbit); ferencd@0: return false; ferencd@0: } ferencd@0: return true; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: unsigned ferencd@0: read_unsigned(std::basic_istream& is, unsigned m = 1, unsigned M = 10) ferencd@0: { ferencd@0: unsigned x = 0; ferencd@0: unsigned count = 0; ferencd@0: while (true) ferencd@0: { ferencd@0: auto ic = is.peek(); ferencd@0: if (Traits::eq_int_type(ic, Traits::eof())) ferencd@0: break; ferencd@0: auto c = static_cast(Traits::to_char_type(ic)); ferencd@0: if (!('0' <= c && c <= '9')) ferencd@0: break; ferencd@0: (void)is.get(); ferencd@0: ++count; ferencd@0: x = 10*x + static_cast(c - '0'); ferencd@0: if (count == M) ferencd@0: break; ferencd@0: } ferencd@0: if (count < m) ferencd@0: is.setstate(std::ios::failbit); ferencd@0: return x; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: int ferencd@0: read_signed(std::basic_istream& is, unsigned m = 1, unsigned M = 10) ferencd@0: { ferencd@0: auto ic = is.peek(); ferencd@0: if (!Traits::eq_int_type(ic, Traits::eof())) ferencd@0: { ferencd@0: auto c = static_cast(Traits::to_char_type(ic)); ferencd@0: if (('0' <= c && c <= '9') || c == '-' || c == '+') ferencd@0: { ferencd@0: if (c == '-' || c == '+') ferencd@0: (void)is.get(); ferencd@0: auto x = static_cast(read_unsigned(is, std::max(m, 1u), M)); ferencd@0: if (!is.fail()) ferencd@0: { ferencd@0: if (c == '-') ferencd@0: x = -x; ferencd@0: return x; ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: if (m > 0) ferencd@0: is.setstate(std::ios::failbit); ferencd@0: return 0; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: long double ferencd@0: read_long_double(std::basic_istream& is, unsigned m = 1, unsigned M = 10) ferencd@0: { ferencd@0: unsigned count = 0; ferencd@0: auto decimal_point = Traits::to_int_type( ferencd@0: std::use_facet>(is.getloc()).decimal_point()); ferencd@0: std::string buf; ferencd@0: while (true) ferencd@0: { ferencd@0: auto ic = is.peek(); ferencd@0: if (Traits::eq_int_type(ic, Traits::eof())) ferencd@0: break; ferencd@0: if (Traits::eq_int_type(ic, decimal_point)) ferencd@0: { ferencd@0: buf += '.'; ferencd@0: decimal_point = Traits::eof(); ferencd@0: is.get(); ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: auto c = static_cast(Traits::to_char_type(ic)); ferencd@0: if (!('0' <= c && c <= '9')) ferencd@0: break; ferencd@0: buf += c; ferencd@0: (void)is.get(); ferencd@0: } ferencd@0: if (++count == M) ferencd@0: break; ferencd@0: } ferencd@0: if (count < m) ferencd@0: { ferencd@0: is.setstate(std::ios::failbit); ferencd@0: return 0; ferencd@0: } ferencd@0: return std::stold(buf); ferencd@0: } ferencd@0: ferencd@0: struct rs ferencd@0: { ferencd@0: int& i; ferencd@0: unsigned m; ferencd@0: unsigned M; ferencd@0: }; ferencd@0: ferencd@0: struct ru ferencd@0: { ferencd@0: int& i; ferencd@0: unsigned m; ferencd@0: unsigned M; ferencd@0: }; ferencd@0: ferencd@0: struct rld ferencd@0: { ferencd@0: long double& i; ferencd@0: unsigned m; ferencd@0: unsigned M; ferencd@0: }; ferencd@0: ferencd@0: template ferencd@0: void ferencd@0: read(std::basic_istream&) ferencd@0: { ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: void ferencd@0: read(std::basic_istream& is, CharT a0, Args&& ...args); ferencd@0: ferencd@0: template ferencd@0: void ferencd@0: read(std::basic_istream& is, rs a0, Args&& ...args); ferencd@0: ferencd@0: template ferencd@0: void ferencd@0: read(std::basic_istream& is, ru a0, Args&& ...args); ferencd@0: ferencd@0: template ferencd@0: void ferencd@0: read(std::basic_istream& is, int a0, Args&& ...args); ferencd@0: ferencd@0: template ferencd@0: void ferencd@0: read(std::basic_istream& is, rld a0, Args&& ...args); ferencd@0: ferencd@0: template ferencd@0: void ferencd@0: read(std::basic_istream& is, CharT a0, Args&& ...args) ferencd@0: { ferencd@0: // No-op if a0 == CharT{} ferencd@0: if (a0 != CharT{}) ferencd@0: { ferencd@0: auto ic = is.peek(); ferencd@0: if (Traits::eq_int_type(ic, Traits::eof())) ferencd@0: { ferencd@0: is.setstate(std::ios::failbit | std::ios::eofbit); ferencd@0: return; ferencd@0: } ferencd@0: if (!Traits::eq(Traits::to_char_type(ic), a0)) ferencd@0: { ferencd@0: is.setstate(std::ios::failbit); ferencd@0: return; ferencd@0: } ferencd@0: (void)is.get(); ferencd@0: } ferencd@0: read(is, std::forward(args)...); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: void ferencd@0: read(std::basic_istream& is, rs a0, Args&& ...args) ferencd@0: { ferencd@0: auto x = read_signed(is, a0.m, a0.M); ferencd@0: if (is.fail()) ferencd@0: return; ferencd@0: a0.i = x; ferencd@0: read(is, std::forward(args)...); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: void ferencd@0: read(std::basic_istream& is, ru a0, Args&& ...args) ferencd@0: { ferencd@0: auto x = read_unsigned(is, a0.m, a0.M); ferencd@0: if (is.fail()) ferencd@0: return; ferencd@0: a0.i = static_cast(x); ferencd@0: read(is, std::forward(args)...); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: void ferencd@0: read(std::basic_istream& is, int a0, Args&& ...args) ferencd@0: { ferencd@0: if (a0 != -1) ferencd@0: { ferencd@0: auto u = static_cast(a0); ferencd@0: CharT buf[std::numeric_limits::digits10+2u] = {}; ferencd@0: auto e = buf; ferencd@0: do ferencd@0: { ferencd@0: *e++ = static_cast(CharT(u % 10) + CharT{'0'}); ferencd@0: u /= 10; ferencd@0: } while (u > 0); ferencd@0: std::reverse(buf, e); ferencd@0: for (auto p = buf; p != e && is.rdstate() == std::ios::goodbit; ++p) ferencd@0: read(is, *p); ferencd@0: } ferencd@0: if (is.rdstate() == std::ios::goodbit) ferencd@0: read(is, std::forward(args)...); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: void ferencd@0: read(std::basic_istream& is, rld a0, Args&& ...args) ferencd@0: { ferencd@0: auto x = read_long_double(is, a0.m, a0.M); ferencd@0: if (is.fail()) ferencd@0: return; ferencd@0: a0.i = x; ferencd@0: read(is, std::forward(args)...); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: void ferencd@0: checked_set(T& value, T from, T not_a_value, std::basic_ios& is) ferencd@0: { ferencd@0: if (!is.fail()) ferencd@0: { ferencd@0: if (value == not_a_value) ferencd@0: value = std::move(from); ferencd@0: else if (value != from) ferencd@0: is.setstate(std::ios::failbit); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: } // namespace detail; ferencd@0: ferencd@0: template > ferencd@0: std::basic_istream& ferencd@0: from_stream(std::basic_istream& is, const CharT* fmt, ferencd@0: fields& fds, std::basic_string* abbrev, ferencd@0: std::chrono::minutes* offset) ferencd@0: { ferencd@0: using std::numeric_limits; ferencd@0: using std::ios; ferencd@0: using std::chrono::duration; ferencd@0: using std::chrono::duration_cast; ferencd@0: using std::chrono::seconds; ferencd@0: using std::chrono::minutes; ferencd@0: using std::chrono::hours; ferencd@0: typename std::basic_istream::sentry ok{is, true}; ferencd@0: if (ok) ferencd@0: { ferencd@0: date::detail::save_istream ss(is); ferencd@0: is.fill(' '); ferencd@0: is.flags(std::ios::skipws | std::ios::dec); ferencd@0: is.width(0); ferencd@0: #if !ONLY_C_LOCALE ferencd@0: auto& f = std::use_facet>(is.getloc()); ferencd@0: std::tm tm{}; ferencd@0: #endif ferencd@0: const CharT* command = nullptr; ferencd@0: auto modified = CharT{}; ferencd@0: auto width = -1; ferencd@0: ferencd@0: CONSTDATA int not_a_year = numeric_limits::min(); ferencd@0: CONSTDATA int not_a_2digit_year = 100; ferencd@0: CONSTDATA int not_a_century = not_a_year / 100; ferencd@0: CONSTDATA int not_a_month = 0; ferencd@0: CONSTDATA int not_a_day = 0; ferencd@0: CONSTDATA int not_a_hour = numeric_limits::min(); ferencd@0: CONSTDATA int not_a_hour_12_value = 0; ferencd@0: CONSTDATA int not_a_minute = not_a_hour; ferencd@0: CONSTDATA Duration not_a_second = Duration::min(); ferencd@0: CONSTDATA int not_a_doy = -1; ferencd@0: CONSTDATA int not_a_weekday = 8; ferencd@0: CONSTDATA int not_a_week_num = 100; ferencd@0: CONSTDATA int not_a_ampm = -1; ferencd@0: CONSTDATA minutes not_a_offset = minutes::min(); ferencd@0: ferencd@0: int Y = not_a_year; // c, F, Y * ferencd@0: int y = not_a_2digit_year; // D, x, y * ferencd@0: int g = not_a_2digit_year; // g * ferencd@0: int G = not_a_year; // G * ferencd@0: int C = not_a_century; // C * ferencd@0: int m = not_a_month; // b, B, h, m, c, D, F, x * ferencd@0: int d = not_a_day; // c, d, D, e, F, x * ferencd@0: int j = not_a_doy; // j * ferencd@0: int wd = not_a_weekday; // a, A, u, w * ferencd@0: int H = not_a_hour; // c, H, R, T, X * ferencd@0: int I = not_a_hour_12_value; // I, r * ferencd@0: int p = not_a_ampm; // p, r * ferencd@0: int M = not_a_minute; // c, M, r, R, T, X * ferencd@0: Duration s = not_a_second; // c, r, S, T, X * ferencd@0: int U = not_a_week_num; // U * ferencd@0: int V = not_a_week_num; // V * ferencd@0: int W = not_a_week_num; // W * ferencd@0: std::basic_string temp_abbrev; // Z * ferencd@0: minutes temp_offset = not_a_offset; // z * ferencd@0: ferencd@0: using detail::read; ferencd@0: using detail::rs; ferencd@0: using detail::ru; ferencd@0: using detail::rld; ferencd@0: using detail::checked_set; ferencd@0: for (; *fmt != CharT{} && !is.fail(); ++fmt) ferencd@0: { ferencd@0: switch (*fmt) ferencd@0: { ferencd@0: case 'a': ferencd@0: case 'A': ferencd@0: case 'u': ferencd@0: case 'w': // wd: a, A, u, w ferencd@0: if (command) ferencd@0: { ferencd@0: int trial_wd = not_a_weekday; ferencd@0: if (*fmt == 'a' || *fmt == 'A') ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: #if !ONLY_C_LOCALE ferencd@0: ios::iostate err = ios::goodbit; ferencd@0: f.get(is, nullptr, is, err, &tm, command, fmt+1); ferencd@0: is.setstate(err); ferencd@0: if (!is.fail()) ferencd@0: trial_wd = tm.tm_wday; ferencd@0: #else ferencd@0: auto nm = detail::weekday_names(); ferencd@0: auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; ferencd@0: if (!is.fail()) ferencd@0: trial_wd = i % 7; ferencd@0: #endif ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: } ferencd@0: else // *fmt == 'u' || *fmt == 'w' ferencd@0: { ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #else ferencd@0: if (modified != CharT{'E'}) ferencd@0: #endif ferencd@0: { ferencd@0: read(is, ru{trial_wd, 1, width == -1 ? ferencd@0: 1u : static_cast(width)}); ferencd@0: if (!is.fail()) ferencd@0: { ferencd@0: if (*fmt == 'u') ferencd@0: { ferencd@0: if (!(1 <= trial_wd && trial_wd <= 7)) ferencd@0: { ferencd@0: trial_wd = not_a_weekday; ferencd@0: is.setstate(ios::failbit); ferencd@0: } ferencd@0: else if (trial_wd == 7) ferencd@0: trial_wd = 0; ferencd@0: } ferencd@0: else // *fmt == 'w' ferencd@0: { ferencd@0: if (!(0 <= trial_wd && trial_wd <= 6)) ferencd@0: { ferencd@0: trial_wd = not_a_weekday; ferencd@0: is.setstate(ios::failbit); ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'O'}) ferencd@0: { ferencd@0: ios::iostate err = ios::goodbit; ferencd@0: f.get(is, nullptr, is, err, &tm, command, fmt+1); ferencd@0: is.setstate(err); ferencd@0: if (!is.fail()) ferencd@0: trial_wd = tm.tm_wday; ferencd@0: } ferencd@0: #endif ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: } ferencd@0: if (trial_wd != not_a_weekday) ferencd@0: checked_set(wd, trial_wd, not_a_weekday, is); ferencd@0: } ferencd@0: else // !command ferencd@0: read(is, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: break; ferencd@0: case 'b': ferencd@0: case 'B': ferencd@0: case 'h': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: int ttm = not_a_month; ferencd@0: #if !ONLY_C_LOCALE ferencd@0: ios::iostate err = ios::goodbit; ferencd@0: f.get(is, nullptr, is, err, &tm, command, fmt+1); ferencd@0: if ((err & ios::failbit) == 0) ferencd@0: ttm = tm.tm_mon + 1; ferencd@0: is.setstate(err); ferencd@0: #else ferencd@0: auto nm = detail::month_names(); ferencd@0: auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; ferencd@0: if (!is.fail()) ferencd@0: ttm = i % 12 + 1; ferencd@0: #endif ferencd@0: checked_set(m, ttm, not_a_month, is); ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'c': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified != CharT{'O'}) ferencd@0: { ferencd@0: #if !ONLY_C_LOCALE ferencd@0: ios::iostate err = ios::goodbit; ferencd@0: f.get(is, nullptr, is, err, &tm, command, fmt+1); ferencd@0: if ((err & ios::failbit) == 0) ferencd@0: { ferencd@0: checked_set(Y, tm.tm_year + 1900, not_a_year, is); ferencd@0: checked_set(m, tm.tm_mon + 1, not_a_month, is); ferencd@0: checked_set(d, tm.tm_mday, not_a_day, is); ferencd@0: checked_set(H, tm.tm_hour, not_a_hour, is); ferencd@0: checked_set(M, tm.tm_min, not_a_minute, is); ferencd@0: checked_set(s, duration_cast(seconds{tm.tm_sec}), ferencd@0: not_a_second, is); ferencd@0: } ferencd@0: is.setstate(err); ferencd@0: #else ferencd@0: // "%a %b %e %T %Y" ferencd@0: auto nm = detail::weekday_names(); ferencd@0: auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; ferencd@0: checked_set(wd, static_cast(i % 7), not_a_weekday, is); ferencd@0: ws(is); ferencd@0: nm = detail::month_names(); ferencd@0: i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; ferencd@0: checked_set(m, static_cast(i % 12 + 1), not_a_month, is); ferencd@0: ws(is); ferencd@0: int td = not_a_day; ferencd@0: read(is, rs{td, 1, 2}); ferencd@0: checked_set(d, td, not_a_day, is); ferencd@0: ws(is); ferencd@0: using dfs = detail::decimal_format_seconds; ferencd@0: CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; ferencd@0: int tH; ferencd@0: int tM; ferencd@0: long double S; ferencd@0: read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2}, ferencd@0: CharT{':'}, rld{S, 1, w}); ferencd@0: checked_set(H, tH, not_a_hour, is); ferencd@0: checked_set(M, tM, not_a_minute, is); ferencd@0: checked_set(s, round(duration{S}), ferencd@0: not_a_second, is); ferencd@0: ws(is); ferencd@0: int tY = not_a_year; ferencd@0: read(is, rs{tY, 1, 4u}); ferencd@0: checked_set(Y, tY, not_a_year, is); ferencd@0: #endif ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'x': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified != CharT{'O'}) ferencd@0: { ferencd@0: #if !ONLY_C_LOCALE ferencd@0: ios::iostate err = ios::goodbit; ferencd@0: f.get(is, nullptr, is, err, &tm, command, fmt+1); ferencd@0: if ((err & ios::failbit) == 0) ferencd@0: { ferencd@0: checked_set(Y, tm.tm_year + 1900, not_a_year, is); ferencd@0: checked_set(m, tm.tm_mon + 1, not_a_month, is); ferencd@0: checked_set(d, tm.tm_mday, not_a_day, is); ferencd@0: } ferencd@0: is.setstate(err); ferencd@0: #else ferencd@0: // "%m/%d/%y" ferencd@0: int ty = not_a_2digit_year; ferencd@0: int tm = not_a_month; ferencd@0: int td = not_a_day; ferencd@0: read(is, ru{tm, 1, 2}, CharT{'/'}, ru{td, 1, 2}, CharT{'/'}, ferencd@0: rs{ty, 1, 2}); ferencd@0: checked_set(y, ty, not_a_2digit_year, is); ferencd@0: checked_set(m, tm, not_a_month, is); ferencd@0: checked_set(d, td, not_a_day, is); ferencd@0: #endif ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'X': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified != CharT{'O'}) ferencd@0: { ferencd@0: #if !ONLY_C_LOCALE ferencd@0: ios::iostate err = ios::goodbit; ferencd@0: f.get(is, nullptr, is, err, &tm, command, fmt+1); ferencd@0: if ((err & ios::failbit) == 0) ferencd@0: { ferencd@0: checked_set(H, tm.tm_hour, not_a_hour, is); ferencd@0: checked_set(M, tm.tm_min, not_a_minute, is); ferencd@0: checked_set(s, duration_cast(seconds{tm.tm_sec}), ferencd@0: not_a_second, is); ferencd@0: } ferencd@0: is.setstate(err); ferencd@0: #else ferencd@0: // "%T" ferencd@0: using dfs = detail::decimal_format_seconds; ferencd@0: CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; ferencd@0: int tH = not_a_hour; ferencd@0: int tM = not_a_minute; ferencd@0: long double S; ferencd@0: read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2}, ferencd@0: CharT{':'}, rld{S, 1, w}); ferencd@0: checked_set(H, tH, not_a_hour, is); ferencd@0: checked_set(M, tM, not_a_minute, is); ferencd@0: checked_set(s, round(duration{S}), ferencd@0: not_a_second, is); ferencd@0: #endif ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'C': ferencd@0: if (command) ferencd@0: { ferencd@0: int tC = not_a_century; ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: #endif ferencd@0: read(is, rs{tC, 1, width == -1 ? 2u : static_cast(width)}); ferencd@0: #if !ONLY_C_LOCALE ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: ios::iostate err = ios::goodbit; ferencd@0: f.get(is, nullptr, is, err, &tm, command, fmt+1); ferencd@0: if ((err & ios::failbit) == 0) ferencd@0: { ferencd@0: auto tY = tm.tm_year + 1900; ferencd@0: tC = (tY >= 0 ? tY : tY-99) / 100; ferencd@0: } ferencd@0: is.setstate(err); ferencd@0: } ferencd@0: #endif ferencd@0: checked_set(C, tC, not_a_century, is); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'D': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: int tn = not_a_month; ferencd@0: int td = not_a_day; ferencd@0: int ty = not_a_2digit_year; ferencd@0: read(is, ru{tn, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'}, ferencd@0: ru{td, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'}, ferencd@0: rs{ty, 1, 2}); ferencd@0: checked_set(y, ty, not_a_2digit_year, is); ferencd@0: checked_set(m, tn, not_a_month, is); ferencd@0: checked_set(d, td, not_a_day, is); ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'F': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: int tY = not_a_year; ferencd@0: int tn = not_a_month; ferencd@0: int td = not_a_day; ferencd@0: read(is, rs{tY, 1, width == -1 ? 4u : static_cast(width)}, ferencd@0: CharT{'-'}, ru{tn, 1, 2}, CharT{'-'}, ru{td, 1, 2}); ferencd@0: checked_set(Y, tY, not_a_year, is); ferencd@0: checked_set(m, tn, not_a_month, is); ferencd@0: checked_set(d, td, not_a_day, is); ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'd': ferencd@0: case 'e': ferencd@0: if (command) ferencd@0: { ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #else ferencd@0: if (modified != CharT{'E'}) ferencd@0: #endif ferencd@0: { ferencd@0: int td = not_a_day; ferencd@0: read(is, rs{td, 1, width == -1 ? 2u : static_cast(width)}); ferencd@0: checked_set(d, td, not_a_day, is); ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'O'}) ferencd@0: { ferencd@0: ios::iostate err = ios::goodbit; ferencd@0: f.get(is, nullptr, is, err, &tm, command, fmt+1); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: if ((err & ios::failbit) == 0) ferencd@0: checked_set(d, tm.tm_mday, not_a_day, is); ferencd@0: is.setstate(err); ferencd@0: } ferencd@0: #endif ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'H': ferencd@0: if (command) ferencd@0: { ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #else ferencd@0: if (modified != CharT{'E'}) ferencd@0: #endif ferencd@0: { ferencd@0: int tH = not_a_hour; ferencd@0: read(is, ru{tH, 1, width == -1 ? 2u : static_cast(width)}); ferencd@0: checked_set(H, tH, not_a_hour, is); ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'O'}) ferencd@0: { ferencd@0: ios::iostate err = ios::goodbit; ferencd@0: f.get(is, nullptr, is, err, &tm, command, fmt+1); ferencd@0: if ((err & ios::failbit) == 0) ferencd@0: checked_set(H, tm.tm_hour, not_a_hour, is); ferencd@0: is.setstate(err); ferencd@0: } ferencd@0: #endif ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'I': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: int tI = not_a_hour_12_value; ferencd@0: // reads in an hour into I, but most be in [1, 12] ferencd@0: read(is, rs{tI, 1, width == -1 ? 2u : static_cast(width)}); ferencd@0: if (!(1 <= tI && tI <= 12)) ferencd@0: is.setstate(ios::failbit); ferencd@0: checked_set(I, tI, not_a_hour_12_value, is); ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'j': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: int tj = not_a_doy; ferencd@0: read(is, ru{tj, 1, width == -1 ? 3u : static_cast(width)}); ferencd@0: checked_set(j, tj, not_a_doy, is); ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'M': ferencd@0: if (command) ferencd@0: { ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #else ferencd@0: if (modified != CharT{'E'}) ferencd@0: #endif ferencd@0: { ferencd@0: int tM = not_a_minute; ferencd@0: read(is, ru{tM, 1, width == -1 ? 2u : static_cast(width)}); ferencd@0: checked_set(M, tM, not_a_minute, is); ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'O'}) ferencd@0: { ferencd@0: ios::iostate err = ios::goodbit; ferencd@0: f.get(is, nullptr, is, err, &tm, command, fmt+1); ferencd@0: if ((err & ios::failbit) == 0) ferencd@0: checked_set(M, tm.tm_min, not_a_minute, is); ferencd@0: is.setstate(err); ferencd@0: } ferencd@0: #endif ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'm': ferencd@0: if (command) ferencd@0: { ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #else ferencd@0: if (modified != CharT{'E'}) ferencd@0: #endif ferencd@0: { ferencd@0: int tn = not_a_month; ferencd@0: read(is, rs{tn, 1, width == -1 ? 2u : static_cast(width)}); ferencd@0: checked_set(m, tn, not_a_month, is); ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'O'}) ferencd@0: { ferencd@0: ios::iostate err = ios::goodbit; ferencd@0: f.get(is, nullptr, is, err, &tm, command, fmt+1); ferencd@0: if ((err & ios::failbit) == 0) ferencd@0: checked_set(m, tm.tm_mon + 1, not_a_month, is); ferencd@0: is.setstate(err); ferencd@0: } ferencd@0: #endif ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'n': ferencd@0: case 't': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: // %n matches a single white space character ferencd@0: // %t matches 0 or 1 white space characters ferencd@0: auto ic = is.peek(); ferencd@0: if (Traits::eq_int_type(ic, Traits::eof())) ferencd@0: { ferencd@0: ios::iostate err = ios::eofbit; ferencd@0: if (*fmt == 'n') ferencd@0: err |= ios::failbit; ferencd@0: is.setstate(err); ferencd@0: break; ferencd@0: } ferencd@0: if (isspace(ic)) ferencd@0: { ferencd@0: (void)is.get(); ferencd@0: } ferencd@0: else if (*fmt == 'n') ferencd@0: is.setstate(ios::failbit); ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'p': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: int tp = not_a_ampm; ferencd@0: #if !ONLY_C_LOCALE ferencd@0: tm = std::tm{}; ferencd@0: tm.tm_hour = 1; ferencd@0: ios::iostate err = ios::goodbit; ferencd@0: f.get(is, nullptr, is, err, &tm, command, fmt+1); ferencd@0: is.setstate(err); ferencd@0: if (tm.tm_hour == 1) ferencd@0: tp = 0; ferencd@0: else if (tm.tm_hour == 13) ferencd@0: tp = 1; ferencd@0: else ferencd@0: is.setstate(err); ferencd@0: #else ferencd@0: auto nm = detail::ampm_names(); ferencd@0: auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; ferencd@0: tp = i; ferencd@0: #endif ferencd@0: checked_set(p, tp, not_a_ampm, is); ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: ferencd@0: break; ferencd@0: case 'r': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: #if !ONLY_C_LOCALE ferencd@0: ios::iostate err = ios::goodbit; ferencd@0: f.get(is, nullptr, is, err, &tm, command, fmt+1); ferencd@0: if ((err & ios::failbit) == 0) ferencd@0: { ferencd@0: checked_set(H, tm.tm_hour, not_a_hour, is); ferencd@0: checked_set(M, tm.tm_min, not_a_hour, is); ferencd@0: checked_set(s, duration_cast(seconds{tm.tm_sec}), ferencd@0: not_a_second, is); ferencd@0: } ferencd@0: is.setstate(err); ferencd@0: #else ferencd@0: // "%I:%M:%S %p" ferencd@0: using dfs = detail::decimal_format_seconds; ferencd@0: CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; ferencd@0: long double S; ferencd@0: int tI = not_a_hour_12_value; ferencd@0: int tM = not_a_minute; ferencd@0: read(is, ru{tI, 1, 2}, CharT{':'}, ru{tM, 1, 2}, ferencd@0: CharT{':'}, rld{S, 1, w}); ferencd@0: checked_set(I, tI, not_a_hour_12_value, is); ferencd@0: checked_set(M, tM, not_a_minute, is); ferencd@0: checked_set(s, round(duration{S}), ferencd@0: not_a_second, is); ferencd@0: ws(is); ferencd@0: auto nm = detail::ampm_names(); ferencd@0: auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first; ferencd@0: checked_set(p, static_cast(i), not_a_ampm, is); ferencd@0: #endif ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'R': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: int tH = not_a_hour; ferencd@0: int tM = not_a_minute; ferencd@0: read(is, ru{tH, 1, 2}, CharT{'\0'}, CharT{':'}, CharT{'\0'}, ferencd@0: ru{tM, 1, 2}, CharT{'\0'}); ferencd@0: checked_set(H, tH, not_a_hour, is); ferencd@0: checked_set(M, tM, not_a_minute, is); ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'S': ferencd@0: if (command) ferencd@0: { ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #else ferencd@0: if (modified != CharT{'E'}) ferencd@0: #endif ferencd@0: { ferencd@0: using dfs = detail::decimal_format_seconds; ferencd@0: CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; ferencd@0: long double S; ferencd@0: read(is, rld{S, 1, width == -1 ? w : static_cast(width)}); ferencd@0: checked_set(s, round(duration{S}), ferencd@0: not_a_second, is); ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'O'}) ferencd@0: { ferencd@0: ios::iostate err = ios::goodbit; ferencd@0: f.get(is, nullptr, is, err, &tm, command, fmt+1); ferencd@0: if ((err & ios::failbit) == 0) ferencd@0: checked_set(s, duration_cast(seconds{tm.tm_sec}), ferencd@0: not_a_second, is); ferencd@0: is.setstate(err); ferencd@0: } ferencd@0: #endif ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'T': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: using dfs = detail::decimal_format_seconds; ferencd@0: CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width; ferencd@0: int tH = not_a_hour; ferencd@0: int tM = not_a_minute; ferencd@0: long double S; ferencd@0: read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2}, ferencd@0: CharT{':'}, rld{S, 1, w}); ferencd@0: checked_set(H, tH, not_a_hour, is); ferencd@0: checked_set(M, tM, not_a_minute, is); ferencd@0: checked_set(s, round(duration{S}), ferencd@0: not_a_second, is); ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'Y': ferencd@0: if (command) ferencd@0: { ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #else ferencd@0: if (modified != CharT{'O'}) ferencd@0: #endif ferencd@0: { ferencd@0: int tY = not_a_year; ferencd@0: read(is, rs{tY, 1, width == -1 ? 4u : static_cast(width)}); ferencd@0: checked_set(Y, tY, not_a_year, is); ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else if (modified == CharT{'E'}) ferencd@0: { ferencd@0: ios::iostate err = ios::goodbit; ferencd@0: f.get(is, nullptr, is, err, &tm, command, fmt+1); ferencd@0: if ((err & ios::failbit) == 0) ferencd@0: checked_set(Y, tm.tm_year + 1900, not_a_year, is); ferencd@0: is.setstate(err); ferencd@0: } ferencd@0: #endif ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'y': ferencd@0: if (command) ferencd@0: { ferencd@0: #if !ONLY_C_LOCALE ferencd@0: if (modified == CharT{}) ferencd@0: #endif ferencd@0: { ferencd@0: int ty = not_a_2digit_year; ferencd@0: read(is, ru{ty, 1, width == -1 ? 2u : static_cast(width)}); ferencd@0: checked_set(y, ty, not_a_2digit_year, is); ferencd@0: } ferencd@0: #if !ONLY_C_LOCALE ferencd@0: else ferencd@0: { ferencd@0: ios::iostate err = ios::goodbit; ferencd@0: f.get(is, nullptr, is, err, &tm, command, fmt+1); ferencd@0: if ((err & ios::failbit) == 0) ferencd@0: checked_set(Y, tm.tm_year + 1900, not_a_year, is); ferencd@0: is.setstate(err); ferencd@0: } ferencd@0: #endif ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'g': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: int tg = not_a_2digit_year; ferencd@0: read(is, ru{tg, 1, width == -1 ? 2u : static_cast(width)}); ferencd@0: checked_set(g, tg, not_a_2digit_year, is); ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'G': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: int tG = not_a_year; ferencd@0: read(is, rs{tG, 1, width == -1 ? 4u : static_cast(width)}); ferencd@0: checked_set(G, tG, not_a_year, is); ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'U': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: int tU = not_a_week_num; ferencd@0: read(is, ru{tU, 1, width == -1 ? 2u : static_cast(width)}); ferencd@0: checked_set(U, tU, not_a_week_num, is); ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'V': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: int tV = not_a_week_num; ferencd@0: read(is, ru{tV, 1, width == -1 ? 2u : static_cast(width)}); ferencd@0: checked_set(V, tV, not_a_week_num, is); ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'W': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: int tW = not_a_week_num; ferencd@0: read(is, ru{tW, 1, width == -1 ? 2u : static_cast(width)}); ferencd@0: checked_set(W, tW, not_a_week_num, is); ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'E': ferencd@0: case 'O': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: modified = *fmt; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case '%': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: read(is, *fmt); ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: command = fmt; ferencd@0: break; ferencd@0: case 'z': ferencd@0: if (command) ferencd@0: { ferencd@0: int tH, tM; ferencd@0: minutes toff = not_a_offset; ferencd@0: bool neg = false; ferencd@0: auto ic = is.peek(); ferencd@0: if (!Traits::eq_int_type(ic, Traits::eof())) ferencd@0: { ferencd@0: auto c = static_cast(Traits::to_char_type(ic)); ferencd@0: if (c == '-') ferencd@0: neg = true; ferencd@0: } ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: read(is, rs{tH, 2, 2}); ferencd@0: if (!is.fail()) ferencd@0: toff = hours{std::abs(tH)}; ferencd@0: if (is.good()) ferencd@0: { ferencd@0: ic = is.peek(); ferencd@0: if (!Traits::eq_int_type(ic, Traits::eof())) ferencd@0: { ferencd@0: auto c = static_cast(Traits::to_char_type(ic)); ferencd@0: if ('0' <= c && c <= '9') ferencd@0: { ferencd@0: read(is, ru{tM, 2, 2}); ferencd@0: if (!is.fail()) ferencd@0: toff += minutes{tM}; ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: read(is, rs{tH, 1, 2}); ferencd@0: if (!is.fail()) ferencd@0: toff = hours{std::abs(tH)}; ferencd@0: if (is.good()) ferencd@0: { ferencd@0: ic = is.peek(); ferencd@0: if (!Traits::eq_int_type(ic, Traits::eof())) ferencd@0: { ferencd@0: auto c = static_cast(Traits::to_char_type(ic)); ferencd@0: if (c == ':') ferencd@0: { ferencd@0: (void)is.get(); ferencd@0: read(is, ru{tM, 2, 2}); ferencd@0: if (!is.fail()) ferencd@0: toff += minutes{tM}; ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: if (neg) ferencd@0: toff = -toff; ferencd@0: checked_set(temp_offset, toff, not_a_offset, is); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: case 'Z': ferencd@0: if (command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: { ferencd@0: std::basic_string buf; ferencd@0: while (is.rdstate() == std::ios::goodbit) ferencd@0: { ferencd@0: auto i = is.rdbuf()->sgetc(); ferencd@0: if (Traits::eq_int_type(i, Traits::eof())) ferencd@0: { ferencd@0: is.setstate(ios::eofbit); ferencd@0: break; ferencd@0: } ferencd@0: auto wc = Traits::to_char_type(i); ferencd@0: auto c = static_cast(wc); ferencd@0: // is c a valid time zone name or abbreviation character? ferencd@0: if (!(CharT{1} < wc && wc < CharT{127}) || !(isalnum(c) || ferencd@0: c == '_' || c == '/' || c == '-' || c == '+')) ferencd@0: break; ferencd@0: buf.push_back(c); ferencd@0: is.rdbuf()->sbumpc(); ferencd@0: } ferencd@0: if (buf.empty()) ferencd@0: is.setstate(ios::failbit); ferencd@0: checked_set(temp_abbrev, buf, {}, is); ferencd@0: } ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: break; ferencd@0: default: ferencd@0: if (command) ferencd@0: { ferencd@0: if (width == -1 && modified == CharT{} && '0' <= *fmt && *fmt <= '9') ferencd@0: { ferencd@0: width = static_cast(*fmt) - '0'; ferencd@0: while ('0' <= fmt[1] && fmt[1] <= '9') ferencd@0: width = 10*width + static_cast(*++fmt) - '0'; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: read(is, CharT{'%'}, width, *fmt); ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified, *fmt); ferencd@0: command = nullptr; ferencd@0: width = -1; ferencd@0: modified = CharT{}; ferencd@0: } ferencd@0: } ferencd@0: else // !command ferencd@0: { ferencd@0: if (isspace(static_cast(*fmt))) ferencd@0: { ferencd@0: // space matches 0 or more white space characters ferencd@0: if (is.good()) ferencd@0: ws(is); ferencd@0: } ferencd@0: else ferencd@0: read(is, *fmt); ferencd@0: } ferencd@0: break; ferencd@0: } ferencd@0: } ferencd@0: // is.fail() || *fmt == CharT{} ferencd@0: if (is.rdstate() == ios::goodbit && command) ferencd@0: { ferencd@0: if (modified == CharT{}) ferencd@0: read(is, CharT{'%'}, width); ferencd@0: else ferencd@0: read(is, CharT{'%'}, width, modified); ferencd@0: } ferencd@0: if (!is.fail()) ferencd@0: { ferencd@0: if (y != not_a_2digit_year) ferencd@0: { ferencd@0: // Convert y and an optional C to Y ferencd@0: if (!(0 <= y && y <= 99)) ferencd@0: goto broken; ferencd@0: if (C == not_a_century) ferencd@0: { ferencd@0: if (Y == not_a_year) ferencd@0: { ferencd@0: if (y >= 69) ferencd@0: C = 19; ferencd@0: else ferencd@0: C = 20; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: C = (Y >= 0 ? Y : Y-100) / 100; ferencd@0: } ferencd@0: } ferencd@0: int tY; ferencd@0: if (C >= 0) ferencd@0: tY = 100*C + y; ferencd@0: else ferencd@0: tY = 100*(C+1) - (y == 0 ? 100 : y); ferencd@0: if (Y != not_a_year && Y != tY) ferencd@0: goto broken; ferencd@0: Y = tY; ferencd@0: } ferencd@0: if (g != not_a_2digit_year) ferencd@0: { ferencd@0: // Convert g and an optional C to G ferencd@0: if (!(0 <= g && g <= 99)) ferencd@0: goto broken; ferencd@0: if (C == not_a_century) ferencd@0: { ferencd@0: if (G == not_a_year) ferencd@0: { ferencd@0: if (g >= 69) ferencd@0: C = 19; ferencd@0: else ferencd@0: C = 20; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: C = (G >= 0 ? G : G-100) / 100; ferencd@0: } ferencd@0: } ferencd@0: int tG; ferencd@0: if (C >= 0) ferencd@0: tG = 100*C + g; ferencd@0: else ferencd@0: tG = 100*(C+1) - (g == 0 ? 100 : g); ferencd@0: if (G != not_a_year && G != tG) ferencd@0: goto broken; ferencd@0: G = tG; ferencd@0: } ferencd@0: if (Y < static_cast(year::min()) || Y > static_cast(year::max())) ferencd@0: Y = not_a_year; ferencd@0: bool computed = false; ferencd@0: if (G != not_a_year && V != not_a_week_num && wd != not_a_weekday) ferencd@0: { ferencd@0: year_month_day ymd_trial = sys_days(year{G-1}/December/Thursday[last]) + ferencd@0: (Monday-Thursday) + weeks{V-1} + ferencd@0: (weekday{static_cast(wd)}-Monday); ferencd@0: if (Y == not_a_year) ferencd@0: Y = static_cast(ymd_trial.year()); ferencd@0: else if (year{Y} != ymd_trial.year()) ferencd@0: goto broken; ferencd@0: if (m == not_a_month) ferencd@0: m = static_cast(static_cast(ymd_trial.month())); ferencd@0: else if (month(static_cast(m)) != ymd_trial.month()) ferencd@0: goto broken; ferencd@0: if (d == not_a_day) ferencd@0: d = static_cast(static_cast(ymd_trial.day())); ferencd@0: else if (day(static_cast(d)) != ymd_trial.day()) ferencd@0: goto broken; ferencd@0: computed = true; ferencd@0: } ferencd@0: if (Y != not_a_year && U != not_a_week_num && wd != not_a_weekday) ferencd@0: { ferencd@0: year_month_day ymd_trial = sys_days(year{Y}/January/Sunday[1]) + ferencd@0: weeks{U-1} + ferencd@0: (weekday{static_cast(wd)} - Sunday); ferencd@0: if (Y == not_a_year) ferencd@0: Y = static_cast(ymd_trial.year()); ferencd@0: else if (year{Y} != ymd_trial.year()) ferencd@0: goto broken; ferencd@0: if (m == not_a_month) ferencd@0: m = static_cast(static_cast(ymd_trial.month())); ferencd@0: else if (month(static_cast(m)) != ymd_trial.month()) ferencd@0: goto broken; ferencd@0: if (d == not_a_day) ferencd@0: d = static_cast(static_cast(ymd_trial.day())); ferencd@0: else if (day(static_cast(d)) != ymd_trial.day()) ferencd@0: goto broken; ferencd@0: computed = true; ferencd@0: } ferencd@0: if (Y != not_a_year && W != not_a_week_num && wd != not_a_weekday) ferencd@0: { ferencd@0: year_month_day ymd_trial = sys_days(year{Y}/January/Monday[1]) + ferencd@0: weeks{W-1} + ferencd@0: (weekday{static_cast(wd)} - Monday); ferencd@0: if (Y == not_a_year) ferencd@0: Y = static_cast(ymd_trial.year()); ferencd@0: else if (year{Y} != ymd_trial.year()) ferencd@0: goto broken; ferencd@0: if (m == not_a_month) ferencd@0: m = static_cast(static_cast(ymd_trial.month())); ferencd@0: else if (month(static_cast(m)) != ymd_trial.month()) ferencd@0: goto broken; ferencd@0: if (d == not_a_day) ferencd@0: d = static_cast(static_cast(ymd_trial.day())); ferencd@0: else if (day(static_cast(d)) != ymd_trial.day()) ferencd@0: goto broken; ferencd@0: computed = true; ferencd@0: } ferencd@0: if (j != not_a_doy && Y != not_a_year) ferencd@0: { ferencd@0: auto ymd_trial = year_month_day{local_days(year{Y}/1/1) + days{j-1}}; ferencd@0: if (m == 0) ferencd@0: m = static_cast(static_cast(ymd_trial.month())); ferencd@0: else if (month(static_cast(m)) != ymd_trial.month()) ferencd@0: goto broken; ferencd@0: if (d == 0) ferencd@0: d = static_cast(static_cast(ymd_trial.day())); ferencd@0: else if (day(static_cast(d)) != ymd_trial.day()) ferencd@0: goto broken; ferencd@0: j = not_a_doy; ferencd@0: } ferencd@0: auto ymd = year{Y}/m/d; ferencd@0: if (ymd.ok()) ferencd@0: { ferencd@0: if (wd == not_a_weekday) ferencd@0: wd = static_cast((weekday(sys_days(ymd)) - Sunday).count()); ferencd@0: else if (wd != static_cast((weekday(sys_days(ymd)) - Sunday).count())) ferencd@0: goto broken; ferencd@0: if (!computed) ferencd@0: { ferencd@0: if (G != not_a_year || V != not_a_week_num) ferencd@0: { ferencd@0: sys_days sd = ymd; ferencd@0: auto G_trial = year_month_day{sd + days{3}}.year(); ferencd@0: auto start = sys_days((G_trial - years{1})/December/Thursday[last]) + ferencd@0: (Monday - Thursday); ferencd@0: if (sd < start) ferencd@0: { ferencd@0: --G_trial; ferencd@0: if (V != not_a_week_num) ferencd@0: start = sys_days((G_trial - years{1})/December/Thursday[last]) ferencd@0: + (Monday - Thursday); ferencd@0: } ferencd@0: if (G != not_a_year && G != static_cast(G_trial)) ferencd@0: goto broken; ferencd@0: if (V != not_a_week_num) ferencd@0: { ferencd@0: auto V_trial = duration_cast(sd - start).count() + 1; ferencd@0: if (V != V_trial) ferencd@0: goto broken; ferencd@0: } ferencd@0: } ferencd@0: if (U != not_a_week_num) ferencd@0: { ferencd@0: auto start = sys_days(Sunday[1]/January/ymd.year()); ferencd@0: auto U_trial = floor(sys_days(ymd) - start).count() + 1; ferencd@0: if (U != U_trial) ferencd@0: goto broken; ferencd@0: } ferencd@0: if (W != not_a_week_num) ferencd@0: { ferencd@0: auto start = sys_days(Monday[1]/January/ymd.year()); ferencd@0: auto W_trial = floor(sys_days(ymd) - start).count() + 1; ferencd@0: if (W != W_trial) ferencd@0: goto broken; ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: fds.ymd = ymd; ferencd@0: if (I != not_a_hour_12_value) ferencd@0: { ferencd@0: if (!(1 <= I && I <= 12)) ferencd@0: goto broken; ferencd@0: if (p != not_a_ampm) ferencd@0: { ferencd@0: // p is in [0, 1] == [AM, PM] ferencd@0: // Store trial H in I ferencd@0: if (I == 12) ferencd@0: --p; ferencd@0: I += p*12; ferencd@0: // Either set H from I or make sure H and I are consistent ferencd@0: if (H == not_a_hour) ferencd@0: H = I; ferencd@0: else if (I != H) ferencd@0: goto broken; ferencd@0: } ferencd@0: else // p == not_a_ampm ferencd@0: { ferencd@0: // if H, make sure H and I could be consistent ferencd@0: if (H != not_a_hour) ferencd@0: { ferencd@0: if (I == 12) ferencd@0: { ferencd@0: if (H != 0 && H != 12) ferencd@0: goto broken; ferencd@0: } ferencd@0: else if (!(I == H || I == H+12)) ferencd@0: { ferencd@0: goto broken; ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: if (H != not_a_hour) ferencd@0: { ferencd@0: fds.has_tod = true; ferencd@0: fds.tod = hh_mm_ss{hours{H}}; ferencd@0: } ferencd@0: if (M != not_a_minute) ferencd@0: { ferencd@0: fds.has_tod = true; ferencd@0: fds.tod.m_ = minutes{M}; ferencd@0: } ferencd@0: if (s != not_a_second) ferencd@0: { ferencd@0: fds.has_tod = true; ferencd@0: fds.tod.s_ = detail::decimal_format_seconds{s}; ferencd@0: } ferencd@0: if (j != not_a_doy) ferencd@0: { ferencd@0: fds.has_tod = true; ferencd@0: fds.tod.h_ += hours{days{j}}; ferencd@0: } ferencd@0: if (wd != not_a_weekday) ferencd@0: fds.wd = weekday{static_cast(wd)}; ferencd@0: if (abbrev != nullptr) ferencd@0: *abbrev = std::move(temp_abbrev); ferencd@0: if (offset != nullptr && temp_offset != not_a_offset) ferencd@0: *offset = temp_offset; ferencd@0: } ferencd@0: return is; ferencd@0: } ferencd@0: broken: ferencd@0: is.setstate(ios::failbit); ferencd@0: return is; ferencd@0: } ferencd@0: ferencd@0: template > ferencd@0: std::basic_istream& ferencd@0: from_stream(std::basic_istream& is, const CharT* fmt, year& y, ferencd@0: std::basic_string* abbrev = nullptr, ferencd@0: std::chrono::minutes* offset = nullptr) ferencd@0: { ferencd@0: using CT = std::chrono::seconds; ferencd@0: fields fds{}; ferencd@0: from_stream(is, fmt, fds, abbrev, offset); ferencd@0: if (!fds.ymd.year().ok()) ferencd@0: is.setstate(std::ios::failbit); ferencd@0: if (!is.fail()) ferencd@0: y = fds.ymd.year(); ferencd@0: return is; ferencd@0: } ferencd@0: ferencd@0: template > ferencd@0: std::basic_istream& ferencd@0: from_stream(std::basic_istream& is, const CharT* fmt, month& m, ferencd@0: std::basic_string* abbrev = nullptr, ferencd@0: std::chrono::minutes* offset = nullptr) ferencd@0: { ferencd@0: using CT = std::chrono::seconds; ferencd@0: fields fds{}; ferencd@0: from_stream(is, fmt, fds, abbrev, offset); ferencd@0: if (!fds.ymd.month().ok()) ferencd@0: is.setstate(std::ios::failbit); ferencd@0: if (!is.fail()) ferencd@0: m = fds.ymd.month(); ferencd@0: return is; ferencd@0: } ferencd@0: ferencd@0: template > ferencd@0: std::basic_istream& ferencd@0: from_stream(std::basic_istream& is, const CharT* fmt, day& d, ferencd@0: std::basic_string* abbrev = nullptr, ferencd@0: std::chrono::minutes* offset = nullptr) ferencd@0: { ferencd@0: using CT = std::chrono::seconds; ferencd@0: fields fds{}; ferencd@0: from_stream(is, fmt, fds, abbrev, offset); ferencd@0: if (!fds.ymd.day().ok()) ferencd@0: is.setstate(std::ios::failbit); ferencd@0: if (!is.fail()) ferencd@0: d = fds.ymd.day(); ferencd@0: return is; ferencd@0: } ferencd@0: ferencd@0: template > ferencd@0: std::basic_istream& ferencd@0: from_stream(std::basic_istream& is, const CharT* fmt, weekday& wd, ferencd@0: std::basic_string* abbrev = nullptr, ferencd@0: std::chrono::minutes* offset = nullptr) ferencd@0: { ferencd@0: using CT = std::chrono::seconds; ferencd@0: fields fds{}; ferencd@0: from_stream(is, fmt, fds, abbrev, offset); ferencd@0: if (!fds.wd.ok()) ferencd@0: is.setstate(std::ios::failbit); ferencd@0: if (!is.fail()) ferencd@0: wd = fds.wd; ferencd@0: return is; ferencd@0: } ferencd@0: ferencd@0: template > ferencd@0: std::basic_istream& ferencd@0: from_stream(std::basic_istream& is, const CharT* fmt, year_month& ym, ferencd@0: std::basic_string* abbrev = nullptr, ferencd@0: std::chrono::minutes* offset = nullptr) ferencd@0: { ferencd@0: using CT = std::chrono::seconds; ferencd@0: fields fds{}; ferencd@0: from_stream(is, fmt, fds, abbrev, offset); ferencd@0: if (!fds.ymd.month().ok()) ferencd@0: is.setstate(std::ios::failbit); ferencd@0: if (!is.fail()) ferencd@0: ym = fds.ymd.year()/fds.ymd.month(); ferencd@0: return is; ferencd@0: } ferencd@0: ferencd@0: template > ferencd@0: std::basic_istream& ferencd@0: from_stream(std::basic_istream& is, const CharT* fmt, month_day& md, ferencd@0: std::basic_string* abbrev = nullptr, ferencd@0: std::chrono::minutes* offset = nullptr) ferencd@0: { ferencd@0: using CT = std::chrono::seconds; ferencd@0: fields fds{}; ferencd@0: from_stream(is, fmt, fds, abbrev, offset); ferencd@0: if (!fds.ymd.month().ok() || !fds.ymd.day().ok()) ferencd@0: is.setstate(std::ios::failbit); ferencd@0: if (!is.fail()) ferencd@0: md = fds.ymd.month()/fds.ymd.day(); ferencd@0: return is; ferencd@0: } ferencd@0: ferencd@0: template > ferencd@0: std::basic_istream& ferencd@0: from_stream(std::basic_istream& is, const CharT* fmt, ferencd@0: year_month_day& ymd, std::basic_string* abbrev = nullptr, ferencd@0: std::chrono::minutes* offset = nullptr) ferencd@0: { ferencd@0: using CT = std::chrono::seconds; ferencd@0: fields fds{}; ferencd@0: from_stream(is, fmt, fds, abbrev, offset); ferencd@0: if (!fds.ymd.ok()) ferencd@0: is.setstate(std::ios::failbit); ferencd@0: if (!is.fail()) ferencd@0: ymd = fds.ymd; ferencd@0: return is; ferencd@0: } ferencd@0: ferencd@0: template > ferencd@0: std::basic_istream& ferencd@0: from_stream(std::basic_istream& is, const CharT* fmt, ferencd@0: sys_time& tp, std::basic_string* abbrev = nullptr, ferencd@0: std::chrono::minutes* offset = nullptr) ferencd@0: { ferencd@0: using CT = typename std::common_type::type; ferencd@0: std::chrono::minutes offset_local{}; ferencd@0: auto offptr = offset ? offset : &offset_local; ferencd@0: fields fds{}; ferencd@0: fds.has_tod = true; ferencd@0: from_stream(is, fmt, fds, abbrev, offptr); ferencd@0: if (!fds.ymd.ok() || !fds.tod.in_conventional_range()) ferencd@0: is.setstate(std::ios::failbit); ferencd@0: if (!is.fail()) ferencd@0: tp = round(sys_days(fds.ymd) - *offptr + fds.tod.to_duration()); ferencd@0: return is; ferencd@0: } ferencd@0: ferencd@0: template > ferencd@0: std::basic_istream& ferencd@0: from_stream(std::basic_istream& is, const CharT* fmt, ferencd@0: local_time& tp, std::basic_string* abbrev = nullptr, ferencd@0: std::chrono::minutes* offset = nullptr) ferencd@0: { ferencd@0: using CT = typename std::common_type::type; ferencd@0: fields fds{}; ferencd@0: fds.has_tod = true; ferencd@0: from_stream(is, fmt, fds, abbrev, offset); ferencd@0: if (!fds.ymd.ok() || !fds.tod.in_conventional_range()) ferencd@0: is.setstate(std::ios::failbit); ferencd@0: if (!is.fail()) ferencd@0: tp = round(local_seconds{local_days(fds.ymd)} + fds.tod.to_duration()); ferencd@0: return is; ferencd@0: } ferencd@0: ferencd@0: template > ferencd@0: std::basic_istream& ferencd@0: from_stream(std::basic_istream& is, const CharT* fmt, ferencd@0: std::chrono::duration& d, ferencd@0: std::basic_string* abbrev = nullptr, ferencd@0: std::chrono::minutes* offset = nullptr) ferencd@0: { ferencd@0: using Duration = std::chrono::duration; ferencd@0: using CT = typename std::common_type::type; ferencd@0: fields fds{}; ferencd@0: from_stream(is, fmt, fds, abbrev, offset); ferencd@0: if (!fds.has_tod) ferencd@0: is.setstate(std::ios::failbit); ferencd@0: if (!is.fail()) ferencd@0: d = std::chrono::duration_cast(fds.tod.to_duration()); ferencd@0: return is; ferencd@0: } ferencd@0: ferencd@0: template , ferencd@0: class Alloc = std::allocator> ferencd@0: struct parse_manip ferencd@0: { ferencd@0: const std::basic_string format_; ferencd@0: Parsable& tp_; ferencd@0: std::basic_string* abbrev_; ferencd@0: std::chrono::minutes* offset_; ferencd@0: ferencd@0: public: ferencd@0: parse_manip(std::basic_string format, Parsable& tp, ferencd@0: std::basic_string* abbrev = nullptr, ferencd@0: std::chrono::minutes* offset = nullptr) ferencd@0: : format_(std::move(format)) ferencd@0: , tp_(tp) ferencd@0: , abbrev_(abbrev) ferencd@0: , offset_(offset) ferencd@0: {} ferencd@0: ferencd@0: }; ferencd@0: ferencd@0: template ferencd@0: std::basic_istream& ferencd@0: operator>>(std::basic_istream& is, ferencd@0: const parse_manip& x) ferencd@0: { ferencd@0: return from_stream(is, x.format_.c_str(), x.tp_, x.abbrev_, x.offset_); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: auto ferencd@0: parse(const std::basic_string& format, Parsable& tp) ferencd@0: -> decltype(from_stream(std::declval&>(), ferencd@0: format.c_str(), tp), ferencd@0: parse_manip{format, tp}) ferencd@0: { ferencd@0: return {format, tp}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: auto ferencd@0: parse(const std::basic_string& format, Parsable& tp, ferencd@0: std::basic_string& abbrev) ferencd@0: -> decltype(from_stream(std::declval&>(), ferencd@0: format.c_str(), tp, &abbrev), ferencd@0: parse_manip{format, tp, &abbrev}) ferencd@0: { ferencd@0: return {format, tp, &abbrev}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: auto ferencd@0: parse(const std::basic_string& format, Parsable& tp, ferencd@0: std::chrono::minutes& offset) ferencd@0: -> decltype(from_stream(std::declval&>(), ferencd@0: format.c_str(), tp, ferencd@0: std::declval*>(), ferencd@0: &offset), ferencd@0: parse_manip{format, tp, nullptr, &offset}) ferencd@0: { ferencd@0: return {format, tp, nullptr, &offset}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: auto ferencd@0: parse(const std::basic_string& format, Parsable& tp, ferencd@0: std::basic_string& abbrev, std::chrono::minutes& offset) ferencd@0: -> decltype(from_stream(std::declval&>(), ferencd@0: format.c_str(), tp, &abbrev, &offset), ferencd@0: parse_manip{format, tp, &abbrev, &offset}) ferencd@0: { ferencd@0: return {format, tp, &abbrev, &offset}; ferencd@0: } ferencd@0: ferencd@0: // const CharT* formats ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: auto ferencd@0: parse(const CharT* format, Parsable& tp) ferencd@0: -> decltype(from_stream(std::declval&>(), format, tp), ferencd@0: parse_manip{format, tp}) ferencd@0: { ferencd@0: return {format, tp}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: auto ferencd@0: parse(const CharT* format, Parsable& tp, std::basic_string& abbrev) ferencd@0: -> decltype(from_stream(std::declval&>(), format, ferencd@0: tp, &abbrev), ferencd@0: parse_manip{format, tp, &abbrev}) ferencd@0: { ferencd@0: return {format, tp, &abbrev}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: auto ferencd@0: parse(const CharT* format, Parsable& tp, std::chrono::minutes& offset) ferencd@0: -> decltype(from_stream(std::declval&>(), format, ferencd@0: tp, std::declval*>(), &offset), ferencd@0: parse_manip{format, tp, nullptr, &offset}) ferencd@0: { ferencd@0: return {format, tp, nullptr, &offset}; ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: auto ferencd@0: parse(const CharT* format, Parsable& tp, ferencd@0: std::basic_string& abbrev, std::chrono::minutes& offset) ferencd@0: -> decltype(from_stream(std::declval&>(), format, ferencd@0: tp, &abbrev, &offset), ferencd@0: parse_manip{format, tp, &abbrev, &offset}) ferencd@0: { ferencd@0: return {format, tp, &abbrev, &offset}; ferencd@0: } ferencd@0: ferencd@0: // duration streaming ferencd@0: ferencd@0: template ferencd@0: inline ferencd@0: std::basic_ostream& ferencd@0: operator<<(std::basic_ostream& os, ferencd@0: const std::chrono::duration& d) ferencd@0: { ferencd@0: return os << detail::make_string::from(d.count()) + ferencd@0: detail::get_units(typename Period::type{}); ferencd@0: } ferencd@0: ferencd@0: } // namespace date ferencd@0: ferencd@0: #ifdef _MSC_VER ferencd@0: # pragma warning(pop) ferencd@0: #endif ferencd@0: ferencd@0: #ifdef __GNUC__ ferencd@0: # pragma GCC diagnostic pop ferencd@0: #endif ferencd@0: ferencd@0: #endif // DATE_H