xref: /openbmc/bmcweb/features/redfish/include/utils/extern/date.h (revision 06a63974577071c6b4525f7eaeb7dae55b3a7a4d)
1*06a63974SEd Tanous #pragma once
21b8b02a4SEd Tanous // NOLINTBEGIN
31b8b02a4SEd Tanous // clang-format off
41b8b02a4SEd Tanous 
51b8b02a4SEd Tanous /*
61b8b02a4SEd Tanous  *  Originally sourced from
71b8b02a4SEd Tanous  *  https://github.com/HowardHinnant/date/blob/master/include/date/date.h
81b8b02a4SEd Tanous  */
91b8b02a4SEd Tanous 
101b8b02a4SEd Tanous // The MIT License (MIT)
111b8b02a4SEd Tanous //
121b8b02a4SEd Tanous // Copyright (c) 2015, 2016, 2017 Howard Hinnant
131b8b02a4SEd Tanous // Copyright (c) 2016 Adrian Colomitchi
141b8b02a4SEd Tanous // Copyright (c) 2017 Florian Dang
151b8b02a4SEd Tanous // Copyright (c) 2017 Paul Thompson
161b8b02a4SEd Tanous // Copyright (c) 2018, 2019 Tomasz Kamiński
171b8b02a4SEd Tanous // Copyright (c) 2019 Jiangang Zhuang
181b8b02a4SEd Tanous //
191b8b02a4SEd Tanous // Permission is hereby granted, free of charge, to any person obtaining a copy
201b8b02a4SEd Tanous // of this software and associated documentation files (the "Software"), to deal
211b8b02a4SEd Tanous // in the Software without restriction, including without limitation the rights
221b8b02a4SEd Tanous // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
231b8b02a4SEd Tanous // copies of the Software, and to permit persons to whom the Software is
241b8b02a4SEd Tanous // furnished to do so, subject to the following conditions:
251b8b02a4SEd Tanous //
261b8b02a4SEd Tanous // The above copyright notice and this permission notice shall be included in all
271b8b02a4SEd Tanous // copies or substantial portions of the Software.
281b8b02a4SEd Tanous //
291b8b02a4SEd Tanous // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
301b8b02a4SEd Tanous // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
311b8b02a4SEd Tanous // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
321b8b02a4SEd Tanous // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
331b8b02a4SEd Tanous // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
341b8b02a4SEd Tanous // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
351b8b02a4SEd Tanous // SOFTWARE.
361b8b02a4SEd Tanous //
371b8b02a4SEd Tanous // Our apologies.  When the previous paragraph was written, lowercase had not yet
381b8b02a4SEd Tanous // been invented (that would involve another several millennia of evolution).
391b8b02a4SEd Tanous // We did not mean to shout.
401b8b02a4SEd Tanous 
411b8b02a4SEd Tanous #ifndef HAS_STRING_VIEW
421b8b02a4SEd Tanous #  if __cplusplus >= 201703 || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
431b8b02a4SEd Tanous #    define HAS_STRING_VIEW 1
441b8b02a4SEd Tanous #  else
451b8b02a4SEd Tanous #    define HAS_STRING_VIEW 0
461b8b02a4SEd Tanous #  endif
471b8b02a4SEd Tanous #endif  // HAS_STRING_VIEW
481b8b02a4SEd Tanous 
491b8b02a4SEd Tanous #include <cassert>
501b8b02a4SEd Tanous #include <algorithm>
511b8b02a4SEd Tanous #include <cctype>
521b8b02a4SEd Tanous #include <chrono>
531b8b02a4SEd Tanous #include <climits>
541b8b02a4SEd Tanous #include <cmath>
551b8b02a4SEd Tanous #include <cstddef>
561b8b02a4SEd Tanous #include <cstdint>
571b8b02a4SEd Tanous #include <cstdlib>
581b8b02a4SEd Tanous #include <ctime>
591b8b02a4SEd Tanous #include <ios>
601b8b02a4SEd Tanous #include <istream>
611b8b02a4SEd Tanous #include <iterator>
621b8b02a4SEd Tanous #include <limits>
631b8b02a4SEd Tanous #include <locale>
641b8b02a4SEd Tanous #include <memory>
651b8b02a4SEd Tanous #include <ostream>
661b8b02a4SEd Tanous #include <ratio>
671b8b02a4SEd Tanous #include <sstream>
681b8b02a4SEd Tanous #include <stdexcept>
691b8b02a4SEd Tanous #include <string>
701b8b02a4SEd Tanous #if HAS_STRING_VIEW
711b8b02a4SEd Tanous # include <string_view>
721b8b02a4SEd Tanous #endif
731b8b02a4SEd Tanous #include <utility>
741b8b02a4SEd Tanous #include <type_traits>
751b8b02a4SEd Tanous 
761b8b02a4SEd Tanous 
771b8b02a4SEd Tanous #ifdef __GNUC__
781b8b02a4SEd Tanous # pragma GCC diagnostic push
791b8b02a4SEd Tanous # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 7)
801b8b02a4SEd Tanous #  pragma GCC diagnostic ignored "-Wpedantic"
811b8b02a4SEd Tanous #  pragma GCC diagnostic ignored "-Wconversion"
821b8b02a4SEd Tanous #  pragma GCC diagnostic ignored "-Wold-style-cast"
831b8b02a4SEd Tanous # endif
841b8b02a4SEd Tanous # if __GNUC__ < 5
851b8b02a4SEd Tanous    // GCC 4.9 Bug 61489 Wrong warning with -Wmissing-field-initializers
861b8b02a4SEd Tanous #  pragma GCC diagnostic ignored "-Wmissing-field-initializers"
871b8b02a4SEd Tanous # endif
881b8b02a4SEd Tanous #endif
891b8b02a4SEd Tanous 
901b8b02a4SEd Tanous #ifdef __clang__
911b8b02a4SEd Tanous #  pragma GCC diagnostic ignored "-Wunsafe-buffer-usage"
921b8b02a4SEd Tanous #  pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
931b8b02a4SEd Tanous #  pragma GCC diagnostic ignored "-Wold-style-cast"
941b8b02a4SEd Tanous #endif
951b8b02a4SEd Tanous 
961b8b02a4SEd Tanous #ifdef _MSC_VER
971b8b02a4SEd Tanous #   pragma warning(push)
981b8b02a4SEd Tanous // warning C4127: conditional expression is constant
991b8b02a4SEd Tanous #   pragma warning(disable : 4127)
1001b8b02a4SEd Tanous #endif
1011b8b02a4SEd Tanous 
1021b8b02a4SEd Tanous namespace date
1031b8b02a4SEd Tanous {
1041b8b02a4SEd Tanous 
1051b8b02a4SEd Tanous //---------------+
1061b8b02a4SEd Tanous // Configuration |
1071b8b02a4SEd Tanous //---------------+
1081b8b02a4SEd Tanous 
1091b8b02a4SEd Tanous #ifndef ONLY_C_LOCALE
1101b8b02a4SEd Tanous #  define ONLY_C_LOCALE 1
1111b8b02a4SEd Tanous #endif
1121b8b02a4SEd Tanous 
1131b8b02a4SEd Tanous #if defined(_MSC_VER) && (!defined(__clang__) || (_MSC_VER < 1910))
1141b8b02a4SEd Tanous // MSVC
1151b8b02a4SEd Tanous #  ifndef _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING
1161b8b02a4SEd Tanous #    define _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING
1171b8b02a4SEd Tanous #  endif
1181b8b02a4SEd Tanous #  if _MSC_VER < 1910
1191b8b02a4SEd Tanous //   before VS2017
1201b8b02a4SEd Tanous #    define CONSTDATA const
1211b8b02a4SEd Tanous #    define CONSTCD11
1221b8b02a4SEd Tanous #    define CONSTCD14
1231b8b02a4SEd Tanous #    define NOEXCEPT _NOEXCEPT
1241b8b02a4SEd Tanous #  else
1251b8b02a4SEd Tanous //   VS2017 and later
1261b8b02a4SEd Tanous #    define CONSTDATA constexpr const
1271b8b02a4SEd Tanous #    define CONSTCD11 constexpr
1281b8b02a4SEd Tanous #    define CONSTCD14 constexpr
1291b8b02a4SEd Tanous #    define NOEXCEPT noexcept
1301b8b02a4SEd Tanous #  endif
1311b8b02a4SEd Tanous 
1321b8b02a4SEd Tanous #elif defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x5150
1331b8b02a4SEd Tanous // Oracle Developer Studio 12.6 and earlier
1341b8b02a4SEd Tanous #  define CONSTDATA constexpr const
1351b8b02a4SEd Tanous #  define CONSTCD11 constexpr
1361b8b02a4SEd Tanous #  define CONSTCD14
1371b8b02a4SEd Tanous #  define NOEXCEPT noexcept
1381b8b02a4SEd Tanous 
1391b8b02a4SEd Tanous #elif __cplusplus >= 201402
1401b8b02a4SEd Tanous // C++14
1411b8b02a4SEd Tanous #  define CONSTDATA constexpr const
1421b8b02a4SEd Tanous #  define CONSTCD11 constexpr
1431b8b02a4SEd Tanous #  define CONSTCD14 constexpr
1441b8b02a4SEd Tanous #  define NOEXCEPT noexcept
1451b8b02a4SEd Tanous #else
1461b8b02a4SEd Tanous // C++11
1471b8b02a4SEd Tanous #  define CONSTDATA constexpr const
1481b8b02a4SEd Tanous #  define CONSTCD11 constexpr
1491b8b02a4SEd Tanous #  define CONSTCD14
1501b8b02a4SEd Tanous #  define NOEXCEPT noexcept
1511b8b02a4SEd Tanous #endif
1521b8b02a4SEd Tanous 
1531b8b02a4SEd Tanous #ifndef HAS_UNCAUGHT_EXCEPTIONS
1541b8b02a4SEd Tanous #  if __cplusplus >= 201703 || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
1551b8b02a4SEd Tanous #    define HAS_UNCAUGHT_EXCEPTIONS 1
1561b8b02a4SEd Tanous #  else
1571b8b02a4SEd Tanous #    define HAS_UNCAUGHT_EXCEPTIONS 0
1581b8b02a4SEd Tanous #  endif
1591b8b02a4SEd Tanous #endif  // HAS_UNCAUGHT_EXCEPTIONS
1601b8b02a4SEd Tanous 
1611b8b02a4SEd Tanous #ifndef HAS_VOID_T
1621b8b02a4SEd Tanous #  if __cplusplus >= 201703 || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
1631b8b02a4SEd Tanous #    define HAS_VOID_T 1
1641b8b02a4SEd Tanous #  else
1651b8b02a4SEd Tanous #    define HAS_VOID_T 0
1661b8b02a4SEd Tanous #  endif
1671b8b02a4SEd Tanous #endif  // HAS_VOID_T
1681b8b02a4SEd Tanous 
1691b8b02a4SEd Tanous // Protect from Oracle sun macro
1701b8b02a4SEd Tanous #ifdef sun
1711b8b02a4SEd Tanous #  undef sun
1721b8b02a4SEd Tanous #endif
1731b8b02a4SEd Tanous 
1741b8b02a4SEd Tanous // Work around for a NVCC compiler bug which causes it to fail
1751b8b02a4SEd Tanous // to compile std::ratio_{multiply,divide} when used directly
1761b8b02a4SEd Tanous // in the std::chrono::duration template instantiations below
1771b8b02a4SEd Tanous namespace detail {
1781b8b02a4SEd Tanous template <typename R1, typename R2>
1791b8b02a4SEd Tanous using ratio_multiply = decltype(std::ratio_multiply<R1, R2>{});
1801b8b02a4SEd Tanous 
1811b8b02a4SEd Tanous template <typename R1, typename R2>
1821b8b02a4SEd Tanous using ratio_divide = decltype(std::ratio_divide<R1, R2>{});
1831b8b02a4SEd Tanous }  // namespace detail
1841b8b02a4SEd Tanous 
1851b8b02a4SEd Tanous //-----------+
1861b8b02a4SEd Tanous // Interface |
1871b8b02a4SEd Tanous //-----------+
1881b8b02a4SEd Tanous 
1891b8b02a4SEd Tanous // durations
1901b8b02a4SEd Tanous 
1911b8b02a4SEd Tanous using days = std::chrono::duration
1921b8b02a4SEd Tanous     <int, detail::ratio_multiply<std::ratio<24>, std::chrono::hours::period>>;
1931b8b02a4SEd Tanous 
1941b8b02a4SEd Tanous using weeks = std::chrono::duration
1951b8b02a4SEd Tanous     <int, detail::ratio_multiply<std::ratio<7>, days::period>>;
1961b8b02a4SEd Tanous 
1971b8b02a4SEd Tanous using years = std::chrono::duration
1981b8b02a4SEd Tanous     <int, detail::ratio_multiply<std::ratio<146097, 400>, days::period>>;
1991b8b02a4SEd Tanous 
2001b8b02a4SEd Tanous using months = std::chrono::duration
2011b8b02a4SEd Tanous     <int, detail::ratio_divide<years::period, std::ratio<12>>>;
2021b8b02a4SEd Tanous 
2031b8b02a4SEd Tanous // time_point
2041b8b02a4SEd Tanous 
2051b8b02a4SEd Tanous template <class Duration>
2061b8b02a4SEd Tanous     using sys_time = std::chrono::time_point<std::chrono::system_clock, Duration>;
2071b8b02a4SEd Tanous 
2081b8b02a4SEd Tanous using sys_days    = sys_time<days>;
2091b8b02a4SEd Tanous using sys_seconds = sys_time<std::chrono::seconds>;
2101b8b02a4SEd Tanous 
2111b8b02a4SEd Tanous struct local_t {};
2121b8b02a4SEd Tanous 
2131b8b02a4SEd Tanous template <class Duration>
2141b8b02a4SEd Tanous     using local_time = std::chrono::time_point<local_t, Duration>;
2151b8b02a4SEd Tanous 
2161b8b02a4SEd Tanous using local_seconds = local_time<std::chrono::seconds>;
2171b8b02a4SEd Tanous using local_days    = local_time<days>;
2181b8b02a4SEd Tanous 
2191b8b02a4SEd Tanous // types
2201b8b02a4SEd Tanous 
2211b8b02a4SEd Tanous struct last_spec
2221b8b02a4SEd Tanous {
2231b8b02a4SEd Tanous     explicit last_spec() = default;
2241b8b02a4SEd Tanous };
2251b8b02a4SEd Tanous 
2261b8b02a4SEd Tanous class day;
2271b8b02a4SEd Tanous class month;
2281b8b02a4SEd Tanous class year;
2291b8b02a4SEd Tanous 
2301b8b02a4SEd Tanous class weekday;
2311b8b02a4SEd Tanous class weekday_indexed;
2321b8b02a4SEd Tanous class weekday_last;
2331b8b02a4SEd Tanous 
2341b8b02a4SEd Tanous class month_day;
2351b8b02a4SEd Tanous class month_day_last;
2361b8b02a4SEd Tanous class month_weekday;
2371b8b02a4SEd Tanous class month_weekday_last;
2381b8b02a4SEd Tanous 
2391b8b02a4SEd Tanous class year_month;
2401b8b02a4SEd Tanous 
2411b8b02a4SEd Tanous class year_month_day;
2421b8b02a4SEd Tanous class year_month_day_last;
2431b8b02a4SEd Tanous class year_month_weekday;
2441b8b02a4SEd Tanous class year_month_weekday_last;
2451b8b02a4SEd Tanous 
2461b8b02a4SEd Tanous // date composition operators
2471b8b02a4SEd Tanous 
2481b8b02a4SEd Tanous CONSTCD11 year_month operator/(const year& y, const month& m) NOEXCEPT;
2491b8b02a4SEd Tanous CONSTCD11 year_month operator/(const year& y, int          m) NOEXCEPT;
2501b8b02a4SEd Tanous 
2511b8b02a4SEd Tanous CONSTCD11 month_day operator/(const day& d, const month& m) NOEXCEPT;
2521b8b02a4SEd Tanous CONSTCD11 month_day operator/(const day& d, int          m) NOEXCEPT;
2531b8b02a4SEd Tanous CONSTCD11 month_day operator/(const month& m, const day& d) NOEXCEPT;
2541b8b02a4SEd Tanous CONSTCD11 month_day operator/(const month& m, int        d) NOEXCEPT;
2551b8b02a4SEd Tanous CONSTCD11 month_day operator/(int          m, const day& d) NOEXCEPT;
2561b8b02a4SEd Tanous 
2571b8b02a4SEd Tanous CONSTCD11 month_day_last operator/(const month& m, last_spec) NOEXCEPT;
2581b8b02a4SEd Tanous CONSTCD11 month_day_last operator/(int          m, last_spec) NOEXCEPT;
2591b8b02a4SEd Tanous CONSTCD11 month_day_last operator/(last_spec, const month& m) NOEXCEPT;
2601b8b02a4SEd Tanous CONSTCD11 month_day_last operator/(last_spec, int          m) NOEXCEPT;
2611b8b02a4SEd Tanous 
2621b8b02a4SEd Tanous CONSTCD11 month_weekday operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT;
2631b8b02a4SEd Tanous CONSTCD11 month_weekday operator/(int          m, const weekday_indexed& wdi) NOEXCEPT;
2641b8b02a4SEd Tanous CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT;
2651b8b02a4SEd Tanous CONSTCD11 month_weekday operator/(const weekday_indexed& wdi, int          m) NOEXCEPT;
2661b8b02a4SEd Tanous 
2671b8b02a4SEd Tanous CONSTCD11 month_weekday_last operator/(const month& m, const weekday_last& wdl) NOEXCEPT;
2681b8b02a4SEd Tanous CONSTCD11 month_weekday_last operator/(int          m, const weekday_last& wdl) NOEXCEPT;
2691b8b02a4SEd Tanous CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, const month& m) NOEXCEPT;
2701b8b02a4SEd Tanous CONSTCD11 month_weekday_last operator/(const weekday_last& wdl, int          m) NOEXCEPT;
2711b8b02a4SEd Tanous 
2721b8b02a4SEd Tanous CONSTCD11 year_month_day operator/(const year_month& ym, const day& d) NOEXCEPT;
2731b8b02a4SEd Tanous CONSTCD11 year_month_day operator/(const year_month& ym, int        d) NOEXCEPT;
2741b8b02a4SEd Tanous CONSTCD11 year_month_day operator/(const year& y, const month_day& md) NOEXCEPT;
2751b8b02a4SEd Tanous CONSTCD11 year_month_day operator/(int         y, const month_day& md) NOEXCEPT;
2761b8b02a4SEd Tanous CONSTCD11 year_month_day operator/(const month_day& md, const year& y) NOEXCEPT;
2771b8b02a4SEd Tanous CONSTCD11 year_month_day operator/(const month_day& md, int         y) NOEXCEPT;
2781b8b02a4SEd Tanous 
2791b8b02a4SEd Tanous CONSTCD11
2801b8b02a4SEd Tanous     year_month_day_last operator/(const year_month& ym,   last_spec) NOEXCEPT;
2811b8b02a4SEd Tanous CONSTCD11
2821b8b02a4SEd Tanous     year_month_day_last operator/(const year& y, const month_day_last& mdl) NOEXCEPT;
2831b8b02a4SEd Tanous CONSTCD11
2841b8b02a4SEd Tanous     year_month_day_last operator/(int         y, const month_day_last& mdl) NOEXCEPT;
2851b8b02a4SEd Tanous CONSTCD11
2861b8b02a4SEd Tanous     year_month_day_last operator/(const month_day_last& mdl, const year& y) NOEXCEPT;
2871b8b02a4SEd Tanous CONSTCD11
2881b8b02a4SEd Tanous     year_month_day_last operator/(const month_day_last& mdl, int         y) NOEXCEPT;
2891b8b02a4SEd Tanous 
2901b8b02a4SEd Tanous CONSTCD11
2911b8b02a4SEd Tanous year_month_weekday
2921b8b02a4SEd Tanous operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT;
2931b8b02a4SEd Tanous 
2941b8b02a4SEd Tanous CONSTCD11
2951b8b02a4SEd Tanous year_month_weekday
2961b8b02a4SEd Tanous operator/(const year&        y, const month_weekday&   mwd) NOEXCEPT;
2971b8b02a4SEd Tanous 
2981b8b02a4SEd Tanous CONSTCD11
2991b8b02a4SEd Tanous year_month_weekday
3001b8b02a4SEd Tanous operator/(int                y, const month_weekday&   mwd) NOEXCEPT;
3011b8b02a4SEd Tanous 
3021b8b02a4SEd Tanous CONSTCD11
3031b8b02a4SEd Tanous year_month_weekday
3041b8b02a4SEd Tanous operator/(const month_weekday& mwd, const year&          y) NOEXCEPT;
3051b8b02a4SEd Tanous 
3061b8b02a4SEd Tanous CONSTCD11
3071b8b02a4SEd Tanous year_month_weekday
3081b8b02a4SEd Tanous operator/(const month_weekday& mwd, int                  y) NOEXCEPT;
3091b8b02a4SEd Tanous 
3101b8b02a4SEd Tanous CONSTCD11
3111b8b02a4SEd Tanous year_month_weekday_last
3121b8b02a4SEd Tanous operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT;
3131b8b02a4SEd Tanous 
3141b8b02a4SEd Tanous CONSTCD11
3151b8b02a4SEd Tanous year_month_weekday_last
3161b8b02a4SEd Tanous operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT;
3171b8b02a4SEd Tanous 
3181b8b02a4SEd Tanous CONSTCD11
3191b8b02a4SEd Tanous year_month_weekday_last
3201b8b02a4SEd Tanous operator/(int         y, const month_weekday_last& mwdl) NOEXCEPT;
3211b8b02a4SEd Tanous 
3221b8b02a4SEd Tanous CONSTCD11
3231b8b02a4SEd Tanous year_month_weekday_last
3241b8b02a4SEd Tanous operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT;
3251b8b02a4SEd Tanous 
3261b8b02a4SEd Tanous CONSTCD11
3271b8b02a4SEd Tanous year_month_weekday_last
3281b8b02a4SEd Tanous operator/(const month_weekday_last& mwdl, int         y) NOEXCEPT;
3291b8b02a4SEd Tanous 
3301b8b02a4SEd Tanous // Detailed interface
3311b8b02a4SEd Tanous 
3321b8b02a4SEd Tanous // day
3331b8b02a4SEd Tanous 
3341b8b02a4SEd Tanous class day
3351b8b02a4SEd Tanous {
3361b8b02a4SEd Tanous     unsigned char d_;
3371b8b02a4SEd Tanous 
3381b8b02a4SEd Tanous public:
3391b8b02a4SEd Tanous     day() = default;
3401b8b02a4SEd Tanous     explicit CONSTCD11 day(unsigned d) NOEXCEPT;
3411b8b02a4SEd Tanous 
3421b8b02a4SEd Tanous     CONSTCD14 day& operator++()    NOEXCEPT;
3431b8b02a4SEd Tanous     CONSTCD14 day  operator++(int) NOEXCEPT;
3441b8b02a4SEd Tanous     CONSTCD14 day& operator--()    NOEXCEPT;
3451b8b02a4SEd Tanous     CONSTCD14 day  operator--(int) NOEXCEPT;
3461b8b02a4SEd Tanous 
3471b8b02a4SEd Tanous     CONSTCD14 day& operator+=(const days& d) NOEXCEPT;
3481b8b02a4SEd Tanous     CONSTCD14 day& operator-=(const days& d) NOEXCEPT;
3491b8b02a4SEd Tanous 
3501b8b02a4SEd Tanous     CONSTCD11 explicit operator unsigned() const NOEXCEPT;
3511b8b02a4SEd Tanous     CONSTCD11 bool ok() const NOEXCEPT;
3521b8b02a4SEd Tanous };
3531b8b02a4SEd Tanous 
3541b8b02a4SEd Tanous CONSTCD11 bool operator==(const day& x, const day& y) NOEXCEPT;
3551b8b02a4SEd Tanous CONSTCD11 bool operator!=(const day& x, const day& y) NOEXCEPT;
3561b8b02a4SEd Tanous CONSTCD11 bool operator< (const day& x, const day& y) NOEXCEPT;
3571b8b02a4SEd Tanous CONSTCD11 bool operator> (const day& x, const day& y) NOEXCEPT;
3581b8b02a4SEd Tanous CONSTCD11 bool operator<=(const day& x, const day& y) NOEXCEPT;
3591b8b02a4SEd Tanous CONSTCD11 bool operator>=(const day& x, const day& y) NOEXCEPT;
3601b8b02a4SEd Tanous 
3611b8b02a4SEd Tanous CONSTCD11 day  operator+(const day&  x, const days& y) NOEXCEPT;
3621b8b02a4SEd Tanous CONSTCD11 day  operator+(const days& x, const day&  y) NOEXCEPT;
3631b8b02a4SEd Tanous CONSTCD11 day  operator-(const day&  x, const days& y) NOEXCEPT;
3641b8b02a4SEd Tanous CONSTCD11 days operator-(const day&  x, const day&  y) NOEXCEPT;
3651b8b02a4SEd Tanous 
3661b8b02a4SEd Tanous template<class CharT, class Traits>
3671b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
3681b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const day& d);
3691b8b02a4SEd Tanous 
3701b8b02a4SEd Tanous // month
3711b8b02a4SEd Tanous 
3721b8b02a4SEd Tanous class month
3731b8b02a4SEd Tanous {
3741b8b02a4SEd Tanous     unsigned char m_;
3751b8b02a4SEd Tanous 
3761b8b02a4SEd Tanous public:
3771b8b02a4SEd Tanous     month() = default;
3781b8b02a4SEd Tanous     explicit CONSTCD11 month(unsigned m) NOEXCEPT;
3791b8b02a4SEd Tanous 
3801b8b02a4SEd Tanous     CONSTCD14 month& operator++()    NOEXCEPT;
3811b8b02a4SEd Tanous     CONSTCD14 month  operator++(int) NOEXCEPT;
3821b8b02a4SEd Tanous     CONSTCD14 month& operator--()    NOEXCEPT;
3831b8b02a4SEd Tanous     CONSTCD14 month  operator--(int) NOEXCEPT;
3841b8b02a4SEd Tanous 
3851b8b02a4SEd Tanous     CONSTCD14 month& operator+=(const months& m) NOEXCEPT;
3861b8b02a4SEd Tanous     CONSTCD14 month& operator-=(const months& m) NOEXCEPT;
3871b8b02a4SEd Tanous 
3881b8b02a4SEd Tanous     CONSTCD11 explicit operator unsigned() const NOEXCEPT;
3891b8b02a4SEd Tanous     CONSTCD11 bool ok() const NOEXCEPT;
3901b8b02a4SEd Tanous };
3911b8b02a4SEd Tanous 
3921b8b02a4SEd Tanous CONSTCD11 bool operator==(const month& x, const month& y) NOEXCEPT;
3931b8b02a4SEd Tanous CONSTCD11 bool operator!=(const month& x, const month& y) NOEXCEPT;
3941b8b02a4SEd Tanous CONSTCD11 bool operator< (const month& x, const month& y) NOEXCEPT;
3951b8b02a4SEd Tanous CONSTCD11 bool operator> (const month& x, const month& y) NOEXCEPT;
3961b8b02a4SEd Tanous CONSTCD11 bool operator<=(const month& x, const month& y) NOEXCEPT;
3971b8b02a4SEd Tanous CONSTCD11 bool operator>=(const month& x, const month& y) NOEXCEPT;
3981b8b02a4SEd Tanous 
3991b8b02a4SEd Tanous CONSTCD14 month  operator+(const month&  x, const months& y) NOEXCEPT;
4001b8b02a4SEd Tanous CONSTCD14 month  operator+(const months& x,  const month& y) NOEXCEPT;
4011b8b02a4SEd Tanous CONSTCD14 month  operator-(const month&  x, const months& y) NOEXCEPT;
4021b8b02a4SEd Tanous CONSTCD14 months operator-(const month&  x,  const month& y) NOEXCEPT;
4031b8b02a4SEd Tanous 
4041b8b02a4SEd Tanous template<class CharT, class Traits>
4051b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
4061b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const month& m);
4071b8b02a4SEd Tanous 
4081b8b02a4SEd Tanous // year
4091b8b02a4SEd Tanous 
4101b8b02a4SEd Tanous class year
4111b8b02a4SEd Tanous {
4121b8b02a4SEd Tanous     short y_;
4131b8b02a4SEd Tanous 
4141b8b02a4SEd Tanous public:
4151b8b02a4SEd Tanous     year() = default;
4161b8b02a4SEd Tanous     explicit CONSTCD11 year(int y) NOEXCEPT;
4171b8b02a4SEd Tanous 
4181b8b02a4SEd Tanous     CONSTCD14 year& operator++()    NOEXCEPT;
4191b8b02a4SEd Tanous     CONSTCD14 year  operator++(int) NOEXCEPT;
4201b8b02a4SEd Tanous     CONSTCD14 year& operator--()    NOEXCEPT;
4211b8b02a4SEd Tanous     CONSTCD14 year  operator--(int) NOEXCEPT;
4221b8b02a4SEd Tanous 
4231b8b02a4SEd Tanous     CONSTCD14 year& operator+=(const years& y) NOEXCEPT;
4241b8b02a4SEd Tanous     CONSTCD14 year& operator-=(const years& y) NOEXCEPT;
4251b8b02a4SEd Tanous 
4261b8b02a4SEd Tanous     CONSTCD11 year operator-() const NOEXCEPT;
4271b8b02a4SEd Tanous     CONSTCD11 year operator+() const NOEXCEPT;
4281b8b02a4SEd Tanous 
4291b8b02a4SEd Tanous     CONSTCD11 bool is_leap() const NOEXCEPT;
4301b8b02a4SEd Tanous 
4311b8b02a4SEd Tanous     CONSTCD11 explicit operator int() const NOEXCEPT;
4321b8b02a4SEd Tanous     CONSTCD11 bool ok() const NOEXCEPT;
4331b8b02a4SEd Tanous 
4341b8b02a4SEd Tanous     static CONSTCD11 year min() NOEXCEPT { return year{-32767}; }
4351b8b02a4SEd Tanous     static CONSTCD11 year max() NOEXCEPT { return year{32767}; }
4361b8b02a4SEd Tanous };
4371b8b02a4SEd Tanous 
4381b8b02a4SEd Tanous CONSTCD11 bool operator==(const year& x, const year& y) NOEXCEPT;
4391b8b02a4SEd Tanous CONSTCD11 bool operator!=(const year& x, const year& y) NOEXCEPT;
4401b8b02a4SEd Tanous CONSTCD11 bool operator< (const year& x, const year& y) NOEXCEPT;
4411b8b02a4SEd Tanous CONSTCD11 bool operator> (const year& x, const year& y) NOEXCEPT;
4421b8b02a4SEd Tanous CONSTCD11 bool operator<=(const year& x, const year& y) NOEXCEPT;
4431b8b02a4SEd Tanous CONSTCD11 bool operator>=(const year& x, const year& y) NOEXCEPT;
4441b8b02a4SEd Tanous 
4451b8b02a4SEd Tanous CONSTCD11 year  operator+(const year&  x, const years& y) NOEXCEPT;
4461b8b02a4SEd Tanous CONSTCD11 year  operator+(const years& x, const year&  y) NOEXCEPT;
4471b8b02a4SEd Tanous CONSTCD11 year  operator-(const year&  x, const years& y) NOEXCEPT;
4481b8b02a4SEd Tanous CONSTCD11 years operator-(const year&  x, const year&  y) NOEXCEPT;
4491b8b02a4SEd Tanous 
4501b8b02a4SEd Tanous template<class CharT, class Traits>
4511b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
4521b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const year& y);
4531b8b02a4SEd Tanous 
4541b8b02a4SEd Tanous // weekday
4551b8b02a4SEd Tanous 
4561b8b02a4SEd Tanous class weekday
4571b8b02a4SEd Tanous {
4581b8b02a4SEd Tanous     unsigned char wd_;
4591b8b02a4SEd Tanous public:
4601b8b02a4SEd Tanous     weekday() = default;
4611b8b02a4SEd Tanous     explicit CONSTCD11 weekday(unsigned wd) NOEXCEPT;
4621b8b02a4SEd Tanous     CONSTCD14 weekday(const sys_days& dp) NOEXCEPT;
4631b8b02a4SEd Tanous     CONSTCD14 explicit weekday(const local_days& dp) NOEXCEPT;
4641b8b02a4SEd Tanous 
4651b8b02a4SEd Tanous     CONSTCD14 weekday& operator++()    NOEXCEPT;
4661b8b02a4SEd Tanous     CONSTCD14 weekday  operator++(int) NOEXCEPT;
4671b8b02a4SEd Tanous     CONSTCD14 weekday& operator--()    NOEXCEPT;
4681b8b02a4SEd Tanous     CONSTCD14 weekday  operator--(int) NOEXCEPT;
4691b8b02a4SEd Tanous 
4701b8b02a4SEd Tanous     CONSTCD14 weekday& operator+=(const days& d) NOEXCEPT;
4711b8b02a4SEd Tanous     CONSTCD14 weekday& operator-=(const days& d) NOEXCEPT;
4721b8b02a4SEd Tanous 
4731b8b02a4SEd Tanous     CONSTCD11 bool ok() const NOEXCEPT;
4741b8b02a4SEd Tanous 
4751b8b02a4SEd Tanous     CONSTCD11 unsigned c_encoding() const NOEXCEPT;
4761b8b02a4SEd Tanous     CONSTCD11 unsigned iso_encoding() const NOEXCEPT;
4771b8b02a4SEd Tanous 
4781b8b02a4SEd Tanous     CONSTCD11 weekday_indexed operator[](unsigned index) const NOEXCEPT;
4791b8b02a4SEd Tanous     CONSTCD11 weekday_last    operator[](last_spec)      const NOEXCEPT;
4801b8b02a4SEd Tanous 
4811b8b02a4SEd Tanous private:
4821b8b02a4SEd Tanous     static CONSTCD14 unsigned char weekday_from_days(int z) NOEXCEPT;
4831b8b02a4SEd Tanous 
4841b8b02a4SEd Tanous     friend CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT;
4851b8b02a4SEd Tanous     friend CONSTCD14 days operator-(const weekday& x, const weekday& y) NOEXCEPT;
4861b8b02a4SEd Tanous     friend CONSTCD14 weekday operator+(const weekday& x, const days& y) NOEXCEPT;
4871b8b02a4SEd Tanous     template<class CharT, class Traits>
4881b8b02a4SEd Tanous         friend std::basic_ostream<CharT, Traits>&
4891b8b02a4SEd Tanous             operator<<(std::basic_ostream<CharT, Traits>& os, const weekday& wd);
4901b8b02a4SEd Tanous     friend class weekday_indexed;
4911b8b02a4SEd Tanous };
4921b8b02a4SEd Tanous 
4931b8b02a4SEd Tanous CONSTCD11 bool operator==(const weekday& x, const weekday& y) NOEXCEPT;
4941b8b02a4SEd Tanous CONSTCD11 bool operator!=(const weekday& x, const weekday& y) NOEXCEPT;
4951b8b02a4SEd Tanous 
4961b8b02a4SEd Tanous CONSTCD14 weekday operator+(const weekday& x, const days&    y) NOEXCEPT;
4971b8b02a4SEd Tanous CONSTCD14 weekday operator+(const days&    x, const weekday& y) NOEXCEPT;
4981b8b02a4SEd Tanous CONSTCD14 weekday operator-(const weekday& x, const days&    y) NOEXCEPT;
4991b8b02a4SEd Tanous CONSTCD14 days    operator-(const weekday& x, const weekday& y) NOEXCEPT;
5001b8b02a4SEd Tanous 
5011b8b02a4SEd Tanous template<class CharT, class Traits>
5021b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
5031b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const weekday& wd);
5041b8b02a4SEd Tanous 
5051b8b02a4SEd Tanous // weekday_indexed
5061b8b02a4SEd Tanous 
5071b8b02a4SEd Tanous class weekday_indexed
5081b8b02a4SEd Tanous {
5091b8b02a4SEd Tanous     unsigned char wd_    : 4;
5101b8b02a4SEd Tanous     unsigned char index_ : 4;
5111b8b02a4SEd Tanous 
5121b8b02a4SEd Tanous public:
5131b8b02a4SEd Tanous     weekday_indexed() = default;
5141b8b02a4SEd Tanous     CONSTCD11 weekday_indexed(const date::weekday& wd, unsigned index) NOEXCEPT;
5151b8b02a4SEd Tanous 
5161b8b02a4SEd Tanous     CONSTCD11 date::weekday weekday() const NOEXCEPT;
5171b8b02a4SEd Tanous     CONSTCD11 unsigned index() const NOEXCEPT;
5181b8b02a4SEd Tanous     CONSTCD11 bool ok() const NOEXCEPT;
5191b8b02a4SEd Tanous };
5201b8b02a4SEd Tanous 
5211b8b02a4SEd Tanous CONSTCD11 bool operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT;
5221b8b02a4SEd Tanous CONSTCD11 bool operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT;
5231b8b02a4SEd Tanous 
5241b8b02a4SEd Tanous template<class CharT, class Traits>
5251b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
5261b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_indexed& wdi);
5271b8b02a4SEd Tanous 
5281b8b02a4SEd Tanous // weekday_last
5291b8b02a4SEd Tanous 
5301b8b02a4SEd Tanous class weekday_last
5311b8b02a4SEd Tanous {
5321b8b02a4SEd Tanous     date::weekday wd_;
5331b8b02a4SEd Tanous 
5341b8b02a4SEd Tanous public:
5351b8b02a4SEd Tanous     explicit CONSTCD11 weekday_last(const date::weekday& wd) NOEXCEPT;
5361b8b02a4SEd Tanous 
5371b8b02a4SEd Tanous     CONSTCD11 date::weekday weekday() const NOEXCEPT;
5381b8b02a4SEd Tanous     CONSTCD11 bool ok() const NOEXCEPT;
5391b8b02a4SEd Tanous };
5401b8b02a4SEd Tanous 
5411b8b02a4SEd Tanous CONSTCD11 bool operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT;
5421b8b02a4SEd Tanous CONSTCD11 bool operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT;
5431b8b02a4SEd Tanous 
5441b8b02a4SEd Tanous template<class CharT, class Traits>
5451b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
5461b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_last& wdl);
5471b8b02a4SEd Tanous 
5481b8b02a4SEd Tanous namespace detail
5491b8b02a4SEd Tanous {
5501b8b02a4SEd Tanous 
5511b8b02a4SEd Tanous struct unspecified_month_disambiguator {};
5521b8b02a4SEd Tanous 
5531b8b02a4SEd Tanous }  // namespace detail
5541b8b02a4SEd Tanous 
5551b8b02a4SEd Tanous // year_month
5561b8b02a4SEd Tanous 
5571b8b02a4SEd Tanous class year_month
5581b8b02a4SEd Tanous {
5591b8b02a4SEd Tanous     date::year  y_;
5601b8b02a4SEd Tanous     date::month m_;
5611b8b02a4SEd Tanous 
5621b8b02a4SEd Tanous public:
5631b8b02a4SEd Tanous     year_month() = default;
5641b8b02a4SEd Tanous     CONSTCD11 year_month(const date::year& y, const date::month& m) NOEXCEPT;
5651b8b02a4SEd Tanous 
5661b8b02a4SEd Tanous     CONSTCD11 date::year  year()  const NOEXCEPT;
5671b8b02a4SEd Tanous     CONSTCD11 date::month month() const NOEXCEPT;
5681b8b02a4SEd Tanous 
5691b8b02a4SEd Tanous     template<class = detail::unspecified_month_disambiguator>
5701b8b02a4SEd Tanous     CONSTCD14 year_month& operator+=(const months& dm) NOEXCEPT;
5711b8b02a4SEd Tanous     template<class = detail::unspecified_month_disambiguator>
5721b8b02a4SEd Tanous     CONSTCD14 year_month& operator-=(const months& dm) NOEXCEPT;
5731b8b02a4SEd Tanous     CONSTCD14 year_month& operator+=(const years& dy) NOEXCEPT;
5741b8b02a4SEd Tanous     CONSTCD14 year_month& operator-=(const years& dy) NOEXCEPT;
5751b8b02a4SEd Tanous 
5761b8b02a4SEd Tanous     CONSTCD11 bool ok() const NOEXCEPT;
5771b8b02a4SEd Tanous };
5781b8b02a4SEd Tanous 
5791b8b02a4SEd Tanous CONSTCD11 bool operator==(const year_month& x, const year_month& y) NOEXCEPT;
5801b8b02a4SEd Tanous CONSTCD11 bool operator!=(const year_month& x, const year_month& y) NOEXCEPT;
5811b8b02a4SEd Tanous CONSTCD11 bool operator< (const year_month& x, const year_month& y) NOEXCEPT;
5821b8b02a4SEd Tanous CONSTCD11 bool operator> (const year_month& x, const year_month& y) NOEXCEPT;
5831b8b02a4SEd Tanous CONSTCD11 bool operator<=(const year_month& x, const year_month& y) NOEXCEPT;
5841b8b02a4SEd Tanous CONSTCD11 bool operator>=(const year_month& x, const year_month& y) NOEXCEPT;
5851b8b02a4SEd Tanous 
5861b8b02a4SEd Tanous template<class = detail::unspecified_month_disambiguator>
5871b8b02a4SEd Tanous CONSTCD14 year_month operator+(const year_month& ym, const months& dm) NOEXCEPT;
5881b8b02a4SEd Tanous template<class = detail::unspecified_month_disambiguator>
5891b8b02a4SEd Tanous CONSTCD14 year_month operator+(const months& dm, const year_month& ym) NOEXCEPT;
5901b8b02a4SEd Tanous template<class = detail::unspecified_month_disambiguator>
5911b8b02a4SEd Tanous CONSTCD14 year_month operator-(const year_month& ym, const months& dm) NOEXCEPT;
5921b8b02a4SEd Tanous 
5931b8b02a4SEd Tanous CONSTCD11 months operator-(const year_month& x, const year_month& y) NOEXCEPT;
5941b8b02a4SEd Tanous CONSTCD11 year_month operator+(const year_month& ym, const years& dy) NOEXCEPT;
5951b8b02a4SEd Tanous CONSTCD11 year_month operator+(const years& dy, const year_month& ym) NOEXCEPT;
5961b8b02a4SEd Tanous CONSTCD11 year_month operator-(const year_month& ym, const years& dy) NOEXCEPT;
5971b8b02a4SEd Tanous 
5981b8b02a4SEd Tanous template<class CharT, class Traits>
5991b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
6001b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const year_month& ym);
6011b8b02a4SEd Tanous 
6021b8b02a4SEd Tanous // month_day
6031b8b02a4SEd Tanous 
6041b8b02a4SEd Tanous class month_day
6051b8b02a4SEd Tanous {
6061b8b02a4SEd Tanous     date::month m_;
6071b8b02a4SEd Tanous     date::day   d_;
6081b8b02a4SEd Tanous 
6091b8b02a4SEd Tanous public:
6101b8b02a4SEd Tanous     month_day() = default;
6111b8b02a4SEd Tanous     CONSTCD11 month_day(const date::month& m, const date::day& d) NOEXCEPT;
6121b8b02a4SEd Tanous 
6131b8b02a4SEd Tanous     CONSTCD11 date::month month() const NOEXCEPT;
6141b8b02a4SEd Tanous     CONSTCD11 date::day   day() const NOEXCEPT;
6151b8b02a4SEd Tanous 
6161b8b02a4SEd Tanous     CONSTCD14 bool ok() const NOEXCEPT;
6171b8b02a4SEd Tanous };
6181b8b02a4SEd Tanous 
6191b8b02a4SEd Tanous CONSTCD11 bool operator==(const month_day& x, const month_day& y) NOEXCEPT;
6201b8b02a4SEd Tanous CONSTCD11 bool operator!=(const month_day& x, const month_day& y) NOEXCEPT;
6211b8b02a4SEd Tanous CONSTCD11 bool operator< (const month_day& x, const month_day& y) NOEXCEPT;
6221b8b02a4SEd Tanous CONSTCD11 bool operator> (const month_day& x, const month_day& y) NOEXCEPT;
6231b8b02a4SEd Tanous CONSTCD11 bool operator<=(const month_day& x, const month_day& y) NOEXCEPT;
6241b8b02a4SEd Tanous CONSTCD11 bool operator>=(const month_day& x, const month_day& y) NOEXCEPT;
6251b8b02a4SEd Tanous 
6261b8b02a4SEd Tanous template<class CharT, class Traits>
6271b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
6281b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const month_day& md);
6291b8b02a4SEd Tanous 
6301b8b02a4SEd Tanous // month_day_last
6311b8b02a4SEd Tanous 
6321b8b02a4SEd Tanous class month_day_last
6331b8b02a4SEd Tanous {
6341b8b02a4SEd Tanous     date::month m_;
6351b8b02a4SEd Tanous 
6361b8b02a4SEd Tanous public:
6371b8b02a4SEd Tanous     CONSTCD11 explicit month_day_last(const date::month& m) NOEXCEPT;
6381b8b02a4SEd Tanous 
6391b8b02a4SEd Tanous     CONSTCD11 date::month month() const NOEXCEPT;
6401b8b02a4SEd Tanous     CONSTCD11 bool ok() const NOEXCEPT;
6411b8b02a4SEd Tanous };
6421b8b02a4SEd Tanous 
6431b8b02a4SEd Tanous CONSTCD11 bool operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT;
6441b8b02a4SEd Tanous CONSTCD11 bool operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT;
6451b8b02a4SEd Tanous CONSTCD11 bool operator< (const month_day_last& x, const month_day_last& y) NOEXCEPT;
6461b8b02a4SEd Tanous CONSTCD11 bool operator> (const month_day_last& x, const month_day_last& y) NOEXCEPT;
6471b8b02a4SEd Tanous CONSTCD11 bool operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT;
6481b8b02a4SEd Tanous CONSTCD11 bool operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT;
6491b8b02a4SEd Tanous 
6501b8b02a4SEd Tanous template<class CharT, class Traits>
6511b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
6521b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const month_day_last& mdl);
6531b8b02a4SEd Tanous 
6541b8b02a4SEd Tanous // month_weekday
6551b8b02a4SEd Tanous 
6561b8b02a4SEd Tanous class month_weekday
6571b8b02a4SEd Tanous {
6581b8b02a4SEd Tanous     date::month           m_;
6591b8b02a4SEd Tanous     date::weekday_indexed wdi_;
6601b8b02a4SEd Tanous public:
6611b8b02a4SEd Tanous     CONSTCD11 month_weekday(const date::month& m,
6621b8b02a4SEd Tanous                             const date::weekday_indexed& wdi) NOEXCEPT;
6631b8b02a4SEd Tanous 
6641b8b02a4SEd Tanous     CONSTCD11 date::month           month()           const NOEXCEPT;
6651b8b02a4SEd Tanous     CONSTCD11 date::weekday_indexed weekday_indexed() const NOEXCEPT;
6661b8b02a4SEd Tanous 
6671b8b02a4SEd Tanous     CONSTCD11 bool ok() const NOEXCEPT;
6681b8b02a4SEd Tanous };
6691b8b02a4SEd Tanous 
6701b8b02a4SEd Tanous CONSTCD11 bool operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT;
6711b8b02a4SEd Tanous CONSTCD11 bool operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT;
6721b8b02a4SEd Tanous 
6731b8b02a4SEd Tanous template<class CharT, class Traits>
6741b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
6751b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday& mwd);
6761b8b02a4SEd Tanous 
6771b8b02a4SEd Tanous // month_weekday_last
6781b8b02a4SEd Tanous 
6791b8b02a4SEd Tanous class month_weekday_last
6801b8b02a4SEd Tanous {
6811b8b02a4SEd Tanous     date::month        m_;
6821b8b02a4SEd Tanous     date::weekday_last wdl_;
6831b8b02a4SEd Tanous 
6841b8b02a4SEd Tanous public:
6851b8b02a4SEd Tanous     CONSTCD11 month_weekday_last(const date::month& m,
6861b8b02a4SEd Tanous                                  const date::weekday_last& wd) NOEXCEPT;
6871b8b02a4SEd Tanous 
6881b8b02a4SEd Tanous     CONSTCD11 date::month        month()        const NOEXCEPT;
6891b8b02a4SEd Tanous     CONSTCD11 date::weekday_last weekday_last() const NOEXCEPT;
6901b8b02a4SEd Tanous 
6911b8b02a4SEd Tanous     CONSTCD11 bool ok() const NOEXCEPT;
6921b8b02a4SEd Tanous };
6931b8b02a4SEd Tanous 
6941b8b02a4SEd Tanous CONSTCD11
6951b8b02a4SEd Tanous     bool operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT;
6961b8b02a4SEd Tanous CONSTCD11
6971b8b02a4SEd Tanous     bool operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT;
6981b8b02a4SEd Tanous 
6991b8b02a4SEd Tanous template<class CharT, class Traits>
7001b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
7011b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday_last& mwdl);
7021b8b02a4SEd Tanous 
7031b8b02a4SEd Tanous // class year_month_day
7041b8b02a4SEd Tanous 
7051b8b02a4SEd Tanous class year_month_day
7061b8b02a4SEd Tanous {
7071b8b02a4SEd Tanous     date::year  y_;
7081b8b02a4SEd Tanous     date::month m_;
7091b8b02a4SEd Tanous     date::day   d_;
7101b8b02a4SEd Tanous 
7111b8b02a4SEd Tanous public:
7121b8b02a4SEd Tanous     year_month_day() = default;
7131b8b02a4SEd Tanous     CONSTCD11 year_month_day(const date::year& y, const date::month& m,
7141b8b02a4SEd Tanous                              const date::day& d) NOEXCEPT;
7151b8b02a4SEd Tanous     CONSTCD14 year_month_day(const year_month_day_last& ymdl) NOEXCEPT;
7161b8b02a4SEd Tanous 
7171b8b02a4SEd Tanous     CONSTCD14 year_month_day(sys_days dp) NOEXCEPT;
7181b8b02a4SEd Tanous     CONSTCD14 explicit year_month_day(local_days dp) NOEXCEPT;
7191b8b02a4SEd Tanous 
7201b8b02a4SEd Tanous     template<class = detail::unspecified_month_disambiguator>
7211b8b02a4SEd Tanous     CONSTCD14 year_month_day& operator+=(const months& m) NOEXCEPT;
7221b8b02a4SEd Tanous     template<class = detail::unspecified_month_disambiguator>
7231b8b02a4SEd Tanous     CONSTCD14 year_month_day& operator-=(const months& m) NOEXCEPT;
7241b8b02a4SEd Tanous     CONSTCD14 year_month_day& operator+=(const years& y)  NOEXCEPT;
7251b8b02a4SEd Tanous     CONSTCD14 year_month_day& operator-=(const years& y)  NOEXCEPT;
7261b8b02a4SEd Tanous 
7271b8b02a4SEd Tanous     CONSTCD11 date::year  year()  const NOEXCEPT;
7281b8b02a4SEd Tanous     CONSTCD11 date::month month() const NOEXCEPT;
7291b8b02a4SEd Tanous     CONSTCD11 date::day   day()   const NOEXCEPT;
7301b8b02a4SEd Tanous 
7311b8b02a4SEd Tanous     CONSTCD14 operator sys_days() const NOEXCEPT;
7321b8b02a4SEd Tanous     CONSTCD14 explicit operator local_days() const NOEXCEPT;
7331b8b02a4SEd Tanous     CONSTCD14 bool ok() const NOEXCEPT;
7341b8b02a4SEd Tanous 
7351b8b02a4SEd Tanous private:
7361b8b02a4SEd Tanous     static CONSTCD14 year_month_day from_days(days dp) NOEXCEPT;
7371b8b02a4SEd Tanous     CONSTCD14 days to_days() const NOEXCEPT;
7381b8b02a4SEd Tanous };
7391b8b02a4SEd Tanous 
7401b8b02a4SEd Tanous CONSTCD11 bool operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT;
7411b8b02a4SEd Tanous CONSTCD11 bool operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT;
7421b8b02a4SEd Tanous CONSTCD11 bool operator< (const year_month_day& x, const year_month_day& y) NOEXCEPT;
7431b8b02a4SEd Tanous CONSTCD11 bool operator> (const year_month_day& x, const year_month_day& y) NOEXCEPT;
7441b8b02a4SEd Tanous CONSTCD11 bool operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT;
7451b8b02a4SEd Tanous CONSTCD11 bool operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT;
7461b8b02a4SEd Tanous 
7471b8b02a4SEd Tanous template<class = detail::unspecified_month_disambiguator>
7481b8b02a4SEd Tanous CONSTCD14 year_month_day operator+(const year_month_day& ymd, const months& dm) NOEXCEPT;
7491b8b02a4SEd Tanous template<class = detail::unspecified_month_disambiguator>
7501b8b02a4SEd Tanous CONSTCD14 year_month_day operator+(const months& dm, const year_month_day& ymd) NOEXCEPT;
7511b8b02a4SEd Tanous template<class = detail::unspecified_month_disambiguator>
7521b8b02a4SEd Tanous CONSTCD14 year_month_day operator-(const year_month_day& ymd, const months& dm) NOEXCEPT;
7531b8b02a4SEd Tanous CONSTCD11 year_month_day operator+(const year_month_day& ymd, const years& dy)  NOEXCEPT;
7541b8b02a4SEd Tanous CONSTCD11 year_month_day operator+(const years& dy, const year_month_day& ymd)  NOEXCEPT;
7551b8b02a4SEd Tanous CONSTCD11 year_month_day operator-(const year_month_day& ymd, const years& dy)  NOEXCEPT;
7561b8b02a4SEd Tanous 
7571b8b02a4SEd Tanous template<class CharT, class Traits>
7581b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
7591b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day& ymd);
7601b8b02a4SEd Tanous 
7611b8b02a4SEd Tanous // year_month_day_last
7621b8b02a4SEd Tanous 
7631b8b02a4SEd Tanous class year_month_day_last
7641b8b02a4SEd Tanous {
7651b8b02a4SEd Tanous     date::year           y_;
7661b8b02a4SEd Tanous     date::month_day_last mdl_;
7671b8b02a4SEd Tanous 
7681b8b02a4SEd Tanous public:
7691b8b02a4SEd Tanous     CONSTCD11 year_month_day_last(const date::year& y,
7701b8b02a4SEd Tanous                                   const date::month_day_last& mdl) NOEXCEPT;
7711b8b02a4SEd Tanous 
7721b8b02a4SEd Tanous     template<class = detail::unspecified_month_disambiguator>
7731b8b02a4SEd Tanous     CONSTCD14 year_month_day_last& operator+=(const months& m) NOEXCEPT;
7741b8b02a4SEd Tanous     template<class = detail::unspecified_month_disambiguator>
7751b8b02a4SEd Tanous     CONSTCD14 year_month_day_last& operator-=(const months& m) NOEXCEPT;
7761b8b02a4SEd Tanous     CONSTCD14 year_month_day_last& operator+=(const years& y)  NOEXCEPT;
7771b8b02a4SEd Tanous     CONSTCD14 year_month_day_last& operator-=(const years& y)  NOEXCEPT;
7781b8b02a4SEd Tanous 
7791b8b02a4SEd Tanous     CONSTCD11 date::year           year()           const NOEXCEPT;
7801b8b02a4SEd Tanous     CONSTCD11 date::month          month()          const NOEXCEPT;
7811b8b02a4SEd Tanous     CONSTCD11 date::month_day_last month_day_last() const NOEXCEPT;
7821b8b02a4SEd Tanous     CONSTCD14 date::day            day()            const NOEXCEPT;
7831b8b02a4SEd Tanous 
7841b8b02a4SEd Tanous     CONSTCD14 operator sys_days() const NOEXCEPT;
7851b8b02a4SEd Tanous     CONSTCD14 explicit operator local_days() const NOEXCEPT;
7861b8b02a4SEd Tanous     CONSTCD11 bool ok() const NOEXCEPT;
7871b8b02a4SEd Tanous };
7881b8b02a4SEd Tanous 
7891b8b02a4SEd Tanous CONSTCD11
7901b8b02a4SEd Tanous     bool operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
7911b8b02a4SEd Tanous CONSTCD11
7921b8b02a4SEd Tanous     bool operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
7931b8b02a4SEd Tanous CONSTCD11
7941b8b02a4SEd Tanous     bool operator< (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
7951b8b02a4SEd Tanous CONSTCD11
7961b8b02a4SEd Tanous     bool operator> (const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
7971b8b02a4SEd Tanous CONSTCD11
7981b8b02a4SEd Tanous     bool operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
7991b8b02a4SEd Tanous CONSTCD11
8001b8b02a4SEd Tanous     bool operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT;
8011b8b02a4SEd Tanous 
8021b8b02a4SEd Tanous template<class = detail::unspecified_month_disambiguator>
8031b8b02a4SEd Tanous CONSTCD14
8041b8b02a4SEd Tanous year_month_day_last
8051b8b02a4SEd Tanous operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT;
8061b8b02a4SEd Tanous 
8071b8b02a4SEd Tanous template<class = detail::unspecified_month_disambiguator>
8081b8b02a4SEd Tanous CONSTCD14
8091b8b02a4SEd Tanous year_month_day_last
8101b8b02a4SEd Tanous operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT;
8111b8b02a4SEd Tanous 
8121b8b02a4SEd Tanous CONSTCD11
8131b8b02a4SEd Tanous year_month_day_last
8141b8b02a4SEd Tanous operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT;
8151b8b02a4SEd Tanous 
8161b8b02a4SEd Tanous CONSTCD11
8171b8b02a4SEd Tanous year_month_day_last
8181b8b02a4SEd Tanous operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT;
8191b8b02a4SEd Tanous 
8201b8b02a4SEd Tanous template<class = detail::unspecified_month_disambiguator>
8211b8b02a4SEd Tanous CONSTCD14
8221b8b02a4SEd Tanous year_month_day_last
8231b8b02a4SEd Tanous operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT;
8241b8b02a4SEd Tanous 
8251b8b02a4SEd Tanous CONSTCD11
8261b8b02a4SEd Tanous year_month_day_last
8271b8b02a4SEd Tanous operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT;
8281b8b02a4SEd Tanous 
8291b8b02a4SEd Tanous template<class CharT, class Traits>
8301b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
8311b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day_last& ymdl);
8321b8b02a4SEd Tanous 
8331b8b02a4SEd Tanous // year_month_weekday
8341b8b02a4SEd Tanous 
8351b8b02a4SEd Tanous class year_month_weekday
8361b8b02a4SEd Tanous {
8371b8b02a4SEd Tanous     date::year            y_;
8381b8b02a4SEd Tanous     date::month           m_;
8391b8b02a4SEd Tanous     date::weekday_indexed wdi_;
8401b8b02a4SEd Tanous 
8411b8b02a4SEd Tanous public:
8421b8b02a4SEd Tanous     year_month_weekday() = default;
8431b8b02a4SEd Tanous     CONSTCD11 year_month_weekday(const date::year& y, const date::month& m,
8441b8b02a4SEd Tanous                                    const date::weekday_indexed& wdi) NOEXCEPT;
8451b8b02a4SEd Tanous     CONSTCD14 year_month_weekday(const sys_days& dp) NOEXCEPT;
8461b8b02a4SEd Tanous     CONSTCD14 explicit year_month_weekday(const local_days& dp) NOEXCEPT;
8471b8b02a4SEd Tanous 
8481b8b02a4SEd Tanous     template<class = detail::unspecified_month_disambiguator>
8491b8b02a4SEd Tanous     CONSTCD14 year_month_weekday& operator+=(const months& m) NOEXCEPT;
8501b8b02a4SEd Tanous     template<class = detail::unspecified_month_disambiguator>
8511b8b02a4SEd Tanous     CONSTCD14 year_month_weekday& operator-=(const months& m) NOEXCEPT;
8521b8b02a4SEd Tanous     CONSTCD14 year_month_weekday& operator+=(const years& y)  NOEXCEPT;
8531b8b02a4SEd Tanous     CONSTCD14 year_month_weekday& operator-=(const years& y)  NOEXCEPT;
8541b8b02a4SEd Tanous 
8551b8b02a4SEd Tanous     CONSTCD11 date::year year() const NOEXCEPT;
8561b8b02a4SEd Tanous     CONSTCD11 date::month month() const NOEXCEPT;
8571b8b02a4SEd Tanous     CONSTCD11 date::weekday weekday() const NOEXCEPT;
8581b8b02a4SEd Tanous     CONSTCD11 unsigned index() const NOEXCEPT;
8591b8b02a4SEd Tanous     CONSTCD11 date::weekday_indexed weekday_indexed() const NOEXCEPT;
8601b8b02a4SEd Tanous 
8611b8b02a4SEd Tanous     CONSTCD14 operator sys_days() const NOEXCEPT;
8621b8b02a4SEd Tanous     CONSTCD14 explicit operator local_days() const NOEXCEPT;
8631b8b02a4SEd Tanous     CONSTCD14 bool ok() const NOEXCEPT;
8641b8b02a4SEd Tanous 
8651b8b02a4SEd Tanous private:
8661b8b02a4SEd Tanous     static CONSTCD14 year_month_weekday from_days(days dp) NOEXCEPT;
8671b8b02a4SEd Tanous     CONSTCD14 days to_days() const NOEXCEPT;
8681b8b02a4SEd Tanous };
8691b8b02a4SEd Tanous 
8701b8b02a4SEd Tanous CONSTCD11
8711b8b02a4SEd Tanous     bool operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT;
8721b8b02a4SEd Tanous CONSTCD11
8731b8b02a4SEd Tanous     bool operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT;
8741b8b02a4SEd Tanous 
8751b8b02a4SEd Tanous template<class = detail::unspecified_month_disambiguator>
8761b8b02a4SEd Tanous CONSTCD14
8771b8b02a4SEd Tanous year_month_weekday
8781b8b02a4SEd Tanous operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT;
8791b8b02a4SEd Tanous 
8801b8b02a4SEd Tanous template<class = detail::unspecified_month_disambiguator>
8811b8b02a4SEd Tanous CONSTCD14
8821b8b02a4SEd Tanous year_month_weekday
8831b8b02a4SEd Tanous operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT;
8841b8b02a4SEd Tanous 
8851b8b02a4SEd Tanous CONSTCD11
8861b8b02a4SEd Tanous year_month_weekday
8871b8b02a4SEd Tanous operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT;
8881b8b02a4SEd Tanous 
8891b8b02a4SEd Tanous CONSTCD11
8901b8b02a4SEd Tanous year_month_weekday
8911b8b02a4SEd Tanous operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT;
8921b8b02a4SEd Tanous 
8931b8b02a4SEd Tanous template<class = detail::unspecified_month_disambiguator>
8941b8b02a4SEd Tanous CONSTCD14
8951b8b02a4SEd Tanous year_month_weekday
8961b8b02a4SEd Tanous operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT;
8971b8b02a4SEd Tanous 
8981b8b02a4SEd Tanous CONSTCD11
8991b8b02a4SEd Tanous year_month_weekday
9001b8b02a4SEd Tanous operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT;
9011b8b02a4SEd Tanous 
9021b8b02a4SEd Tanous template<class CharT, class Traits>
9031b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
9041b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday& ymwdi);
9051b8b02a4SEd Tanous 
9061b8b02a4SEd Tanous // year_month_weekday_last
9071b8b02a4SEd Tanous 
9081b8b02a4SEd Tanous class year_month_weekday_last
9091b8b02a4SEd Tanous {
9101b8b02a4SEd Tanous     date::year y_;
9111b8b02a4SEd Tanous     date::month m_;
9121b8b02a4SEd Tanous     date::weekday_last wdl_;
9131b8b02a4SEd Tanous 
9141b8b02a4SEd Tanous public:
9151b8b02a4SEd Tanous     CONSTCD11 year_month_weekday_last(const date::year& y, const date::month& m,
9161b8b02a4SEd Tanous                                       const date::weekday_last& wdl) NOEXCEPT;
9171b8b02a4SEd Tanous 
9181b8b02a4SEd Tanous     template<class = detail::unspecified_month_disambiguator>
9191b8b02a4SEd Tanous     CONSTCD14 year_month_weekday_last& operator+=(const months& m) NOEXCEPT;
9201b8b02a4SEd Tanous     template<class = detail::unspecified_month_disambiguator>
9211b8b02a4SEd Tanous     CONSTCD14 year_month_weekday_last& operator-=(const months& m) NOEXCEPT;
9221b8b02a4SEd Tanous     CONSTCD14 year_month_weekday_last& operator+=(const years& y) NOEXCEPT;
9231b8b02a4SEd Tanous     CONSTCD14 year_month_weekday_last& operator-=(const years& y) NOEXCEPT;
9241b8b02a4SEd Tanous 
9251b8b02a4SEd Tanous     CONSTCD11 date::year year() const NOEXCEPT;
9261b8b02a4SEd Tanous     CONSTCD11 date::month month() const NOEXCEPT;
9271b8b02a4SEd Tanous     CONSTCD11 date::weekday weekday() const NOEXCEPT;
9281b8b02a4SEd Tanous     CONSTCD11 date::weekday_last weekday_last() const NOEXCEPT;
9291b8b02a4SEd Tanous 
9301b8b02a4SEd Tanous     CONSTCD14 operator sys_days() const NOEXCEPT;
9311b8b02a4SEd Tanous     CONSTCD14 explicit operator local_days() const NOEXCEPT;
9321b8b02a4SEd Tanous     CONSTCD11 bool ok() const NOEXCEPT;
9331b8b02a4SEd Tanous 
9341b8b02a4SEd Tanous private:
9351b8b02a4SEd Tanous     CONSTCD14 days to_days() const NOEXCEPT;
9361b8b02a4SEd Tanous };
9371b8b02a4SEd Tanous 
9381b8b02a4SEd Tanous CONSTCD11
9391b8b02a4SEd Tanous bool
9401b8b02a4SEd Tanous operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT;
9411b8b02a4SEd Tanous 
9421b8b02a4SEd Tanous CONSTCD11
9431b8b02a4SEd Tanous bool
9441b8b02a4SEd Tanous operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT;
9451b8b02a4SEd Tanous 
9461b8b02a4SEd Tanous template<class = detail::unspecified_month_disambiguator>
9471b8b02a4SEd Tanous CONSTCD14
9481b8b02a4SEd Tanous year_month_weekday_last
9491b8b02a4SEd Tanous operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT;
9501b8b02a4SEd Tanous 
9511b8b02a4SEd Tanous template<class = detail::unspecified_month_disambiguator>
9521b8b02a4SEd Tanous CONSTCD14
9531b8b02a4SEd Tanous year_month_weekday_last
9541b8b02a4SEd Tanous operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT;
9551b8b02a4SEd Tanous 
9561b8b02a4SEd Tanous CONSTCD11
9571b8b02a4SEd Tanous year_month_weekday_last
9581b8b02a4SEd Tanous operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT;
9591b8b02a4SEd Tanous 
9601b8b02a4SEd Tanous CONSTCD11
9611b8b02a4SEd Tanous year_month_weekday_last
9621b8b02a4SEd Tanous operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT;
9631b8b02a4SEd Tanous 
9641b8b02a4SEd Tanous template<class = detail::unspecified_month_disambiguator>
9651b8b02a4SEd Tanous CONSTCD14
9661b8b02a4SEd Tanous year_month_weekday_last
9671b8b02a4SEd Tanous operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT;
9681b8b02a4SEd Tanous 
9691b8b02a4SEd Tanous CONSTCD11
9701b8b02a4SEd Tanous year_month_weekday_last
9711b8b02a4SEd Tanous operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT;
9721b8b02a4SEd Tanous 
9731b8b02a4SEd Tanous template<class CharT, class Traits>
9741b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
9751b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last& ymwdl);
9761b8b02a4SEd Tanous 
9771b8b02a4SEd Tanous #if !defined(_MSC_VER) || (_MSC_VER >= 1900)
9781b8b02a4SEd Tanous inline namespace literals
9791b8b02a4SEd Tanous {
9801b8b02a4SEd Tanous 
9811b8b02a4SEd Tanous CONSTCD11 date::day  operator ""_d(unsigned long long d) NOEXCEPT;
9821b8b02a4SEd Tanous CONSTCD11 date::year operator ""_y(unsigned long long y) NOEXCEPT;
9831b8b02a4SEd Tanous 
9841b8b02a4SEd Tanous }  // inline namespace literals
9851b8b02a4SEd Tanous #endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
9861b8b02a4SEd Tanous 
9871b8b02a4SEd Tanous // CONSTDATA date::month January{1};
9881b8b02a4SEd Tanous // CONSTDATA date::month February{2};
9891b8b02a4SEd Tanous // CONSTDATA date::month March{3};
9901b8b02a4SEd Tanous // CONSTDATA date::month April{4};
9911b8b02a4SEd Tanous // CONSTDATA date::month May{5};
9921b8b02a4SEd Tanous // CONSTDATA date::month June{6};
9931b8b02a4SEd Tanous // CONSTDATA date::month July{7};
9941b8b02a4SEd Tanous // CONSTDATA date::month August{8};
9951b8b02a4SEd Tanous // CONSTDATA date::month September{9};
9961b8b02a4SEd Tanous // CONSTDATA date::month October{10};
9971b8b02a4SEd Tanous // CONSTDATA date::month November{11};
9981b8b02a4SEd Tanous // CONSTDATA date::month December{12};
9991b8b02a4SEd Tanous //
10001b8b02a4SEd Tanous // CONSTDATA date::weekday Sunday{0u};
10011b8b02a4SEd Tanous // CONSTDATA date::weekday Monday{1u};
10021b8b02a4SEd Tanous // CONSTDATA date::weekday Tuesday{2u};
10031b8b02a4SEd Tanous // CONSTDATA date::weekday Wednesday{3u};
10041b8b02a4SEd Tanous // CONSTDATA date::weekday Thursday{4u};
10051b8b02a4SEd Tanous // CONSTDATA date::weekday Friday{5u};
10061b8b02a4SEd Tanous // CONSTDATA date::weekday Saturday{6u};
10071b8b02a4SEd Tanous 
10081b8b02a4SEd Tanous #if HAS_VOID_T
10091b8b02a4SEd Tanous 
10101b8b02a4SEd Tanous template <class T, class = std::void_t<>>
10111b8b02a4SEd Tanous struct is_clock
10121b8b02a4SEd Tanous     : std::false_type
10131b8b02a4SEd Tanous {};
10141b8b02a4SEd Tanous 
10151b8b02a4SEd Tanous template <class T>
10161b8b02a4SEd Tanous struct is_clock<T, std::void_t<decltype(T::now()), typename T::rep, typename T::period,
10171b8b02a4SEd Tanous                                typename T::duration, typename T::time_point,
10181b8b02a4SEd Tanous                                decltype(T::is_steady)>>
10191b8b02a4SEd Tanous     : std::true_type
10201b8b02a4SEd Tanous {};
10211b8b02a4SEd Tanous 
10221b8b02a4SEd Tanous template<class T> inline constexpr bool is_clock_v = is_clock<T>::value;
10231b8b02a4SEd Tanous 
10241b8b02a4SEd Tanous #endif  // HAS_VOID_T
10251b8b02a4SEd Tanous 
10261b8b02a4SEd Tanous //----------------+
10271b8b02a4SEd Tanous // Implementation |
10281b8b02a4SEd Tanous //----------------+
10291b8b02a4SEd Tanous 
10301b8b02a4SEd Tanous // utilities
10311b8b02a4SEd Tanous namespace detail {
10321b8b02a4SEd Tanous 
10331b8b02a4SEd Tanous template<class CharT, class Traits = std::char_traits<CharT>>
10341b8b02a4SEd Tanous class save_istream
10351b8b02a4SEd Tanous {
10361b8b02a4SEd Tanous protected:
10371b8b02a4SEd Tanous     std::basic_ios<CharT, Traits>& is_;
10381b8b02a4SEd Tanous     CharT fill_;
10391b8b02a4SEd Tanous     std::ios::fmtflags flags_;
10401b8b02a4SEd Tanous     std::streamsize precision_;
10411b8b02a4SEd Tanous     std::streamsize width_;
10421b8b02a4SEd Tanous     std::basic_ostream<CharT, Traits>* tie_;
10431b8b02a4SEd Tanous     std::locale loc_;
10441b8b02a4SEd Tanous 
10451b8b02a4SEd Tanous public:
10461b8b02a4SEd Tanous     ~save_istream()
10471b8b02a4SEd Tanous     {
10481b8b02a4SEd Tanous         is_.fill(fill_);
10491b8b02a4SEd Tanous         is_.flags(flags_);
10501b8b02a4SEd Tanous         is_.precision(precision_);
10511b8b02a4SEd Tanous         is_.width(width_);
10521b8b02a4SEd Tanous         is_.imbue(loc_);
10531b8b02a4SEd Tanous         is_.tie(tie_);
10541b8b02a4SEd Tanous     }
10551b8b02a4SEd Tanous 
10561b8b02a4SEd Tanous     save_istream(const save_istream&) = delete;
10571b8b02a4SEd Tanous     save_istream& operator=(const save_istream&) = delete;
10581b8b02a4SEd Tanous 
10591b8b02a4SEd Tanous     explicit save_istream(std::basic_ios<CharT, Traits>& is)
10601b8b02a4SEd Tanous         : is_(is)
10611b8b02a4SEd Tanous         , fill_(is.fill())
10621b8b02a4SEd Tanous         , flags_(is.flags())
10631b8b02a4SEd Tanous         , precision_(is.precision())
10641b8b02a4SEd Tanous         , width_(is.width(0))
10651b8b02a4SEd Tanous         , tie_(is.tie(nullptr))
10661b8b02a4SEd Tanous         , loc_(is.getloc())
10671b8b02a4SEd Tanous         {
10681b8b02a4SEd Tanous             if (tie_ != nullptr)
10691b8b02a4SEd Tanous                 tie_->flush();
10701b8b02a4SEd Tanous         }
10711b8b02a4SEd Tanous };
10721b8b02a4SEd Tanous 
10731b8b02a4SEd Tanous template<class CharT, class Traits = std::char_traits<CharT>>
10741b8b02a4SEd Tanous class save_ostream
10751b8b02a4SEd Tanous     : private save_istream<CharT, Traits>
10761b8b02a4SEd Tanous {
10771b8b02a4SEd Tanous public:
10781b8b02a4SEd Tanous     ~save_ostream()
10791b8b02a4SEd Tanous     {
10801b8b02a4SEd Tanous         if ((this->flags_ & std::ios::unitbuf) &&
10811b8b02a4SEd Tanous #if HAS_UNCAUGHT_EXCEPTIONS
10821b8b02a4SEd Tanous                 std::uncaught_exceptions() == 0 &&
10831b8b02a4SEd Tanous #else
10841b8b02a4SEd Tanous                 !std::uncaught_exception() &&
10851b8b02a4SEd Tanous #endif
10861b8b02a4SEd Tanous                 this->is_.good())
10871b8b02a4SEd Tanous             this->is_.rdbuf()->pubsync();
10881b8b02a4SEd Tanous     }
10891b8b02a4SEd Tanous 
10901b8b02a4SEd Tanous     save_ostream(const save_ostream&) = delete;
10911b8b02a4SEd Tanous     save_ostream& operator=(const save_ostream&) = delete;
10921b8b02a4SEd Tanous 
10931b8b02a4SEd Tanous     explicit save_ostream(std::basic_ios<CharT, Traits>& os)
10941b8b02a4SEd Tanous         : save_istream<CharT, Traits>(os)
10951b8b02a4SEd Tanous         {
10961b8b02a4SEd Tanous         }
10971b8b02a4SEd Tanous };
10981b8b02a4SEd Tanous 
10991b8b02a4SEd Tanous template <class T>
11001b8b02a4SEd Tanous struct choose_trunc_type
11011b8b02a4SEd Tanous {
11021b8b02a4SEd Tanous     static const int digits = std::numeric_limits<T>::digits;
11031b8b02a4SEd Tanous     using type = typename std::conditional
11041b8b02a4SEd Tanous                  <
11051b8b02a4SEd Tanous                      digits < 32,
11061b8b02a4SEd Tanous                      std::int32_t,
11071b8b02a4SEd Tanous                      typename std::conditional
11081b8b02a4SEd Tanous                      <
11091b8b02a4SEd Tanous                          digits < 64,
11101b8b02a4SEd Tanous                          std::int64_t,
11111b8b02a4SEd Tanous #ifdef __SIZEOF_INT128__
11121b8b02a4SEd Tanous                          __int128
11131b8b02a4SEd Tanous #else
11141b8b02a4SEd Tanous                          std::int64_t
11151b8b02a4SEd Tanous #endif
11161b8b02a4SEd Tanous                      >::type
11171b8b02a4SEd Tanous                  >::type;
11181b8b02a4SEd Tanous };
11191b8b02a4SEd Tanous 
11201b8b02a4SEd Tanous template <class T>
11211b8b02a4SEd Tanous CONSTCD11
11221b8b02a4SEd Tanous inline
11231b8b02a4SEd Tanous typename std::enable_if
11241b8b02a4SEd Tanous <
11251b8b02a4SEd Tanous     !std::chrono::treat_as_floating_point<T>::value,
11261b8b02a4SEd Tanous     T
11271b8b02a4SEd Tanous >::type
11281b8b02a4SEd Tanous trunc(T t) NOEXCEPT
11291b8b02a4SEd Tanous {
11301b8b02a4SEd Tanous     return t;
11311b8b02a4SEd Tanous }
11321b8b02a4SEd Tanous 
11331b8b02a4SEd Tanous template <class T>
11341b8b02a4SEd Tanous CONSTCD14
11351b8b02a4SEd Tanous inline
11361b8b02a4SEd Tanous typename std::enable_if
11371b8b02a4SEd Tanous <
11381b8b02a4SEd Tanous     std::chrono::treat_as_floating_point<T>::value,
11391b8b02a4SEd Tanous     T
11401b8b02a4SEd Tanous >::type
11411b8b02a4SEd Tanous trunc(T t) NOEXCEPT
11421b8b02a4SEd Tanous {
11431b8b02a4SEd Tanous     using std::numeric_limits;
11441b8b02a4SEd Tanous     using I = typename choose_trunc_type<T>::type;
11451b8b02a4SEd Tanous     CONSTDATA auto digits = numeric_limits<T>::digits;
11461b8b02a4SEd Tanous     static_assert(digits < numeric_limits<I>::digits, "");
11471b8b02a4SEd Tanous     CONSTDATA auto max = I{1} << (digits-1);
11481b8b02a4SEd Tanous     CONSTDATA auto min = -max;
11491b8b02a4SEd Tanous     const auto negative = t < T{0};
11501b8b02a4SEd Tanous     if (min <= t && t <= max && t != 0 && t == t)
11511b8b02a4SEd Tanous     {
11521b8b02a4SEd Tanous         t = static_cast<T>(static_cast<I>(t));
11531b8b02a4SEd Tanous         if (t == 0 && negative)
11541b8b02a4SEd Tanous             t = -t;
11551b8b02a4SEd Tanous     }
11561b8b02a4SEd Tanous     return t;
11571b8b02a4SEd Tanous }
11581b8b02a4SEd Tanous 
11591b8b02a4SEd Tanous template <std::intmax_t Xp, std::intmax_t Yp>
11601b8b02a4SEd Tanous struct static_gcd
11611b8b02a4SEd Tanous {
11621b8b02a4SEd Tanous     static const std::intmax_t value = static_gcd<Yp, Xp % Yp>::value;
11631b8b02a4SEd Tanous };
11641b8b02a4SEd Tanous 
11651b8b02a4SEd Tanous template <std::intmax_t Xp>
11661b8b02a4SEd Tanous struct static_gcd<Xp, 0>
11671b8b02a4SEd Tanous {
11681b8b02a4SEd Tanous     static const std::intmax_t value = Xp;
11691b8b02a4SEd Tanous };
11701b8b02a4SEd Tanous 
11711b8b02a4SEd Tanous template <>
11721b8b02a4SEd Tanous struct static_gcd<0, 0>
11731b8b02a4SEd Tanous {
11741b8b02a4SEd Tanous     static const std::intmax_t value = 1;
11751b8b02a4SEd Tanous };
11761b8b02a4SEd Tanous 
11771b8b02a4SEd Tanous template <class R1, class R2>
11781b8b02a4SEd Tanous struct no_overflow
11791b8b02a4SEd Tanous {
11801b8b02a4SEd Tanous private:
11811b8b02a4SEd Tanous     static const std::intmax_t gcd_n1_n2 = static_gcd<R1::num, R2::num>::value;
11821b8b02a4SEd Tanous     static const std::intmax_t gcd_d1_d2 = static_gcd<R1::den, R2::den>::value;
11831b8b02a4SEd Tanous     static const std::intmax_t n1 = R1::num / gcd_n1_n2;
11841b8b02a4SEd Tanous     static const std::intmax_t d1 = R1::den / gcd_d1_d2;
11851b8b02a4SEd Tanous     static const std::intmax_t n2 = R2::num / gcd_n1_n2;
11861b8b02a4SEd Tanous     static const std::intmax_t d2 = R2::den / gcd_d1_d2;
11871b8b02a4SEd Tanous #ifdef __cpp_constexpr
11881b8b02a4SEd Tanous     static const std::intmax_t max = std::numeric_limits<std::intmax_t>::max();
11891b8b02a4SEd Tanous #else
11901b8b02a4SEd Tanous     static const std::intmax_t max = LLONG_MAX;
11911b8b02a4SEd Tanous #endif
11921b8b02a4SEd Tanous 
11931b8b02a4SEd Tanous     template <std::intmax_t Xp, std::intmax_t Yp, bool overflow>
11941b8b02a4SEd Tanous     struct mul    // overflow == false
11951b8b02a4SEd Tanous     {
11961b8b02a4SEd Tanous         static const std::intmax_t value = Xp * Yp;
11971b8b02a4SEd Tanous     };
11981b8b02a4SEd Tanous 
11991b8b02a4SEd Tanous     template <std::intmax_t Xp, std::intmax_t Yp>
12001b8b02a4SEd Tanous     struct mul<Xp, Yp, true>
12011b8b02a4SEd Tanous     {
12021b8b02a4SEd Tanous         static const std::intmax_t value = 1;
12031b8b02a4SEd Tanous     };
12041b8b02a4SEd Tanous 
12051b8b02a4SEd Tanous public:
12061b8b02a4SEd Tanous     static const bool value = (n1 <= max / d2) && (n2 <= max / d1);
12071b8b02a4SEd Tanous     typedef std::ratio<mul<n1, d2, !value>::value,
12081b8b02a4SEd Tanous                        mul<n2, d1, !value>::value> type;
12091b8b02a4SEd Tanous };
12101b8b02a4SEd Tanous 
12111b8b02a4SEd Tanous }  // detail
12121b8b02a4SEd Tanous 
12131b8b02a4SEd Tanous // trunc towards zero
12141b8b02a4SEd Tanous template <class To, class Rep, class Period>
12151b8b02a4SEd Tanous CONSTCD11
12161b8b02a4SEd Tanous inline
12171b8b02a4SEd Tanous typename std::enable_if
12181b8b02a4SEd Tanous <
12191b8b02a4SEd Tanous     detail::no_overflow<Period, typename To::period>::value,
12201b8b02a4SEd Tanous     To
12211b8b02a4SEd Tanous >::type
12221b8b02a4SEd Tanous trunc(const std::chrono::duration<Rep, Period>& d)
12231b8b02a4SEd Tanous {
12241b8b02a4SEd Tanous     return To{detail::trunc(std::chrono::duration_cast<To>(d).count())};
12251b8b02a4SEd Tanous }
12261b8b02a4SEd Tanous 
12271b8b02a4SEd Tanous template <class To, class Rep, class Period>
12281b8b02a4SEd Tanous CONSTCD11
12291b8b02a4SEd Tanous inline
12301b8b02a4SEd Tanous typename std::enable_if
12311b8b02a4SEd Tanous <
12321b8b02a4SEd Tanous     !detail::no_overflow<Period, typename To::period>::value,
12331b8b02a4SEd Tanous     To
12341b8b02a4SEd Tanous >::type
12351b8b02a4SEd Tanous trunc(const std::chrono::duration<Rep, Period>& d)
12361b8b02a4SEd Tanous {
12371b8b02a4SEd Tanous     using std::chrono::duration_cast;
12381b8b02a4SEd Tanous     using std::chrono::duration;
12391b8b02a4SEd Tanous     using rep = typename std::common_type<Rep, typename To::rep>::type;
12401b8b02a4SEd Tanous     return To{detail::trunc(duration_cast<To>(duration_cast<duration<rep>>(d)).count())};
12411b8b02a4SEd Tanous }
12421b8b02a4SEd Tanous 
12431b8b02a4SEd Tanous #ifndef HAS_CHRONO_ROUNDING
12441b8b02a4SEd Tanous #  if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023918 || (_MSC_FULL_VER >= 190000000 && defined (__clang__)))
12451b8b02a4SEd Tanous #    define HAS_CHRONO_ROUNDING 1
12461b8b02a4SEd Tanous #  elif defined(__cpp_lib_chrono) && __cplusplus > 201402 && __cpp_lib_chrono >= 201510
12471b8b02a4SEd Tanous #    define HAS_CHRONO_ROUNDING 1
12481b8b02a4SEd Tanous #  elif defined(_LIBCPP_VERSION) && __cplusplus > 201402 && _LIBCPP_VERSION >= 3800
12491b8b02a4SEd Tanous #    define HAS_CHRONO_ROUNDING 1
12501b8b02a4SEd Tanous #  else
12511b8b02a4SEd Tanous #    define HAS_CHRONO_ROUNDING 0
12521b8b02a4SEd Tanous #  endif
12531b8b02a4SEd Tanous #endif  // HAS_CHRONO_ROUNDING
12541b8b02a4SEd Tanous 
12551b8b02a4SEd Tanous #if HAS_CHRONO_ROUNDING == 0
12561b8b02a4SEd Tanous 
12571b8b02a4SEd Tanous // round down
12581b8b02a4SEd Tanous template <class To, class Rep, class Period>
12591b8b02a4SEd Tanous CONSTCD14
12601b8b02a4SEd Tanous inline
12611b8b02a4SEd Tanous typename std::enable_if
12621b8b02a4SEd Tanous <
12631b8b02a4SEd Tanous     detail::no_overflow<Period, typename To::period>::value,
12641b8b02a4SEd Tanous     To
12651b8b02a4SEd Tanous >::type
12661b8b02a4SEd Tanous floor(const std::chrono::duration<Rep, Period>& d)
12671b8b02a4SEd Tanous {
12681b8b02a4SEd Tanous     auto t = trunc<To>(d);
12691b8b02a4SEd Tanous     if (t > d)
12701b8b02a4SEd Tanous         return t - To{1};
12711b8b02a4SEd Tanous     return t;
12721b8b02a4SEd Tanous }
12731b8b02a4SEd Tanous 
12741b8b02a4SEd Tanous template <class To, class Rep, class Period>
12751b8b02a4SEd Tanous CONSTCD14
12761b8b02a4SEd Tanous inline
12771b8b02a4SEd Tanous typename std::enable_if
12781b8b02a4SEd Tanous <
12791b8b02a4SEd Tanous     !detail::no_overflow<Period, typename To::period>::value,
12801b8b02a4SEd Tanous     To
12811b8b02a4SEd Tanous >::type
12821b8b02a4SEd Tanous floor(const std::chrono::duration<Rep, Period>& d)
12831b8b02a4SEd Tanous {
12841b8b02a4SEd Tanous     using rep = typename std::common_type<Rep, typename To::rep>::type;
12851b8b02a4SEd Tanous     return floor<To>(floor<std::chrono::duration<rep>>(d));
12861b8b02a4SEd Tanous }
12871b8b02a4SEd Tanous 
12881b8b02a4SEd Tanous // round to nearest, to even on tie
12891b8b02a4SEd Tanous template <class To, class Rep, class Period>
12901b8b02a4SEd Tanous CONSTCD14
12911b8b02a4SEd Tanous inline
12921b8b02a4SEd Tanous To
12931b8b02a4SEd Tanous round(const std::chrono::duration<Rep, Period>& d)
12941b8b02a4SEd Tanous {
12951b8b02a4SEd Tanous     auto t0 = floor<To>(d);
12961b8b02a4SEd Tanous     auto t1 = t0 + To{1};
12971b8b02a4SEd Tanous     if (t1 == To{0} && t0 < To{0})
12981b8b02a4SEd Tanous         t1 = -t1;
12991b8b02a4SEd Tanous     auto diff0 = d - t0;
13001b8b02a4SEd Tanous     auto diff1 = t1 - d;
13011b8b02a4SEd Tanous     if (diff0 == diff1)
13021b8b02a4SEd Tanous     {
13031b8b02a4SEd Tanous         if (t0 - trunc<To>(t0/2)*2 == To{0})
13041b8b02a4SEd Tanous             return t0;
13051b8b02a4SEd Tanous         return t1;
13061b8b02a4SEd Tanous     }
13071b8b02a4SEd Tanous     if (diff0 < diff1)
13081b8b02a4SEd Tanous         return t0;
13091b8b02a4SEd Tanous     return t1;
13101b8b02a4SEd Tanous }
13111b8b02a4SEd Tanous 
13121b8b02a4SEd Tanous // round up
13131b8b02a4SEd Tanous template <class To, class Rep, class Period>
13141b8b02a4SEd Tanous CONSTCD14
13151b8b02a4SEd Tanous inline
13161b8b02a4SEd Tanous To
13171b8b02a4SEd Tanous ceil(const std::chrono::duration<Rep, Period>& d)
13181b8b02a4SEd Tanous {
13191b8b02a4SEd Tanous     auto t = trunc<To>(d);
13201b8b02a4SEd Tanous     if (t < d)
13211b8b02a4SEd Tanous         return t + To{1};
13221b8b02a4SEd Tanous     return t;
13231b8b02a4SEd Tanous }
13241b8b02a4SEd Tanous 
13251b8b02a4SEd Tanous template <class Rep, class Period,
13261b8b02a4SEd Tanous           class = typename std::enable_if
13271b8b02a4SEd Tanous           <
13281b8b02a4SEd Tanous               std::numeric_limits<Rep>::is_signed
13291b8b02a4SEd Tanous           >::type>
13301b8b02a4SEd Tanous CONSTCD11
13311b8b02a4SEd Tanous std::chrono::duration<Rep, Period>
13321b8b02a4SEd Tanous abs(std::chrono::duration<Rep, Period> d)
13331b8b02a4SEd Tanous {
13341b8b02a4SEd Tanous     return d >= d.zero() ? d : static_cast<decltype(d)>(-d);
13351b8b02a4SEd Tanous }
13361b8b02a4SEd Tanous 
13371b8b02a4SEd Tanous // round down
13381b8b02a4SEd Tanous template <class To, class Clock, class FromDuration>
13391b8b02a4SEd Tanous CONSTCD11
13401b8b02a4SEd Tanous inline
13411b8b02a4SEd Tanous std::chrono::time_point<Clock, To>
13421b8b02a4SEd Tanous floor(const std::chrono::time_point<Clock, FromDuration>& tp)
13431b8b02a4SEd Tanous {
13441b8b02a4SEd Tanous     using std::chrono::time_point;
13451b8b02a4SEd Tanous     return time_point<Clock, To>{date::floor<To>(tp.time_since_epoch())};
13461b8b02a4SEd Tanous }
13471b8b02a4SEd Tanous 
13481b8b02a4SEd Tanous // round to nearest, to even on tie
13491b8b02a4SEd Tanous template <class To, class Clock, class FromDuration>
13501b8b02a4SEd Tanous CONSTCD11
13511b8b02a4SEd Tanous inline
13521b8b02a4SEd Tanous std::chrono::time_point<Clock, To>
13531b8b02a4SEd Tanous round(const std::chrono::time_point<Clock, FromDuration>& tp)
13541b8b02a4SEd Tanous {
13551b8b02a4SEd Tanous     using std::chrono::time_point;
13561b8b02a4SEd Tanous     return time_point<Clock, To>{round<To>(tp.time_since_epoch())};
13571b8b02a4SEd Tanous }
13581b8b02a4SEd Tanous 
13591b8b02a4SEd Tanous // round up
13601b8b02a4SEd Tanous template <class To, class Clock, class FromDuration>
13611b8b02a4SEd Tanous CONSTCD11
13621b8b02a4SEd Tanous inline
13631b8b02a4SEd Tanous std::chrono::time_point<Clock, To>
13641b8b02a4SEd Tanous ceil(const std::chrono::time_point<Clock, FromDuration>& tp)
13651b8b02a4SEd Tanous {
13661b8b02a4SEd Tanous     using std::chrono::time_point;
13671b8b02a4SEd Tanous     return time_point<Clock, To>{ceil<To>(tp.time_since_epoch())};
13681b8b02a4SEd Tanous }
13691b8b02a4SEd Tanous 
13701b8b02a4SEd Tanous #else  // HAS_CHRONO_ROUNDING == 1
13711b8b02a4SEd Tanous 
13721b8b02a4SEd Tanous using std::chrono::floor;
13731b8b02a4SEd Tanous using std::chrono::ceil;
13741b8b02a4SEd Tanous using std::chrono::round;
13751b8b02a4SEd Tanous using std::chrono::abs;
13761b8b02a4SEd Tanous 
13771b8b02a4SEd Tanous #endif  // HAS_CHRONO_ROUNDING
13781b8b02a4SEd Tanous 
13791b8b02a4SEd Tanous namespace detail
13801b8b02a4SEd Tanous {
13811b8b02a4SEd Tanous 
13821b8b02a4SEd Tanous template <class To, class Rep, class Period>
13831b8b02a4SEd Tanous CONSTCD14
13841b8b02a4SEd Tanous inline
13851b8b02a4SEd Tanous typename std::enable_if
13861b8b02a4SEd Tanous <
13871b8b02a4SEd Tanous     !std::chrono::treat_as_floating_point<typename To::rep>::value,
13881b8b02a4SEd Tanous     To
13891b8b02a4SEd Tanous >::type
13901b8b02a4SEd Tanous round_i(const std::chrono::duration<Rep, Period>& d)
13911b8b02a4SEd Tanous {
13921b8b02a4SEd Tanous     return round<To>(d);
13931b8b02a4SEd Tanous }
13941b8b02a4SEd Tanous 
13951b8b02a4SEd Tanous template <class To, class Rep, class Period>
13961b8b02a4SEd Tanous CONSTCD14
13971b8b02a4SEd Tanous inline
13981b8b02a4SEd Tanous typename std::enable_if
13991b8b02a4SEd Tanous <
14001b8b02a4SEd Tanous     std::chrono::treat_as_floating_point<typename To::rep>::value,
14011b8b02a4SEd Tanous     To
14021b8b02a4SEd Tanous >::type
14031b8b02a4SEd Tanous round_i(const std::chrono::duration<Rep, Period>& d)
14041b8b02a4SEd Tanous {
14051b8b02a4SEd Tanous     return d;
14061b8b02a4SEd Tanous }
14071b8b02a4SEd Tanous 
14081b8b02a4SEd Tanous template <class To, class Clock, class FromDuration>
14091b8b02a4SEd Tanous CONSTCD11
14101b8b02a4SEd Tanous inline
14111b8b02a4SEd Tanous std::chrono::time_point<Clock, To>
14121b8b02a4SEd Tanous round_i(const std::chrono::time_point<Clock, FromDuration>& tp)
14131b8b02a4SEd Tanous {
14141b8b02a4SEd Tanous     using std::chrono::time_point;
14151b8b02a4SEd Tanous     return time_point<Clock, To>{round_i<To>(tp.time_since_epoch())};
14161b8b02a4SEd Tanous }
14171b8b02a4SEd Tanous 
14181b8b02a4SEd Tanous }  // detail
14191b8b02a4SEd Tanous 
14201b8b02a4SEd Tanous // trunc towards zero
14211b8b02a4SEd Tanous template <class To, class Clock, class FromDuration>
14221b8b02a4SEd Tanous CONSTCD11
14231b8b02a4SEd Tanous inline
14241b8b02a4SEd Tanous std::chrono::time_point<Clock, To>
14251b8b02a4SEd Tanous trunc(const std::chrono::time_point<Clock, FromDuration>& tp)
14261b8b02a4SEd Tanous {
14271b8b02a4SEd Tanous     using std::chrono::time_point;
14281b8b02a4SEd Tanous     return time_point<Clock, To>{trunc<To>(tp.time_since_epoch())};
14291b8b02a4SEd Tanous }
14301b8b02a4SEd Tanous 
14311b8b02a4SEd Tanous // day
14321b8b02a4SEd Tanous 
14331b8b02a4SEd Tanous CONSTCD11 inline day::day(unsigned d) NOEXCEPT : d_(static_cast<decltype(d_)>(d)) {}
14341b8b02a4SEd Tanous CONSTCD14 inline day& day::operator++() NOEXCEPT {++d_; return *this;}
14351b8b02a4SEd Tanous CONSTCD14 inline day day::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
14361b8b02a4SEd Tanous CONSTCD14 inline day& day::operator--() NOEXCEPT {--d_; return *this;}
14371b8b02a4SEd Tanous CONSTCD14 inline day day::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
14381b8b02a4SEd Tanous CONSTCD14 inline day& day::operator+=(const days& d) NOEXCEPT {*this = *this + d; return *this;}
14391b8b02a4SEd Tanous CONSTCD14 inline day& day::operator-=(const days& d) NOEXCEPT {*this = *this - d; return *this;}
14401b8b02a4SEd Tanous CONSTCD11 inline day::operator unsigned() const NOEXCEPT {return d_;}
14411b8b02a4SEd Tanous CONSTCD11 inline bool day::ok() const NOEXCEPT {return 1 <= d_ && d_ <= 31;}
14421b8b02a4SEd Tanous 
14431b8b02a4SEd Tanous CONSTCD11
14441b8b02a4SEd Tanous inline
14451b8b02a4SEd Tanous bool
14461b8b02a4SEd Tanous operator==(const day& x, const day& y) NOEXCEPT
14471b8b02a4SEd Tanous {
14481b8b02a4SEd Tanous     return static_cast<unsigned>(x) == static_cast<unsigned>(y);
14491b8b02a4SEd Tanous }
14501b8b02a4SEd Tanous 
14511b8b02a4SEd Tanous CONSTCD11
14521b8b02a4SEd Tanous inline
14531b8b02a4SEd Tanous bool
14541b8b02a4SEd Tanous operator!=(const day& x, const day& y) NOEXCEPT
14551b8b02a4SEd Tanous {
14561b8b02a4SEd Tanous     return !(x == y);
14571b8b02a4SEd Tanous }
14581b8b02a4SEd Tanous 
14591b8b02a4SEd Tanous CONSTCD11
14601b8b02a4SEd Tanous inline
14611b8b02a4SEd Tanous bool
14621b8b02a4SEd Tanous operator<(const day& x, const day& y) NOEXCEPT
14631b8b02a4SEd Tanous {
14641b8b02a4SEd Tanous     return static_cast<unsigned>(x) < static_cast<unsigned>(y);
14651b8b02a4SEd Tanous }
14661b8b02a4SEd Tanous 
14671b8b02a4SEd Tanous CONSTCD11
14681b8b02a4SEd Tanous inline
14691b8b02a4SEd Tanous bool
14701b8b02a4SEd Tanous operator>(const day& x, const day& y) NOEXCEPT
14711b8b02a4SEd Tanous {
14721b8b02a4SEd Tanous     return y < x;
14731b8b02a4SEd Tanous }
14741b8b02a4SEd Tanous 
14751b8b02a4SEd Tanous CONSTCD11
14761b8b02a4SEd Tanous inline
14771b8b02a4SEd Tanous bool
14781b8b02a4SEd Tanous operator<=(const day& x, const day& y) NOEXCEPT
14791b8b02a4SEd Tanous {
14801b8b02a4SEd Tanous     return !(y < x);
14811b8b02a4SEd Tanous }
14821b8b02a4SEd Tanous 
14831b8b02a4SEd Tanous CONSTCD11
14841b8b02a4SEd Tanous inline
14851b8b02a4SEd Tanous bool
14861b8b02a4SEd Tanous operator>=(const day& x, const day& y) NOEXCEPT
14871b8b02a4SEd Tanous {
14881b8b02a4SEd Tanous     return !(x < y);
14891b8b02a4SEd Tanous }
14901b8b02a4SEd Tanous 
14911b8b02a4SEd Tanous CONSTCD11
14921b8b02a4SEd Tanous inline
14931b8b02a4SEd Tanous days
14941b8b02a4SEd Tanous operator-(const day& x, const day& y) NOEXCEPT
14951b8b02a4SEd Tanous {
14961b8b02a4SEd Tanous     return days{static_cast<days::rep>(static_cast<unsigned>(x)
14971b8b02a4SEd Tanous                                      - static_cast<unsigned>(y))};
14981b8b02a4SEd Tanous }
14991b8b02a4SEd Tanous 
15001b8b02a4SEd Tanous CONSTCD11
15011b8b02a4SEd Tanous inline
15021b8b02a4SEd Tanous day
15031b8b02a4SEd Tanous operator+(const day& x, const days& y) NOEXCEPT
15041b8b02a4SEd Tanous {
15051b8b02a4SEd Tanous     return day{static_cast<unsigned>(x) + static_cast<unsigned>(y.count())};
15061b8b02a4SEd Tanous }
15071b8b02a4SEd Tanous 
15081b8b02a4SEd Tanous CONSTCD11
15091b8b02a4SEd Tanous inline
15101b8b02a4SEd Tanous day
15111b8b02a4SEd Tanous operator+(const days& x, const day& y) NOEXCEPT
15121b8b02a4SEd Tanous {
15131b8b02a4SEd Tanous     return y + x;
15141b8b02a4SEd Tanous }
15151b8b02a4SEd Tanous 
15161b8b02a4SEd Tanous CONSTCD11
15171b8b02a4SEd Tanous inline
15181b8b02a4SEd Tanous day
15191b8b02a4SEd Tanous operator-(const day& x, const days& y) NOEXCEPT
15201b8b02a4SEd Tanous {
15211b8b02a4SEd Tanous     return x + -y;
15221b8b02a4SEd Tanous }
15231b8b02a4SEd Tanous 
15241b8b02a4SEd Tanous namespace detail
15251b8b02a4SEd Tanous {
15261b8b02a4SEd Tanous 
15271b8b02a4SEd Tanous template<class CharT, class Traits>
15281b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
15291b8b02a4SEd Tanous low_level_fmt(std::basic_ostream<CharT, Traits>& os, const day& d)
15301b8b02a4SEd Tanous {
15311b8b02a4SEd Tanous     detail::save_ostream<CharT, Traits> _(os);
15321b8b02a4SEd Tanous     os.fill('0');
15331b8b02a4SEd Tanous     os.flags(std::ios::dec | std::ios::right);
15341b8b02a4SEd Tanous     os.width(2);
15351b8b02a4SEd Tanous     os << static_cast<unsigned>(d);
15361b8b02a4SEd Tanous     return os;
15371b8b02a4SEd Tanous }
15381b8b02a4SEd Tanous 
15391b8b02a4SEd Tanous }  // namespace detail
15401b8b02a4SEd Tanous 
15411b8b02a4SEd Tanous template<class CharT, class Traits>
15421b8b02a4SEd Tanous inline
15431b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
15441b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const day& d)
15451b8b02a4SEd Tanous {
15461b8b02a4SEd Tanous     detail::low_level_fmt(os, d);
15471b8b02a4SEd Tanous     if (!d.ok())
15481b8b02a4SEd Tanous         os << " is not a valid day";
15491b8b02a4SEd Tanous     return os;
15501b8b02a4SEd Tanous }
15511b8b02a4SEd Tanous 
15521b8b02a4SEd Tanous // month
15531b8b02a4SEd Tanous 
15541b8b02a4SEd Tanous CONSTCD11 inline month::month(unsigned m) NOEXCEPT : m_(static_cast<decltype(m_)>(m)) {}
15551b8b02a4SEd Tanous CONSTCD14 inline month& month::operator++() NOEXCEPT {*this += months{1}; return *this;}
15561b8b02a4SEd Tanous CONSTCD14 inline month month::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
15571b8b02a4SEd Tanous CONSTCD14 inline month& month::operator--() NOEXCEPT {*this -= months{1}; return *this;}
15581b8b02a4SEd Tanous CONSTCD14 inline month month::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
15591b8b02a4SEd Tanous 
15601b8b02a4SEd Tanous CONSTCD14
15611b8b02a4SEd Tanous inline
15621b8b02a4SEd Tanous month&
15631b8b02a4SEd Tanous month::operator+=(const months& m) NOEXCEPT
15641b8b02a4SEd Tanous {
15651b8b02a4SEd Tanous     *this = *this + m;
15661b8b02a4SEd Tanous     return *this;
15671b8b02a4SEd Tanous }
15681b8b02a4SEd Tanous 
15691b8b02a4SEd Tanous CONSTCD14
15701b8b02a4SEd Tanous inline
15711b8b02a4SEd Tanous month&
15721b8b02a4SEd Tanous month::operator-=(const months& m) NOEXCEPT
15731b8b02a4SEd Tanous {
15741b8b02a4SEd Tanous     *this = *this - m;
15751b8b02a4SEd Tanous     return *this;
15761b8b02a4SEd Tanous }
15771b8b02a4SEd Tanous 
15781b8b02a4SEd Tanous CONSTCD11 inline month::operator unsigned() const NOEXCEPT {return m_;}
15791b8b02a4SEd Tanous CONSTCD11 inline bool month::ok() const NOEXCEPT {return 1 <= m_ && m_ <= 12;}
15801b8b02a4SEd Tanous 
15811b8b02a4SEd Tanous CONSTCD11
15821b8b02a4SEd Tanous inline
15831b8b02a4SEd Tanous bool
15841b8b02a4SEd Tanous operator==(const month& x, const month& y) NOEXCEPT
15851b8b02a4SEd Tanous {
15861b8b02a4SEd Tanous     return static_cast<unsigned>(x) == static_cast<unsigned>(y);
15871b8b02a4SEd Tanous }
15881b8b02a4SEd Tanous 
15891b8b02a4SEd Tanous CONSTCD11
15901b8b02a4SEd Tanous inline
15911b8b02a4SEd Tanous bool
15921b8b02a4SEd Tanous operator!=(const month& x, const month& y) NOEXCEPT
15931b8b02a4SEd Tanous {
15941b8b02a4SEd Tanous     return !(x == y);
15951b8b02a4SEd Tanous }
15961b8b02a4SEd Tanous 
15971b8b02a4SEd Tanous CONSTCD11
15981b8b02a4SEd Tanous inline
15991b8b02a4SEd Tanous bool
16001b8b02a4SEd Tanous operator<(const month& x, const month& y) NOEXCEPT
16011b8b02a4SEd Tanous {
16021b8b02a4SEd Tanous     return static_cast<unsigned>(x) < static_cast<unsigned>(y);
16031b8b02a4SEd Tanous }
16041b8b02a4SEd Tanous 
16051b8b02a4SEd Tanous CONSTCD11
16061b8b02a4SEd Tanous inline
16071b8b02a4SEd Tanous bool
16081b8b02a4SEd Tanous operator>(const month& x, const month& y) NOEXCEPT
16091b8b02a4SEd Tanous {
16101b8b02a4SEd Tanous     return y < x;
16111b8b02a4SEd Tanous }
16121b8b02a4SEd Tanous 
16131b8b02a4SEd Tanous CONSTCD11
16141b8b02a4SEd Tanous inline
16151b8b02a4SEd Tanous bool
16161b8b02a4SEd Tanous operator<=(const month& x, const month& y) NOEXCEPT
16171b8b02a4SEd Tanous {
16181b8b02a4SEd Tanous     return !(y < x);
16191b8b02a4SEd Tanous }
16201b8b02a4SEd Tanous 
16211b8b02a4SEd Tanous CONSTCD11
16221b8b02a4SEd Tanous inline
16231b8b02a4SEd Tanous bool
16241b8b02a4SEd Tanous operator>=(const month& x, const month& y) NOEXCEPT
16251b8b02a4SEd Tanous {
16261b8b02a4SEd Tanous     return !(x < y);
16271b8b02a4SEd Tanous }
16281b8b02a4SEd Tanous 
16291b8b02a4SEd Tanous CONSTCD14
16301b8b02a4SEd Tanous inline
16311b8b02a4SEd Tanous months
16321b8b02a4SEd Tanous operator-(const month& x, const month& y) NOEXCEPT
16331b8b02a4SEd Tanous {
16341b8b02a4SEd Tanous     auto const d = static_cast<unsigned>(x) - static_cast<unsigned>(y);
16351b8b02a4SEd Tanous     return months(d <= 11 ? d : d + 12);
16361b8b02a4SEd Tanous }
16371b8b02a4SEd Tanous 
16381b8b02a4SEd Tanous CONSTCD14
16391b8b02a4SEd Tanous inline
16401b8b02a4SEd Tanous month
16411b8b02a4SEd Tanous operator+(const month& x, const months& y) NOEXCEPT
16421b8b02a4SEd Tanous {
16431b8b02a4SEd Tanous     auto const mu = static_cast<long long>(static_cast<unsigned>(x)) + y.count() - 1;
16441b8b02a4SEd Tanous     auto const yr = (mu >= 0 ? mu : mu-11) / 12;
16451b8b02a4SEd Tanous     return month{static_cast<unsigned>(mu - yr * 12 + 1)};
16461b8b02a4SEd Tanous }
16471b8b02a4SEd Tanous 
16481b8b02a4SEd Tanous CONSTCD14
16491b8b02a4SEd Tanous inline
16501b8b02a4SEd Tanous month
16511b8b02a4SEd Tanous operator+(const months& x, const month& y) NOEXCEPT
16521b8b02a4SEd Tanous {
16531b8b02a4SEd Tanous     return y + x;
16541b8b02a4SEd Tanous }
16551b8b02a4SEd Tanous 
16561b8b02a4SEd Tanous CONSTCD14
16571b8b02a4SEd Tanous inline
16581b8b02a4SEd Tanous month
16591b8b02a4SEd Tanous operator-(const month& x, const months& y) NOEXCEPT
16601b8b02a4SEd Tanous {
16611b8b02a4SEd Tanous     return x + -y;
16621b8b02a4SEd Tanous }
16631b8b02a4SEd Tanous 
16641b8b02a4SEd Tanous namespace detail
16651b8b02a4SEd Tanous {
16661b8b02a4SEd Tanous 
16671b8b02a4SEd Tanous template<class CharT, class Traits>
16681b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
16691b8b02a4SEd Tanous low_level_fmt(std::basic_ostream<CharT, Traits>& os, const month& m)
16701b8b02a4SEd Tanous {
16711b8b02a4SEd Tanous     if (m.ok())
16721b8b02a4SEd Tanous     {
16731b8b02a4SEd Tanous         CharT fmt[] = {'%', 'b', 0};
16741b8b02a4SEd Tanous         os << format(os.getloc(), fmt, m);
16751b8b02a4SEd Tanous     }
16761b8b02a4SEd Tanous     else
16771b8b02a4SEd Tanous         os << static_cast<unsigned>(m);
16781b8b02a4SEd Tanous     return os;
16791b8b02a4SEd Tanous }
16801b8b02a4SEd Tanous 
16811b8b02a4SEd Tanous }  // namespace detail
16821b8b02a4SEd Tanous 
16831b8b02a4SEd Tanous template<class CharT, class Traits>
16841b8b02a4SEd Tanous inline
16851b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
16861b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const month& m)
16871b8b02a4SEd Tanous {
16881b8b02a4SEd Tanous     detail::low_level_fmt(os, m);
16891b8b02a4SEd Tanous     if (!m.ok())
16901b8b02a4SEd Tanous         os << " is not a valid month";
16911b8b02a4SEd Tanous     return os;
16921b8b02a4SEd Tanous }
16931b8b02a4SEd Tanous 
16941b8b02a4SEd Tanous // year
16951b8b02a4SEd Tanous 
16961b8b02a4SEd Tanous CONSTCD11 inline year::year(int y) NOEXCEPT : y_(static_cast<decltype(y_)>(y)) {}
16971b8b02a4SEd Tanous CONSTCD14 inline year& year::operator++() NOEXCEPT {++y_; return *this;}
16981b8b02a4SEd Tanous CONSTCD14 inline year year::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
16991b8b02a4SEd Tanous CONSTCD14 inline year& year::operator--() NOEXCEPT {--y_; return *this;}
17001b8b02a4SEd Tanous CONSTCD14 inline year year::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
17011b8b02a4SEd Tanous CONSTCD14 inline year& year::operator+=(const years& y) NOEXCEPT {*this = *this + y; return *this;}
17021b8b02a4SEd Tanous CONSTCD14 inline year& year::operator-=(const years& y) NOEXCEPT {*this = *this - y; return *this;}
17031b8b02a4SEd Tanous CONSTCD11 inline year year::operator-() const NOEXCEPT {return year{-y_};}
17041b8b02a4SEd Tanous CONSTCD11 inline year year::operator+() const NOEXCEPT {return *this;}
17051b8b02a4SEd Tanous 
17061b8b02a4SEd Tanous CONSTCD11
17071b8b02a4SEd Tanous inline
17081b8b02a4SEd Tanous bool
17091b8b02a4SEd Tanous year::is_leap() const NOEXCEPT
17101b8b02a4SEd Tanous {
17111b8b02a4SEd Tanous     return y_ % 4 == 0 && (y_ % 100 != 0 || y_ % 400 == 0);
17121b8b02a4SEd Tanous }
17131b8b02a4SEd Tanous 
17141b8b02a4SEd Tanous CONSTCD11 inline year::operator int() const NOEXCEPT {return y_;}
17151b8b02a4SEd Tanous 
17161b8b02a4SEd Tanous CONSTCD11
17171b8b02a4SEd Tanous inline
17181b8b02a4SEd Tanous bool
17191b8b02a4SEd Tanous year::ok() const NOEXCEPT
17201b8b02a4SEd Tanous {
17211b8b02a4SEd Tanous     return y_ != std::numeric_limits<short>::min();
17221b8b02a4SEd Tanous }
17231b8b02a4SEd Tanous 
17241b8b02a4SEd Tanous CONSTCD11
17251b8b02a4SEd Tanous inline
17261b8b02a4SEd Tanous bool
17271b8b02a4SEd Tanous operator==(const year& x, const year& y) NOEXCEPT
17281b8b02a4SEd Tanous {
17291b8b02a4SEd Tanous     return static_cast<int>(x) == static_cast<int>(y);
17301b8b02a4SEd Tanous }
17311b8b02a4SEd Tanous 
17321b8b02a4SEd Tanous CONSTCD11
17331b8b02a4SEd Tanous inline
17341b8b02a4SEd Tanous bool
17351b8b02a4SEd Tanous operator!=(const year& x, const year& y) NOEXCEPT
17361b8b02a4SEd Tanous {
17371b8b02a4SEd Tanous     return !(x == y);
17381b8b02a4SEd Tanous }
17391b8b02a4SEd Tanous 
17401b8b02a4SEd Tanous CONSTCD11
17411b8b02a4SEd Tanous inline
17421b8b02a4SEd Tanous bool
17431b8b02a4SEd Tanous operator<(const year& x, const year& y) NOEXCEPT
17441b8b02a4SEd Tanous {
17451b8b02a4SEd Tanous     return static_cast<int>(x) < static_cast<int>(y);
17461b8b02a4SEd Tanous }
17471b8b02a4SEd Tanous 
17481b8b02a4SEd Tanous CONSTCD11
17491b8b02a4SEd Tanous inline
17501b8b02a4SEd Tanous bool
17511b8b02a4SEd Tanous operator>(const year& x, const year& y) NOEXCEPT
17521b8b02a4SEd Tanous {
17531b8b02a4SEd Tanous     return y < x;
17541b8b02a4SEd Tanous }
17551b8b02a4SEd Tanous 
17561b8b02a4SEd Tanous CONSTCD11
17571b8b02a4SEd Tanous inline
17581b8b02a4SEd Tanous bool
17591b8b02a4SEd Tanous operator<=(const year& x, const year& y) NOEXCEPT
17601b8b02a4SEd Tanous {
17611b8b02a4SEd Tanous     return !(y < x);
17621b8b02a4SEd Tanous }
17631b8b02a4SEd Tanous 
17641b8b02a4SEd Tanous CONSTCD11
17651b8b02a4SEd Tanous inline
17661b8b02a4SEd Tanous bool
17671b8b02a4SEd Tanous operator>=(const year& x, const year& y) NOEXCEPT
17681b8b02a4SEd Tanous {
17691b8b02a4SEd Tanous     return !(x < y);
17701b8b02a4SEd Tanous }
17711b8b02a4SEd Tanous 
17721b8b02a4SEd Tanous CONSTCD11
17731b8b02a4SEd Tanous inline
17741b8b02a4SEd Tanous years
17751b8b02a4SEd Tanous operator-(const year& x, const year& y) NOEXCEPT
17761b8b02a4SEd Tanous {
17771b8b02a4SEd Tanous     return years{static_cast<int>(x) - static_cast<int>(y)};
17781b8b02a4SEd Tanous }
17791b8b02a4SEd Tanous 
17801b8b02a4SEd Tanous CONSTCD11
17811b8b02a4SEd Tanous inline
17821b8b02a4SEd Tanous year
17831b8b02a4SEd Tanous operator+(const year& x, const years& y) NOEXCEPT
17841b8b02a4SEd Tanous {
17851b8b02a4SEd Tanous     return year{static_cast<int>(x) + y.count()};
17861b8b02a4SEd Tanous }
17871b8b02a4SEd Tanous 
17881b8b02a4SEd Tanous CONSTCD11
17891b8b02a4SEd Tanous inline
17901b8b02a4SEd Tanous year
17911b8b02a4SEd Tanous operator+(const years& x, const year& y) NOEXCEPT
17921b8b02a4SEd Tanous {
17931b8b02a4SEd Tanous     return y + x;
17941b8b02a4SEd Tanous }
17951b8b02a4SEd Tanous 
17961b8b02a4SEd Tanous CONSTCD11
17971b8b02a4SEd Tanous inline
17981b8b02a4SEd Tanous year
17991b8b02a4SEd Tanous operator-(const year& x, const years& y) NOEXCEPT
18001b8b02a4SEd Tanous {
18011b8b02a4SEd Tanous     return year{static_cast<int>(x) - y.count()};
18021b8b02a4SEd Tanous }
18031b8b02a4SEd Tanous 
18041b8b02a4SEd Tanous namespace detail
18051b8b02a4SEd Tanous {
18061b8b02a4SEd Tanous 
18071b8b02a4SEd Tanous template<class CharT, class Traits>
18081b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
18091b8b02a4SEd Tanous low_level_fmt(std::basic_ostream<CharT, Traits>& os, const year& y)
18101b8b02a4SEd Tanous {
18111b8b02a4SEd Tanous     detail::save_ostream<CharT, Traits> _(os);
18121b8b02a4SEd Tanous     os.fill('0');
18131b8b02a4SEd Tanous     os.flags(std::ios::dec | std::ios::internal);
18141b8b02a4SEd Tanous     os.width(4 + (y < year{0}));
18151b8b02a4SEd Tanous     os.imbue(std::locale::classic());
18161b8b02a4SEd Tanous     os << static_cast<int>(y);
18171b8b02a4SEd Tanous     return os;
18181b8b02a4SEd Tanous }
18191b8b02a4SEd Tanous 
18201b8b02a4SEd Tanous }  // namespace detail
18211b8b02a4SEd Tanous 
18221b8b02a4SEd Tanous template<class CharT, class Traits>
18231b8b02a4SEd Tanous inline
18241b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
18251b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const year& y)
18261b8b02a4SEd Tanous {
18271b8b02a4SEd Tanous     detail::low_level_fmt(os, y);
18281b8b02a4SEd Tanous     if (!y.ok())
18291b8b02a4SEd Tanous         os << " is not a valid year";
18301b8b02a4SEd Tanous     return os;
18311b8b02a4SEd Tanous }
18321b8b02a4SEd Tanous 
18331b8b02a4SEd Tanous // weekday
18341b8b02a4SEd Tanous 
18351b8b02a4SEd Tanous CONSTCD14
18361b8b02a4SEd Tanous inline
18371b8b02a4SEd Tanous unsigned char
18381b8b02a4SEd Tanous weekday::weekday_from_days(int z) NOEXCEPT
18391b8b02a4SEd Tanous {
18401b8b02a4SEd Tanous     auto u = static_cast<unsigned>(z);
18411b8b02a4SEd Tanous     return static_cast<unsigned char>(z >= -4 ? (u+4) % 7 : u % 7);
18421b8b02a4SEd Tanous }
18431b8b02a4SEd Tanous 
18441b8b02a4SEd Tanous CONSTCD11
18451b8b02a4SEd Tanous inline
18461b8b02a4SEd Tanous weekday::weekday(unsigned wd) NOEXCEPT
18471b8b02a4SEd Tanous     : wd_(static_cast<decltype(wd_)>(wd != 7 ? wd : 0))
18481b8b02a4SEd Tanous     {}
18491b8b02a4SEd Tanous 
18501b8b02a4SEd Tanous CONSTCD14
18511b8b02a4SEd Tanous inline
18521b8b02a4SEd Tanous weekday::weekday(const sys_days& dp) NOEXCEPT
18531b8b02a4SEd Tanous     : wd_(weekday_from_days(dp.time_since_epoch().count()))
18541b8b02a4SEd Tanous     {}
18551b8b02a4SEd Tanous 
18561b8b02a4SEd Tanous CONSTCD14
18571b8b02a4SEd Tanous inline
18581b8b02a4SEd Tanous weekday::weekday(const local_days& dp) NOEXCEPT
18591b8b02a4SEd Tanous     : wd_(weekday_from_days(dp.time_since_epoch().count()))
18601b8b02a4SEd Tanous     {}
18611b8b02a4SEd Tanous 
18621b8b02a4SEd Tanous CONSTCD14 inline weekday& weekday::operator++() NOEXCEPT {*this += days{1}; return *this;}
18631b8b02a4SEd Tanous CONSTCD14 inline weekday weekday::operator++(int) NOEXCEPT {auto tmp(*this); ++(*this); return tmp;}
18641b8b02a4SEd Tanous CONSTCD14 inline weekday& weekday::operator--() NOEXCEPT {*this -= days{1}; return *this;}
18651b8b02a4SEd Tanous CONSTCD14 inline weekday weekday::operator--(int) NOEXCEPT {auto tmp(*this); --(*this); return tmp;}
18661b8b02a4SEd Tanous 
18671b8b02a4SEd Tanous CONSTCD14
18681b8b02a4SEd Tanous inline
18691b8b02a4SEd Tanous weekday&
18701b8b02a4SEd Tanous weekday::operator+=(const days& d) NOEXCEPT
18711b8b02a4SEd Tanous {
18721b8b02a4SEd Tanous     *this = *this + d;
18731b8b02a4SEd Tanous     return *this;
18741b8b02a4SEd Tanous }
18751b8b02a4SEd Tanous 
18761b8b02a4SEd Tanous CONSTCD14
18771b8b02a4SEd Tanous inline
18781b8b02a4SEd Tanous weekday&
18791b8b02a4SEd Tanous weekday::operator-=(const days& d) NOEXCEPT
18801b8b02a4SEd Tanous {
18811b8b02a4SEd Tanous     *this = *this - d;
18821b8b02a4SEd Tanous     return *this;
18831b8b02a4SEd Tanous }
18841b8b02a4SEd Tanous 
18851b8b02a4SEd Tanous CONSTCD11 inline bool weekday::ok() const NOEXCEPT {return wd_ <= 6;}
18861b8b02a4SEd Tanous 
18871b8b02a4SEd Tanous CONSTCD11
18881b8b02a4SEd Tanous inline
18891b8b02a4SEd Tanous unsigned weekday::c_encoding() const NOEXCEPT
18901b8b02a4SEd Tanous {
18911b8b02a4SEd Tanous     return unsigned{wd_};
18921b8b02a4SEd Tanous }
18931b8b02a4SEd Tanous 
18941b8b02a4SEd Tanous CONSTCD11
18951b8b02a4SEd Tanous inline
18961b8b02a4SEd Tanous unsigned weekday::iso_encoding() const NOEXCEPT
18971b8b02a4SEd Tanous {
18981b8b02a4SEd Tanous     return unsigned{((wd_ == 0u) ? 7u : wd_)};
18991b8b02a4SEd Tanous }
19001b8b02a4SEd Tanous 
19011b8b02a4SEd Tanous CONSTCD11
19021b8b02a4SEd Tanous inline
19031b8b02a4SEd Tanous bool
19041b8b02a4SEd Tanous operator==(const weekday& x, const weekday& y) NOEXCEPT
19051b8b02a4SEd Tanous {
19061b8b02a4SEd Tanous     return x.wd_ == y.wd_;
19071b8b02a4SEd Tanous }
19081b8b02a4SEd Tanous 
19091b8b02a4SEd Tanous CONSTCD11
19101b8b02a4SEd Tanous inline
19111b8b02a4SEd Tanous bool
19121b8b02a4SEd Tanous operator!=(const weekday& x, const weekday& y) NOEXCEPT
19131b8b02a4SEd Tanous {
19141b8b02a4SEd Tanous     return !(x == y);
19151b8b02a4SEd Tanous }
19161b8b02a4SEd Tanous 
19171b8b02a4SEd Tanous CONSTCD14
19181b8b02a4SEd Tanous inline
19191b8b02a4SEd Tanous days
19201b8b02a4SEd Tanous operator-(const weekday& x, const weekday& y) NOEXCEPT
19211b8b02a4SEd Tanous {
19221b8b02a4SEd Tanous     auto const wdu = x.wd_ - y.wd_;
19231b8b02a4SEd Tanous     auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7;
19241b8b02a4SEd Tanous     return days{wdu - wk * 7};
19251b8b02a4SEd Tanous }
19261b8b02a4SEd Tanous 
19271b8b02a4SEd Tanous CONSTCD14
19281b8b02a4SEd Tanous inline
19291b8b02a4SEd Tanous weekday
19301b8b02a4SEd Tanous operator+(const weekday& x, const days& y) NOEXCEPT
19311b8b02a4SEd Tanous {
19321b8b02a4SEd Tanous     auto const wdu = static_cast<long long>(static_cast<unsigned>(x.wd_)) + y.count();
19331b8b02a4SEd Tanous     auto const wk = (wdu >= 0 ? wdu : wdu-6) / 7;
19341b8b02a4SEd Tanous     return weekday{static_cast<unsigned>(wdu - wk * 7)};
19351b8b02a4SEd Tanous }
19361b8b02a4SEd Tanous 
19371b8b02a4SEd Tanous CONSTCD14
19381b8b02a4SEd Tanous inline
19391b8b02a4SEd Tanous weekday
19401b8b02a4SEd Tanous operator+(const days& x, const weekday& y) NOEXCEPT
19411b8b02a4SEd Tanous {
19421b8b02a4SEd Tanous     return y + x;
19431b8b02a4SEd Tanous }
19441b8b02a4SEd Tanous 
19451b8b02a4SEd Tanous CONSTCD14
19461b8b02a4SEd Tanous inline
19471b8b02a4SEd Tanous weekday
19481b8b02a4SEd Tanous operator-(const weekday& x, const days& y) NOEXCEPT
19491b8b02a4SEd Tanous {
19501b8b02a4SEd Tanous     return x + -y;
19511b8b02a4SEd Tanous }
19521b8b02a4SEd Tanous 
19531b8b02a4SEd Tanous namespace detail
19541b8b02a4SEd Tanous {
19551b8b02a4SEd Tanous 
19561b8b02a4SEd Tanous template<class CharT, class Traits>
19571b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
19581b8b02a4SEd Tanous low_level_fmt(std::basic_ostream<CharT, Traits>& os, const weekday& wd)
19591b8b02a4SEd Tanous {
19601b8b02a4SEd Tanous     if (wd.ok())
19611b8b02a4SEd Tanous     {
19621b8b02a4SEd Tanous         CharT fmt[] = {'%', 'a', 0};
19631b8b02a4SEd Tanous         os << format(fmt, wd);
19641b8b02a4SEd Tanous     }
19651b8b02a4SEd Tanous     else
19661b8b02a4SEd Tanous         os << wd.c_encoding();
19671b8b02a4SEd Tanous     return os;
19681b8b02a4SEd Tanous }
19691b8b02a4SEd Tanous 
19701b8b02a4SEd Tanous }  // namespace detail
19711b8b02a4SEd Tanous 
19721b8b02a4SEd Tanous template<class CharT, class Traits>
19731b8b02a4SEd Tanous inline
19741b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
19751b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const weekday& wd)
19761b8b02a4SEd Tanous {
19771b8b02a4SEd Tanous     detail::low_level_fmt(os, wd);
19781b8b02a4SEd Tanous     if (!wd.ok())
19791b8b02a4SEd Tanous         os << " is not a valid weekday";
19801b8b02a4SEd Tanous     return os;
19811b8b02a4SEd Tanous }
19821b8b02a4SEd Tanous 
19831b8b02a4SEd Tanous #if !defined(_MSC_VER) || (_MSC_VER >= 1900)
19841b8b02a4SEd Tanous inline namespace literals
19851b8b02a4SEd Tanous {
19861b8b02a4SEd Tanous 
19871b8b02a4SEd Tanous CONSTCD11
19881b8b02a4SEd Tanous inline
19891b8b02a4SEd Tanous date::day
19901b8b02a4SEd Tanous operator ""_d(unsigned long long d) NOEXCEPT
19911b8b02a4SEd Tanous {
19921b8b02a4SEd Tanous     return date::day{static_cast<unsigned>(d)};
19931b8b02a4SEd Tanous }
19941b8b02a4SEd Tanous 
19951b8b02a4SEd Tanous CONSTCD11
19961b8b02a4SEd Tanous inline
19971b8b02a4SEd Tanous date::year
19981b8b02a4SEd Tanous operator ""_y(unsigned long long y) NOEXCEPT
19991b8b02a4SEd Tanous {
20001b8b02a4SEd Tanous     return date::year(static_cast<int>(y));
20011b8b02a4SEd Tanous }
20021b8b02a4SEd Tanous #endif  // !defined(_MSC_VER) || (_MSC_VER >= 1900)
20031b8b02a4SEd Tanous 
20041b8b02a4SEd Tanous CONSTDATA date::last_spec last{};
20051b8b02a4SEd Tanous 
20061b8b02a4SEd Tanous CONSTDATA date::month jan{1};
20071b8b02a4SEd Tanous CONSTDATA date::month feb{2};
20081b8b02a4SEd Tanous CONSTDATA date::month mar{3};
20091b8b02a4SEd Tanous CONSTDATA date::month apr{4};
20101b8b02a4SEd Tanous CONSTDATA date::month may{5};
20111b8b02a4SEd Tanous CONSTDATA date::month jun{6};
20121b8b02a4SEd Tanous CONSTDATA date::month jul{7};
20131b8b02a4SEd Tanous CONSTDATA date::month aug{8};
20141b8b02a4SEd Tanous CONSTDATA date::month sep{9};
20151b8b02a4SEd Tanous CONSTDATA date::month oct{10};
20161b8b02a4SEd Tanous CONSTDATA date::month nov{11};
20171b8b02a4SEd Tanous CONSTDATA date::month dec{12};
20181b8b02a4SEd Tanous 
20191b8b02a4SEd Tanous CONSTDATA date::weekday sun{0u};
20201b8b02a4SEd Tanous CONSTDATA date::weekday mon{1u};
20211b8b02a4SEd Tanous CONSTDATA date::weekday tue{2u};
20221b8b02a4SEd Tanous CONSTDATA date::weekday wed{3u};
20231b8b02a4SEd Tanous CONSTDATA date::weekday thu{4u};
20241b8b02a4SEd Tanous CONSTDATA date::weekday fri{5u};
20251b8b02a4SEd Tanous CONSTDATA date::weekday sat{6u};
20261b8b02a4SEd Tanous 
20271b8b02a4SEd Tanous #if !defined(_MSC_VER) || (_MSC_VER >= 1900)
20281b8b02a4SEd Tanous }  // inline namespace literals
20291b8b02a4SEd Tanous #endif
20301b8b02a4SEd Tanous 
20311b8b02a4SEd Tanous CONSTDATA date::month January{1};
20321b8b02a4SEd Tanous CONSTDATA date::month February{2};
20331b8b02a4SEd Tanous CONSTDATA date::month March{3};
20341b8b02a4SEd Tanous CONSTDATA date::month April{4};
20351b8b02a4SEd Tanous CONSTDATA date::month May{5};
20361b8b02a4SEd Tanous CONSTDATA date::month June{6};
20371b8b02a4SEd Tanous CONSTDATA date::month July{7};
20381b8b02a4SEd Tanous CONSTDATA date::month August{8};
20391b8b02a4SEd Tanous CONSTDATA date::month September{9};
20401b8b02a4SEd Tanous CONSTDATA date::month October{10};
20411b8b02a4SEd Tanous CONSTDATA date::month November{11};
20421b8b02a4SEd Tanous CONSTDATA date::month December{12};
20431b8b02a4SEd Tanous 
20441b8b02a4SEd Tanous CONSTDATA date::weekday Monday{1};
20451b8b02a4SEd Tanous CONSTDATA date::weekday Tuesday{2};
20461b8b02a4SEd Tanous CONSTDATA date::weekday Wednesday{3};
20471b8b02a4SEd Tanous CONSTDATA date::weekday Thursday{4};
20481b8b02a4SEd Tanous CONSTDATA date::weekday Friday{5};
20491b8b02a4SEd Tanous CONSTDATA date::weekday Saturday{6};
20501b8b02a4SEd Tanous CONSTDATA date::weekday Sunday{7};
20511b8b02a4SEd Tanous 
20521b8b02a4SEd Tanous // weekday_indexed
20531b8b02a4SEd Tanous 
20541b8b02a4SEd Tanous CONSTCD11
20551b8b02a4SEd Tanous inline
20561b8b02a4SEd Tanous weekday
20571b8b02a4SEd Tanous weekday_indexed::weekday() const NOEXCEPT
20581b8b02a4SEd Tanous {
20591b8b02a4SEd Tanous     return date::weekday{static_cast<unsigned>(wd_)};
20601b8b02a4SEd Tanous }
20611b8b02a4SEd Tanous 
20621b8b02a4SEd Tanous CONSTCD11 inline unsigned weekday_indexed::index() const NOEXCEPT {return index_;}
20631b8b02a4SEd Tanous 
20641b8b02a4SEd Tanous CONSTCD11
20651b8b02a4SEd Tanous inline
20661b8b02a4SEd Tanous bool
20671b8b02a4SEd Tanous weekday_indexed::ok() const NOEXCEPT
20681b8b02a4SEd Tanous {
20691b8b02a4SEd Tanous     return weekday().ok() && 1 <= index_ && index_ <= 5;
20701b8b02a4SEd Tanous }
20711b8b02a4SEd Tanous 
20721b8b02a4SEd Tanous #ifdef __GNUC__
20731b8b02a4SEd Tanous #  pragma GCC diagnostic push
20741b8b02a4SEd Tanous #  pragma GCC diagnostic ignored "-Wconversion"
20751b8b02a4SEd Tanous #endif  // __GNUC__
20761b8b02a4SEd Tanous 
20771b8b02a4SEd Tanous CONSTCD11
20781b8b02a4SEd Tanous inline
20791b8b02a4SEd Tanous weekday_indexed::weekday_indexed(const date::weekday& wd, unsigned index) NOEXCEPT
20801b8b02a4SEd Tanous     : wd_(static_cast<decltype(wd_)>(static_cast<unsigned>(wd.wd_)))
20811b8b02a4SEd Tanous     , index_(static_cast<decltype(index_)>(index))
20821b8b02a4SEd Tanous     {}
20831b8b02a4SEd Tanous 
20841b8b02a4SEd Tanous #ifdef __GNUC__
20851b8b02a4SEd Tanous #  pragma GCC diagnostic pop
20861b8b02a4SEd Tanous #endif  // __GNUC__
20871b8b02a4SEd Tanous 
20881b8b02a4SEd Tanous namespace detail
20891b8b02a4SEd Tanous {
20901b8b02a4SEd Tanous 
20911b8b02a4SEd Tanous template<class CharT, class Traits>
20921b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
20931b8b02a4SEd Tanous low_level_fmt(std::basic_ostream<CharT, Traits>& os, const weekday_indexed& wdi)
20941b8b02a4SEd Tanous {
20951b8b02a4SEd Tanous     return low_level_fmt(os, wdi.weekday()) << '[' << wdi.index() << ']';
20961b8b02a4SEd Tanous }
20971b8b02a4SEd Tanous 
20981b8b02a4SEd Tanous }  // namespace detail
20991b8b02a4SEd Tanous 
21001b8b02a4SEd Tanous template<class CharT, class Traits>
21011b8b02a4SEd Tanous inline
21021b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
21031b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_indexed& wdi)
21041b8b02a4SEd Tanous {
21051b8b02a4SEd Tanous     detail::low_level_fmt(os, wdi);
21061b8b02a4SEd Tanous     if (!wdi.ok())
21071b8b02a4SEd Tanous         os << " is not a valid weekday_indexed";
21081b8b02a4SEd Tanous     return os;
21091b8b02a4SEd Tanous }
21101b8b02a4SEd Tanous 
21111b8b02a4SEd Tanous CONSTCD11
21121b8b02a4SEd Tanous inline
21131b8b02a4SEd Tanous weekday_indexed
21141b8b02a4SEd Tanous weekday::operator[](unsigned index) const NOEXCEPT
21151b8b02a4SEd Tanous {
21161b8b02a4SEd Tanous     return {*this, index};
21171b8b02a4SEd Tanous }
21181b8b02a4SEd Tanous 
21191b8b02a4SEd Tanous CONSTCD11
21201b8b02a4SEd Tanous inline
21211b8b02a4SEd Tanous bool
21221b8b02a4SEd Tanous operator==(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT
21231b8b02a4SEd Tanous {
21241b8b02a4SEd Tanous     return x.weekday() == y.weekday() && x.index() == y.index();
21251b8b02a4SEd Tanous }
21261b8b02a4SEd Tanous 
21271b8b02a4SEd Tanous CONSTCD11
21281b8b02a4SEd Tanous inline
21291b8b02a4SEd Tanous bool
21301b8b02a4SEd Tanous operator!=(const weekday_indexed& x, const weekday_indexed& y) NOEXCEPT
21311b8b02a4SEd Tanous {
21321b8b02a4SEd Tanous     return !(x == y);
21331b8b02a4SEd Tanous }
21341b8b02a4SEd Tanous 
21351b8b02a4SEd Tanous // weekday_last
21361b8b02a4SEd Tanous 
21371b8b02a4SEd Tanous CONSTCD11 inline date::weekday weekday_last::weekday() const NOEXCEPT {return wd_;}
21381b8b02a4SEd Tanous CONSTCD11 inline bool weekday_last::ok() const NOEXCEPT {return wd_.ok();}
21391b8b02a4SEd Tanous CONSTCD11 inline weekday_last::weekday_last(const date::weekday& wd) NOEXCEPT : wd_(wd) {}
21401b8b02a4SEd Tanous 
21411b8b02a4SEd Tanous CONSTCD11
21421b8b02a4SEd Tanous inline
21431b8b02a4SEd Tanous bool
21441b8b02a4SEd Tanous operator==(const weekday_last& x, const weekday_last& y) NOEXCEPT
21451b8b02a4SEd Tanous {
21461b8b02a4SEd Tanous     return x.weekday() == y.weekday();
21471b8b02a4SEd Tanous }
21481b8b02a4SEd Tanous 
21491b8b02a4SEd Tanous CONSTCD11
21501b8b02a4SEd Tanous inline
21511b8b02a4SEd Tanous bool
21521b8b02a4SEd Tanous operator!=(const weekday_last& x, const weekday_last& y) NOEXCEPT
21531b8b02a4SEd Tanous {
21541b8b02a4SEd Tanous     return !(x == y);
21551b8b02a4SEd Tanous }
21561b8b02a4SEd Tanous 
21571b8b02a4SEd Tanous namespace detail
21581b8b02a4SEd Tanous {
21591b8b02a4SEd Tanous 
21601b8b02a4SEd Tanous template<class CharT, class Traits>
21611b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
21621b8b02a4SEd Tanous low_level_fmt(std::basic_ostream<CharT, Traits>& os, const weekday_last& wdl)
21631b8b02a4SEd Tanous {
21641b8b02a4SEd Tanous     return low_level_fmt(os, wdl.weekday()) << "[last]";
21651b8b02a4SEd Tanous }
21661b8b02a4SEd Tanous 
21671b8b02a4SEd Tanous }  // namespace detail
21681b8b02a4SEd Tanous 
21691b8b02a4SEd Tanous template<class CharT, class Traits>
21701b8b02a4SEd Tanous inline
21711b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
21721b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const weekday_last& wdl)
21731b8b02a4SEd Tanous {
21741b8b02a4SEd Tanous     detail::low_level_fmt(os, wdl);
21751b8b02a4SEd Tanous     if (!wdl.ok())
21761b8b02a4SEd Tanous         os << " is not a valid weekday_last";
21771b8b02a4SEd Tanous     return os;
21781b8b02a4SEd Tanous }
21791b8b02a4SEd Tanous 
21801b8b02a4SEd Tanous CONSTCD11
21811b8b02a4SEd Tanous inline
21821b8b02a4SEd Tanous weekday_last
21831b8b02a4SEd Tanous weekday::operator[](last_spec) const NOEXCEPT
21841b8b02a4SEd Tanous {
21851b8b02a4SEd Tanous     return weekday_last{*this};
21861b8b02a4SEd Tanous }
21871b8b02a4SEd Tanous 
21881b8b02a4SEd Tanous // year_month
21891b8b02a4SEd Tanous 
21901b8b02a4SEd Tanous CONSTCD11
21911b8b02a4SEd Tanous inline
21921b8b02a4SEd Tanous year_month::year_month(const date::year& y, const date::month& m) NOEXCEPT
21931b8b02a4SEd Tanous     : y_(y)
21941b8b02a4SEd Tanous     , m_(m)
21951b8b02a4SEd Tanous     {}
21961b8b02a4SEd Tanous 
21971b8b02a4SEd Tanous CONSTCD11 inline year year_month::year() const NOEXCEPT {return y_;}
21981b8b02a4SEd Tanous CONSTCD11 inline month year_month::month() const NOEXCEPT {return m_;}
21991b8b02a4SEd Tanous CONSTCD11 inline bool year_month::ok() const NOEXCEPT {return y_.ok() && m_.ok();}
22001b8b02a4SEd Tanous 
22011b8b02a4SEd Tanous template<class>
22021b8b02a4SEd Tanous CONSTCD14
22031b8b02a4SEd Tanous inline
22041b8b02a4SEd Tanous year_month&
22051b8b02a4SEd Tanous year_month::operator+=(const months& dm) NOEXCEPT
22061b8b02a4SEd Tanous {
22071b8b02a4SEd Tanous     *this = *this + dm;
22081b8b02a4SEd Tanous     return *this;
22091b8b02a4SEd Tanous }
22101b8b02a4SEd Tanous 
22111b8b02a4SEd Tanous template<class>
22121b8b02a4SEd Tanous CONSTCD14
22131b8b02a4SEd Tanous inline
22141b8b02a4SEd Tanous year_month&
22151b8b02a4SEd Tanous year_month::operator-=(const months& dm) NOEXCEPT
22161b8b02a4SEd Tanous {
22171b8b02a4SEd Tanous     *this = *this - dm;
22181b8b02a4SEd Tanous     return *this;
22191b8b02a4SEd Tanous }
22201b8b02a4SEd Tanous 
22211b8b02a4SEd Tanous CONSTCD14
22221b8b02a4SEd Tanous inline
22231b8b02a4SEd Tanous year_month&
22241b8b02a4SEd Tanous year_month::operator+=(const years& dy) NOEXCEPT
22251b8b02a4SEd Tanous {
22261b8b02a4SEd Tanous     *this = *this + dy;
22271b8b02a4SEd Tanous     return *this;
22281b8b02a4SEd Tanous }
22291b8b02a4SEd Tanous 
22301b8b02a4SEd Tanous CONSTCD14
22311b8b02a4SEd Tanous inline
22321b8b02a4SEd Tanous year_month&
22331b8b02a4SEd Tanous year_month::operator-=(const years& dy) NOEXCEPT
22341b8b02a4SEd Tanous {
22351b8b02a4SEd Tanous     *this = *this - dy;
22361b8b02a4SEd Tanous     return *this;
22371b8b02a4SEd Tanous }
22381b8b02a4SEd Tanous 
22391b8b02a4SEd Tanous CONSTCD11
22401b8b02a4SEd Tanous inline
22411b8b02a4SEd Tanous bool
22421b8b02a4SEd Tanous operator==(const year_month& x, const year_month& y) NOEXCEPT
22431b8b02a4SEd Tanous {
22441b8b02a4SEd Tanous     return x.year() == y.year() && x.month() == y.month();
22451b8b02a4SEd Tanous }
22461b8b02a4SEd Tanous 
22471b8b02a4SEd Tanous CONSTCD11
22481b8b02a4SEd Tanous inline
22491b8b02a4SEd Tanous bool
22501b8b02a4SEd Tanous operator!=(const year_month& x, const year_month& y) NOEXCEPT
22511b8b02a4SEd Tanous {
22521b8b02a4SEd Tanous     return !(x == y);
22531b8b02a4SEd Tanous }
22541b8b02a4SEd Tanous 
22551b8b02a4SEd Tanous CONSTCD11
22561b8b02a4SEd Tanous inline
22571b8b02a4SEd Tanous bool
22581b8b02a4SEd Tanous operator<(const year_month& x, const year_month& y) NOEXCEPT
22591b8b02a4SEd Tanous {
22601b8b02a4SEd Tanous     return x.year() < y.year() ? true
22611b8b02a4SEd Tanous         : (x.year() > y.year() ? false
22621b8b02a4SEd Tanous         : (x.month() < y.month()));
22631b8b02a4SEd Tanous }
22641b8b02a4SEd Tanous 
22651b8b02a4SEd Tanous CONSTCD11
22661b8b02a4SEd Tanous inline
22671b8b02a4SEd Tanous bool
22681b8b02a4SEd Tanous operator>(const year_month& x, const year_month& y) NOEXCEPT
22691b8b02a4SEd Tanous {
22701b8b02a4SEd Tanous     return y < x;
22711b8b02a4SEd Tanous }
22721b8b02a4SEd Tanous 
22731b8b02a4SEd Tanous CONSTCD11
22741b8b02a4SEd Tanous inline
22751b8b02a4SEd Tanous bool
22761b8b02a4SEd Tanous operator<=(const year_month& x, const year_month& y) NOEXCEPT
22771b8b02a4SEd Tanous {
22781b8b02a4SEd Tanous     return !(y < x);
22791b8b02a4SEd Tanous }
22801b8b02a4SEd Tanous 
22811b8b02a4SEd Tanous CONSTCD11
22821b8b02a4SEd Tanous inline
22831b8b02a4SEd Tanous bool
22841b8b02a4SEd Tanous operator>=(const year_month& x, const year_month& y) NOEXCEPT
22851b8b02a4SEd Tanous {
22861b8b02a4SEd Tanous     return !(x < y);
22871b8b02a4SEd Tanous }
22881b8b02a4SEd Tanous 
22891b8b02a4SEd Tanous template<class>
22901b8b02a4SEd Tanous CONSTCD14
22911b8b02a4SEd Tanous inline
22921b8b02a4SEd Tanous year_month
22931b8b02a4SEd Tanous operator+(const year_month& ym, const months& dm) NOEXCEPT
22941b8b02a4SEd Tanous {
22951b8b02a4SEd Tanous     auto dmi = static_cast<int>(static_cast<unsigned>(ym.month())) - 1 + dm.count();
22961b8b02a4SEd Tanous     auto dy = (dmi >= 0 ? dmi : dmi-11) / 12;
22971b8b02a4SEd Tanous     dmi = dmi - dy * 12 + 1;
22981b8b02a4SEd Tanous     return (ym.year() + years(dy)) / month(static_cast<unsigned>(dmi));
22991b8b02a4SEd Tanous }
23001b8b02a4SEd Tanous 
23011b8b02a4SEd Tanous template<class>
23021b8b02a4SEd Tanous CONSTCD14
23031b8b02a4SEd Tanous inline
23041b8b02a4SEd Tanous year_month
23051b8b02a4SEd Tanous operator+(const months& dm, const year_month& ym) NOEXCEPT
23061b8b02a4SEd Tanous {
23071b8b02a4SEd Tanous     return ym + dm;
23081b8b02a4SEd Tanous }
23091b8b02a4SEd Tanous 
23101b8b02a4SEd Tanous template<class>
23111b8b02a4SEd Tanous CONSTCD14
23121b8b02a4SEd Tanous inline
23131b8b02a4SEd Tanous year_month
23141b8b02a4SEd Tanous operator-(const year_month& ym, const months& dm) NOEXCEPT
23151b8b02a4SEd Tanous {
23161b8b02a4SEd Tanous     return ym + -dm;
23171b8b02a4SEd Tanous }
23181b8b02a4SEd Tanous 
23191b8b02a4SEd Tanous CONSTCD11
23201b8b02a4SEd Tanous inline
23211b8b02a4SEd Tanous months
23221b8b02a4SEd Tanous operator-(const year_month& x, const year_month& y) NOEXCEPT
23231b8b02a4SEd Tanous {
23241b8b02a4SEd Tanous     return (x.year() - y.year()) +
23251b8b02a4SEd Tanous             months(static_cast<unsigned>(x.month()) - static_cast<unsigned>(y.month()));
23261b8b02a4SEd Tanous }
23271b8b02a4SEd Tanous 
23281b8b02a4SEd Tanous CONSTCD11
23291b8b02a4SEd Tanous inline
23301b8b02a4SEd Tanous year_month
23311b8b02a4SEd Tanous operator+(const year_month& ym, const years& dy) NOEXCEPT
23321b8b02a4SEd Tanous {
23331b8b02a4SEd Tanous     return (ym.year() + dy) / ym.month();
23341b8b02a4SEd Tanous }
23351b8b02a4SEd Tanous 
23361b8b02a4SEd Tanous CONSTCD11
23371b8b02a4SEd Tanous inline
23381b8b02a4SEd Tanous year_month
23391b8b02a4SEd Tanous operator+(const years& dy, const year_month& ym) NOEXCEPT
23401b8b02a4SEd Tanous {
23411b8b02a4SEd Tanous     return ym + dy;
23421b8b02a4SEd Tanous }
23431b8b02a4SEd Tanous 
23441b8b02a4SEd Tanous CONSTCD11
23451b8b02a4SEd Tanous inline
23461b8b02a4SEd Tanous year_month
23471b8b02a4SEd Tanous operator-(const year_month& ym, const years& dy) NOEXCEPT
23481b8b02a4SEd Tanous {
23491b8b02a4SEd Tanous     return ym + -dy;
23501b8b02a4SEd Tanous }
23511b8b02a4SEd Tanous 
23521b8b02a4SEd Tanous namespace detail
23531b8b02a4SEd Tanous {
23541b8b02a4SEd Tanous 
23551b8b02a4SEd Tanous template<class CharT, class Traits>
23561b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
23571b8b02a4SEd Tanous low_level_fmt(std::basic_ostream<CharT, Traits>& os, const year_month& ym)
23581b8b02a4SEd Tanous {
23591b8b02a4SEd Tanous     low_level_fmt(os, ym.year()) << '/';
23601b8b02a4SEd Tanous     return low_level_fmt(os, ym.month());
23611b8b02a4SEd Tanous }
23621b8b02a4SEd Tanous 
23631b8b02a4SEd Tanous }  // namespace detail
23641b8b02a4SEd Tanous 
23651b8b02a4SEd Tanous template<class CharT, class Traits>
23661b8b02a4SEd Tanous inline
23671b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
23681b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const year_month& ym)
23691b8b02a4SEd Tanous {
23701b8b02a4SEd Tanous     detail::low_level_fmt(os, ym);
23711b8b02a4SEd Tanous     if (!ym.ok())
23721b8b02a4SEd Tanous         os << " is not a valid year_month";
23731b8b02a4SEd Tanous     return os;
23741b8b02a4SEd Tanous }
23751b8b02a4SEd Tanous 
23761b8b02a4SEd Tanous // month_day
23771b8b02a4SEd Tanous 
23781b8b02a4SEd Tanous CONSTCD11
23791b8b02a4SEd Tanous inline
23801b8b02a4SEd Tanous month_day::month_day(const date::month& m, const date::day& d) NOEXCEPT
23811b8b02a4SEd Tanous     : m_(m)
23821b8b02a4SEd Tanous     , d_(d)
23831b8b02a4SEd Tanous     {}
23841b8b02a4SEd Tanous 
23851b8b02a4SEd Tanous CONSTCD11 inline date::month month_day::month() const NOEXCEPT {return m_;}
23861b8b02a4SEd Tanous CONSTCD11 inline date::day month_day::day() const NOEXCEPT {return d_;}
23871b8b02a4SEd Tanous 
23881b8b02a4SEd Tanous CONSTCD14
23891b8b02a4SEd Tanous inline
23901b8b02a4SEd Tanous bool
23911b8b02a4SEd Tanous month_day::ok() const NOEXCEPT
23921b8b02a4SEd Tanous {
23931b8b02a4SEd Tanous     CONSTDATA date::day d[] =
23941b8b02a4SEd Tanous     {
23951b8b02a4SEd Tanous         date::day(31), date::day(29), date::day(31),
23961b8b02a4SEd Tanous         date::day(30), date::day(31), date::day(30),
23971b8b02a4SEd Tanous         date::day(31), date::day(31), date::day(30),
23981b8b02a4SEd Tanous         date::day(31), date::day(30), date::day(31)
23991b8b02a4SEd Tanous     };
24001b8b02a4SEd Tanous     return m_.ok() && date::day{1} <= d_ && d_ <= d[static_cast<unsigned>(m_)-1];
24011b8b02a4SEd Tanous }
24021b8b02a4SEd Tanous 
24031b8b02a4SEd Tanous CONSTCD11
24041b8b02a4SEd Tanous inline
24051b8b02a4SEd Tanous bool
24061b8b02a4SEd Tanous operator==(const month_day& x, const month_day& y) NOEXCEPT
24071b8b02a4SEd Tanous {
24081b8b02a4SEd Tanous     return x.month() == y.month() && x.day() == y.day();
24091b8b02a4SEd Tanous }
24101b8b02a4SEd Tanous 
24111b8b02a4SEd Tanous CONSTCD11
24121b8b02a4SEd Tanous inline
24131b8b02a4SEd Tanous bool
24141b8b02a4SEd Tanous operator!=(const month_day& x, const month_day& y) NOEXCEPT
24151b8b02a4SEd Tanous {
24161b8b02a4SEd Tanous     return !(x == y);
24171b8b02a4SEd Tanous }
24181b8b02a4SEd Tanous 
24191b8b02a4SEd Tanous CONSTCD11
24201b8b02a4SEd Tanous inline
24211b8b02a4SEd Tanous bool
24221b8b02a4SEd Tanous operator<(const month_day& x, const month_day& y) NOEXCEPT
24231b8b02a4SEd Tanous {
24241b8b02a4SEd Tanous     return x.month() < y.month() ? true
24251b8b02a4SEd Tanous         : (x.month() > y.month() ? false
24261b8b02a4SEd Tanous         : (x.day() < y.day()));
24271b8b02a4SEd Tanous }
24281b8b02a4SEd Tanous 
24291b8b02a4SEd Tanous CONSTCD11
24301b8b02a4SEd Tanous inline
24311b8b02a4SEd Tanous bool
24321b8b02a4SEd Tanous operator>(const month_day& x, const month_day& y) NOEXCEPT
24331b8b02a4SEd Tanous {
24341b8b02a4SEd Tanous     return y < x;
24351b8b02a4SEd Tanous }
24361b8b02a4SEd Tanous 
24371b8b02a4SEd Tanous CONSTCD11
24381b8b02a4SEd Tanous inline
24391b8b02a4SEd Tanous bool
24401b8b02a4SEd Tanous operator<=(const month_day& x, const month_day& y) NOEXCEPT
24411b8b02a4SEd Tanous {
24421b8b02a4SEd Tanous     return !(y < x);
24431b8b02a4SEd Tanous }
24441b8b02a4SEd Tanous 
24451b8b02a4SEd Tanous CONSTCD11
24461b8b02a4SEd Tanous inline
24471b8b02a4SEd Tanous bool
24481b8b02a4SEd Tanous operator>=(const month_day& x, const month_day& y) NOEXCEPT
24491b8b02a4SEd Tanous {
24501b8b02a4SEd Tanous     return !(x < y);
24511b8b02a4SEd Tanous }
24521b8b02a4SEd Tanous 
24531b8b02a4SEd Tanous namespace detail
24541b8b02a4SEd Tanous {
24551b8b02a4SEd Tanous 
24561b8b02a4SEd Tanous template<class CharT, class Traits>
24571b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
24581b8b02a4SEd Tanous low_level_fmt(std::basic_ostream<CharT, Traits>& os, const month_day& md)
24591b8b02a4SEd Tanous {
24601b8b02a4SEd Tanous     low_level_fmt(os, md.month()) << '/';
24611b8b02a4SEd Tanous     return low_level_fmt(os, md.day());
24621b8b02a4SEd Tanous }
24631b8b02a4SEd Tanous 
24641b8b02a4SEd Tanous }  // namespace detail
24651b8b02a4SEd Tanous 
24661b8b02a4SEd Tanous template<class CharT, class Traits>
24671b8b02a4SEd Tanous inline
24681b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
24691b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const month_day& md)
24701b8b02a4SEd Tanous {
24711b8b02a4SEd Tanous     detail::low_level_fmt(os, md);
24721b8b02a4SEd Tanous     if (!md.ok())
24731b8b02a4SEd Tanous         os << " is not a valid month_day";
24741b8b02a4SEd Tanous     return os;
24751b8b02a4SEd Tanous }
24761b8b02a4SEd Tanous 
24771b8b02a4SEd Tanous // month_day_last
24781b8b02a4SEd Tanous 
24791b8b02a4SEd Tanous CONSTCD11 inline month month_day_last::month() const NOEXCEPT {return m_;}
24801b8b02a4SEd Tanous CONSTCD11 inline bool month_day_last::ok() const NOEXCEPT {return m_.ok();}
24811b8b02a4SEd Tanous CONSTCD11 inline month_day_last::month_day_last(const date::month& m) NOEXCEPT : m_(m) {}
24821b8b02a4SEd Tanous 
24831b8b02a4SEd Tanous CONSTCD11
24841b8b02a4SEd Tanous inline
24851b8b02a4SEd Tanous bool
24861b8b02a4SEd Tanous operator==(const month_day_last& x, const month_day_last& y) NOEXCEPT
24871b8b02a4SEd Tanous {
24881b8b02a4SEd Tanous     return x.month() == y.month();
24891b8b02a4SEd Tanous }
24901b8b02a4SEd Tanous 
24911b8b02a4SEd Tanous CONSTCD11
24921b8b02a4SEd Tanous inline
24931b8b02a4SEd Tanous bool
24941b8b02a4SEd Tanous operator!=(const month_day_last& x, const month_day_last& y) NOEXCEPT
24951b8b02a4SEd Tanous {
24961b8b02a4SEd Tanous     return !(x == y);
24971b8b02a4SEd Tanous }
24981b8b02a4SEd Tanous 
24991b8b02a4SEd Tanous CONSTCD11
25001b8b02a4SEd Tanous inline
25011b8b02a4SEd Tanous bool
25021b8b02a4SEd Tanous operator<(const month_day_last& x, const month_day_last& y) NOEXCEPT
25031b8b02a4SEd Tanous {
25041b8b02a4SEd Tanous     return x.month() < y.month();
25051b8b02a4SEd Tanous }
25061b8b02a4SEd Tanous 
25071b8b02a4SEd Tanous CONSTCD11
25081b8b02a4SEd Tanous inline
25091b8b02a4SEd Tanous bool
25101b8b02a4SEd Tanous operator>(const month_day_last& x, const month_day_last& y) NOEXCEPT
25111b8b02a4SEd Tanous {
25121b8b02a4SEd Tanous     return y < x;
25131b8b02a4SEd Tanous }
25141b8b02a4SEd Tanous 
25151b8b02a4SEd Tanous CONSTCD11
25161b8b02a4SEd Tanous inline
25171b8b02a4SEd Tanous bool
25181b8b02a4SEd Tanous operator<=(const month_day_last& x, const month_day_last& y) NOEXCEPT
25191b8b02a4SEd Tanous {
25201b8b02a4SEd Tanous     return !(y < x);
25211b8b02a4SEd Tanous }
25221b8b02a4SEd Tanous 
25231b8b02a4SEd Tanous CONSTCD11
25241b8b02a4SEd Tanous inline
25251b8b02a4SEd Tanous bool
25261b8b02a4SEd Tanous operator>=(const month_day_last& x, const month_day_last& y) NOEXCEPT
25271b8b02a4SEd Tanous {
25281b8b02a4SEd Tanous     return !(x < y);
25291b8b02a4SEd Tanous }
25301b8b02a4SEd Tanous 
25311b8b02a4SEd Tanous namespace detail
25321b8b02a4SEd Tanous {
25331b8b02a4SEd Tanous 
25341b8b02a4SEd Tanous template<class CharT, class Traits>
25351b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
25361b8b02a4SEd Tanous low_level_fmt(std::basic_ostream<CharT, Traits>& os, const month_day_last& mdl)
25371b8b02a4SEd Tanous {
25381b8b02a4SEd Tanous     return low_level_fmt(os, mdl.month()) << "/last";
25391b8b02a4SEd Tanous }
25401b8b02a4SEd Tanous 
25411b8b02a4SEd Tanous }  // namespace detail
25421b8b02a4SEd Tanous 
25431b8b02a4SEd Tanous template<class CharT, class Traits>
25441b8b02a4SEd Tanous inline
25451b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
25461b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const month_day_last& mdl)
25471b8b02a4SEd Tanous {
25481b8b02a4SEd Tanous     detail::low_level_fmt(os, mdl);
25491b8b02a4SEd Tanous     if (!mdl.ok())
25501b8b02a4SEd Tanous         os << " is not a valid month_day_last";
25511b8b02a4SEd Tanous     return os;
25521b8b02a4SEd Tanous }
25531b8b02a4SEd Tanous 
25541b8b02a4SEd Tanous // month_weekday
25551b8b02a4SEd Tanous 
25561b8b02a4SEd Tanous CONSTCD11
25571b8b02a4SEd Tanous inline
25581b8b02a4SEd Tanous month_weekday::month_weekday(const date::month& m,
25591b8b02a4SEd Tanous                              const date::weekday_indexed& wdi) NOEXCEPT
25601b8b02a4SEd Tanous     : m_(m)
25611b8b02a4SEd Tanous     , wdi_(wdi)
25621b8b02a4SEd Tanous     {}
25631b8b02a4SEd Tanous 
25641b8b02a4SEd Tanous CONSTCD11 inline month month_weekday::month() const NOEXCEPT {return m_;}
25651b8b02a4SEd Tanous 
25661b8b02a4SEd Tanous CONSTCD11
25671b8b02a4SEd Tanous inline
25681b8b02a4SEd Tanous weekday_indexed
25691b8b02a4SEd Tanous month_weekday::weekday_indexed() const NOEXCEPT
25701b8b02a4SEd Tanous {
25711b8b02a4SEd Tanous     return wdi_;
25721b8b02a4SEd Tanous }
25731b8b02a4SEd Tanous 
25741b8b02a4SEd Tanous CONSTCD11
25751b8b02a4SEd Tanous inline
25761b8b02a4SEd Tanous bool
25771b8b02a4SEd Tanous month_weekday::ok() const NOEXCEPT
25781b8b02a4SEd Tanous {
25791b8b02a4SEd Tanous     return m_.ok() && wdi_.ok();
25801b8b02a4SEd Tanous }
25811b8b02a4SEd Tanous 
25821b8b02a4SEd Tanous CONSTCD11
25831b8b02a4SEd Tanous inline
25841b8b02a4SEd Tanous bool
25851b8b02a4SEd Tanous operator==(const month_weekday& x, const month_weekday& y) NOEXCEPT
25861b8b02a4SEd Tanous {
25871b8b02a4SEd Tanous     return x.month() == y.month() && x.weekday_indexed() == y.weekday_indexed();
25881b8b02a4SEd Tanous }
25891b8b02a4SEd Tanous 
25901b8b02a4SEd Tanous CONSTCD11
25911b8b02a4SEd Tanous inline
25921b8b02a4SEd Tanous bool
25931b8b02a4SEd Tanous operator!=(const month_weekday& x, const month_weekday& y) NOEXCEPT
25941b8b02a4SEd Tanous {
25951b8b02a4SEd Tanous     return !(x == y);
25961b8b02a4SEd Tanous }
25971b8b02a4SEd Tanous 
25981b8b02a4SEd Tanous namespace detail
25991b8b02a4SEd Tanous {
26001b8b02a4SEd Tanous 
26011b8b02a4SEd Tanous template<class CharT, class Traits>
26021b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
26031b8b02a4SEd Tanous low_level_fmt(std::basic_ostream<CharT, Traits>& os, const month_weekday& mwd)
26041b8b02a4SEd Tanous {
26051b8b02a4SEd Tanous     low_level_fmt(os, mwd.month()) << '/';
26061b8b02a4SEd Tanous     return low_level_fmt(os, mwd.weekday_indexed());
26071b8b02a4SEd Tanous }
26081b8b02a4SEd Tanous 
26091b8b02a4SEd Tanous }  // namespace detail
26101b8b02a4SEd Tanous 
26111b8b02a4SEd Tanous template<class CharT, class Traits>
26121b8b02a4SEd Tanous inline
26131b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
26141b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday& mwd)
26151b8b02a4SEd Tanous {
26161b8b02a4SEd Tanous     detail::low_level_fmt(os, mwd);
26171b8b02a4SEd Tanous     if (!mwd.ok())
26181b8b02a4SEd Tanous         os << " is not a valid month_weekday";
26191b8b02a4SEd Tanous     return os;
26201b8b02a4SEd Tanous }
26211b8b02a4SEd Tanous 
26221b8b02a4SEd Tanous // month_weekday_last
26231b8b02a4SEd Tanous 
26241b8b02a4SEd Tanous CONSTCD11
26251b8b02a4SEd Tanous inline
26261b8b02a4SEd Tanous month_weekday_last::month_weekday_last(const date::month& m,
26271b8b02a4SEd Tanous                                        const date::weekday_last& wdl) NOEXCEPT
26281b8b02a4SEd Tanous     : m_(m)
26291b8b02a4SEd Tanous     , wdl_(wdl)
26301b8b02a4SEd Tanous     {}
26311b8b02a4SEd Tanous 
26321b8b02a4SEd Tanous CONSTCD11 inline month month_weekday_last::month() const NOEXCEPT {return m_;}
26331b8b02a4SEd Tanous 
26341b8b02a4SEd Tanous CONSTCD11
26351b8b02a4SEd Tanous inline
26361b8b02a4SEd Tanous weekday_last
26371b8b02a4SEd Tanous month_weekday_last::weekday_last() const NOEXCEPT
26381b8b02a4SEd Tanous {
26391b8b02a4SEd Tanous     return wdl_;
26401b8b02a4SEd Tanous }
26411b8b02a4SEd Tanous 
26421b8b02a4SEd Tanous CONSTCD11
26431b8b02a4SEd Tanous inline
26441b8b02a4SEd Tanous bool
26451b8b02a4SEd Tanous month_weekday_last::ok() const NOEXCEPT
26461b8b02a4SEd Tanous {
26471b8b02a4SEd Tanous     return m_.ok() && wdl_.ok();
26481b8b02a4SEd Tanous }
26491b8b02a4SEd Tanous 
26501b8b02a4SEd Tanous CONSTCD11
26511b8b02a4SEd Tanous inline
26521b8b02a4SEd Tanous bool
26531b8b02a4SEd Tanous operator==(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT
26541b8b02a4SEd Tanous {
26551b8b02a4SEd Tanous     return x.month() == y.month() && x.weekday_last() == y.weekday_last();
26561b8b02a4SEd Tanous }
26571b8b02a4SEd Tanous 
26581b8b02a4SEd Tanous CONSTCD11
26591b8b02a4SEd Tanous inline
26601b8b02a4SEd Tanous bool
26611b8b02a4SEd Tanous operator!=(const month_weekday_last& x, const month_weekday_last& y) NOEXCEPT
26621b8b02a4SEd Tanous {
26631b8b02a4SEd Tanous     return !(x == y);
26641b8b02a4SEd Tanous }
26651b8b02a4SEd Tanous 
26661b8b02a4SEd Tanous namespace detail
26671b8b02a4SEd Tanous {
26681b8b02a4SEd Tanous 
26691b8b02a4SEd Tanous template<class CharT, class Traits>
26701b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
26711b8b02a4SEd Tanous low_level_fmt(std::basic_ostream<CharT, Traits>& os, const month_weekday_last& mwdl)
26721b8b02a4SEd Tanous {
26731b8b02a4SEd Tanous     low_level_fmt(os, mwdl.month()) << '/';
26741b8b02a4SEd Tanous     return low_level_fmt(os, mwdl.weekday_last());
26751b8b02a4SEd Tanous }
26761b8b02a4SEd Tanous 
26771b8b02a4SEd Tanous }  // namespace detail
26781b8b02a4SEd Tanous 
26791b8b02a4SEd Tanous template<class CharT, class Traits>
26801b8b02a4SEd Tanous inline
26811b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
26821b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const month_weekday_last& mwdl)
26831b8b02a4SEd Tanous {
26841b8b02a4SEd Tanous     detail::low_level_fmt(os, mwdl);
26851b8b02a4SEd Tanous     if (!mwdl.ok())
26861b8b02a4SEd Tanous         os << " is not a valid month_weekday_last";
26871b8b02a4SEd Tanous     return os;
26881b8b02a4SEd Tanous }
26891b8b02a4SEd Tanous 
26901b8b02a4SEd Tanous // year_month_day_last
26911b8b02a4SEd Tanous 
26921b8b02a4SEd Tanous CONSTCD11
26931b8b02a4SEd Tanous inline
26941b8b02a4SEd Tanous year_month_day_last::year_month_day_last(const date::year& y,
26951b8b02a4SEd Tanous                                          const date::month_day_last& mdl) NOEXCEPT
26961b8b02a4SEd Tanous     : y_(y)
26971b8b02a4SEd Tanous     , mdl_(mdl)
26981b8b02a4SEd Tanous     {}
26991b8b02a4SEd Tanous 
27001b8b02a4SEd Tanous template<class>
27011b8b02a4SEd Tanous CONSTCD14
27021b8b02a4SEd Tanous inline
27031b8b02a4SEd Tanous year_month_day_last&
27041b8b02a4SEd Tanous year_month_day_last::operator+=(const months& m) NOEXCEPT
27051b8b02a4SEd Tanous {
27061b8b02a4SEd Tanous     *this = *this + m;
27071b8b02a4SEd Tanous     return *this;
27081b8b02a4SEd Tanous }
27091b8b02a4SEd Tanous 
27101b8b02a4SEd Tanous template<class>
27111b8b02a4SEd Tanous CONSTCD14
27121b8b02a4SEd Tanous inline
27131b8b02a4SEd Tanous year_month_day_last&
27141b8b02a4SEd Tanous year_month_day_last::operator-=(const months& m) NOEXCEPT
27151b8b02a4SEd Tanous {
27161b8b02a4SEd Tanous     *this = *this - m;
27171b8b02a4SEd Tanous     return *this;
27181b8b02a4SEd Tanous }
27191b8b02a4SEd Tanous 
27201b8b02a4SEd Tanous CONSTCD14
27211b8b02a4SEd Tanous inline
27221b8b02a4SEd Tanous year_month_day_last&
27231b8b02a4SEd Tanous year_month_day_last::operator+=(const years& y) NOEXCEPT
27241b8b02a4SEd Tanous {
27251b8b02a4SEd Tanous     *this = *this + y;
27261b8b02a4SEd Tanous     return *this;
27271b8b02a4SEd Tanous }
27281b8b02a4SEd Tanous 
27291b8b02a4SEd Tanous CONSTCD14
27301b8b02a4SEd Tanous inline
27311b8b02a4SEd Tanous year_month_day_last&
27321b8b02a4SEd Tanous year_month_day_last::operator-=(const years& y) NOEXCEPT
27331b8b02a4SEd Tanous {
27341b8b02a4SEd Tanous     *this = *this - y;
27351b8b02a4SEd Tanous     return *this;
27361b8b02a4SEd Tanous }
27371b8b02a4SEd Tanous 
27381b8b02a4SEd Tanous CONSTCD11 inline year year_month_day_last::year() const NOEXCEPT {return y_;}
27391b8b02a4SEd Tanous CONSTCD11 inline month year_month_day_last::month() const NOEXCEPT {return mdl_.month();}
27401b8b02a4SEd Tanous 
27411b8b02a4SEd Tanous CONSTCD11
27421b8b02a4SEd Tanous inline
27431b8b02a4SEd Tanous month_day_last
27441b8b02a4SEd Tanous year_month_day_last::month_day_last() const NOEXCEPT
27451b8b02a4SEd Tanous {
27461b8b02a4SEd Tanous     return mdl_;
27471b8b02a4SEd Tanous }
27481b8b02a4SEd Tanous 
27491b8b02a4SEd Tanous CONSTCD14
27501b8b02a4SEd Tanous inline
27511b8b02a4SEd Tanous day
27521b8b02a4SEd Tanous year_month_day_last::day() const NOEXCEPT
27531b8b02a4SEd Tanous {
27541b8b02a4SEd Tanous     CONSTDATA date::day d[] =
27551b8b02a4SEd Tanous     {
27561b8b02a4SEd Tanous         date::day(31), date::day(28), date::day(31),
27571b8b02a4SEd Tanous         date::day(30), date::day(31), date::day(30),
27581b8b02a4SEd Tanous         date::day(31), date::day(31), date::day(30),
27591b8b02a4SEd Tanous         date::day(31), date::day(30), date::day(31)
27601b8b02a4SEd Tanous     };
27611b8b02a4SEd Tanous     return (month() != February || !y_.is_leap()) && mdl_.ok() ?
27621b8b02a4SEd Tanous         d[static_cast<unsigned>(month()) - 1] : date::day{29};
27631b8b02a4SEd Tanous }
27641b8b02a4SEd Tanous 
27651b8b02a4SEd Tanous CONSTCD14
27661b8b02a4SEd Tanous inline
27671b8b02a4SEd Tanous year_month_day_last::operator sys_days() const NOEXCEPT
27681b8b02a4SEd Tanous {
27691b8b02a4SEd Tanous     return sys_days(year()/month()/day());
27701b8b02a4SEd Tanous }
27711b8b02a4SEd Tanous 
27721b8b02a4SEd Tanous CONSTCD14
27731b8b02a4SEd Tanous inline
27741b8b02a4SEd Tanous year_month_day_last::operator local_days() const NOEXCEPT
27751b8b02a4SEd Tanous {
27761b8b02a4SEd Tanous     return local_days(year()/month()/day());
27771b8b02a4SEd Tanous }
27781b8b02a4SEd Tanous 
27791b8b02a4SEd Tanous CONSTCD11
27801b8b02a4SEd Tanous inline
27811b8b02a4SEd Tanous bool
27821b8b02a4SEd Tanous year_month_day_last::ok() const NOEXCEPT
27831b8b02a4SEd Tanous {
27841b8b02a4SEd Tanous     return y_.ok() && mdl_.ok();
27851b8b02a4SEd Tanous }
27861b8b02a4SEd Tanous 
27871b8b02a4SEd Tanous CONSTCD11
27881b8b02a4SEd Tanous inline
27891b8b02a4SEd Tanous bool
27901b8b02a4SEd Tanous operator==(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
27911b8b02a4SEd Tanous {
27921b8b02a4SEd Tanous     return x.year() == y.year() && x.month_day_last() == y.month_day_last();
27931b8b02a4SEd Tanous }
27941b8b02a4SEd Tanous 
27951b8b02a4SEd Tanous CONSTCD11
27961b8b02a4SEd Tanous inline
27971b8b02a4SEd Tanous bool
27981b8b02a4SEd Tanous operator!=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
27991b8b02a4SEd Tanous {
28001b8b02a4SEd Tanous     return !(x == y);
28011b8b02a4SEd Tanous }
28021b8b02a4SEd Tanous 
28031b8b02a4SEd Tanous CONSTCD11
28041b8b02a4SEd Tanous inline
28051b8b02a4SEd Tanous bool
28061b8b02a4SEd Tanous operator<(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
28071b8b02a4SEd Tanous {
28081b8b02a4SEd Tanous     return x.year() < y.year() ? true
28091b8b02a4SEd Tanous         : (x.year() > y.year() ? false
28101b8b02a4SEd Tanous         : (x.month_day_last() < y.month_day_last()));
28111b8b02a4SEd Tanous }
28121b8b02a4SEd Tanous 
28131b8b02a4SEd Tanous CONSTCD11
28141b8b02a4SEd Tanous inline
28151b8b02a4SEd Tanous bool
28161b8b02a4SEd Tanous operator>(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
28171b8b02a4SEd Tanous {
28181b8b02a4SEd Tanous     return y < x;
28191b8b02a4SEd Tanous }
28201b8b02a4SEd Tanous 
28211b8b02a4SEd Tanous CONSTCD11
28221b8b02a4SEd Tanous inline
28231b8b02a4SEd Tanous bool
28241b8b02a4SEd Tanous operator<=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
28251b8b02a4SEd Tanous {
28261b8b02a4SEd Tanous     return !(y < x);
28271b8b02a4SEd Tanous }
28281b8b02a4SEd Tanous 
28291b8b02a4SEd Tanous CONSTCD11
28301b8b02a4SEd Tanous inline
28311b8b02a4SEd Tanous bool
28321b8b02a4SEd Tanous operator>=(const year_month_day_last& x, const year_month_day_last& y) NOEXCEPT
28331b8b02a4SEd Tanous {
28341b8b02a4SEd Tanous     return !(x < y);
28351b8b02a4SEd Tanous }
28361b8b02a4SEd Tanous 
28371b8b02a4SEd Tanous namespace detail
28381b8b02a4SEd Tanous {
28391b8b02a4SEd Tanous 
28401b8b02a4SEd Tanous template<class CharT, class Traits>
28411b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
28421b8b02a4SEd Tanous low_level_fmt(std::basic_ostream<CharT, Traits>& os, const year_month_day_last& ymdl)
28431b8b02a4SEd Tanous {
28441b8b02a4SEd Tanous     low_level_fmt(os, ymdl.year()) << '/';
28451b8b02a4SEd Tanous     return low_level_fmt(os, ymdl.month_day_last());
28461b8b02a4SEd Tanous }
28471b8b02a4SEd Tanous 
28481b8b02a4SEd Tanous }  // namespace detail
28491b8b02a4SEd Tanous 
28501b8b02a4SEd Tanous template<class CharT, class Traits>
28511b8b02a4SEd Tanous inline
28521b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
28531b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day_last& ymdl)
28541b8b02a4SEd Tanous {
28551b8b02a4SEd Tanous     detail::low_level_fmt(os, ymdl);
28561b8b02a4SEd Tanous     if (!ymdl.ok())
28571b8b02a4SEd Tanous         os << " is not a valid year_month_day_last";
28581b8b02a4SEd Tanous     return os;
28591b8b02a4SEd Tanous }
28601b8b02a4SEd Tanous 
28611b8b02a4SEd Tanous template<class>
28621b8b02a4SEd Tanous CONSTCD14
28631b8b02a4SEd Tanous inline
28641b8b02a4SEd Tanous year_month_day_last
28651b8b02a4SEd Tanous operator+(const year_month_day_last& ymdl, const months& dm) NOEXCEPT
28661b8b02a4SEd Tanous {
28671b8b02a4SEd Tanous     return (ymdl.year() / ymdl.month() + dm) / last;
28681b8b02a4SEd Tanous }
28691b8b02a4SEd Tanous 
28701b8b02a4SEd Tanous template<class>
28711b8b02a4SEd Tanous CONSTCD14
28721b8b02a4SEd Tanous inline
28731b8b02a4SEd Tanous year_month_day_last
28741b8b02a4SEd Tanous operator+(const months& dm, const year_month_day_last& ymdl) NOEXCEPT
28751b8b02a4SEd Tanous {
28761b8b02a4SEd Tanous     return ymdl + dm;
28771b8b02a4SEd Tanous }
28781b8b02a4SEd Tanous 
28791b8b02a4SEd Tanous template<class>
28801b8b02a4SEd Tanous CONSTCD14
28811b8b02a4SEd Tanous inline
28821b8b02a4SEd Tanous year_month_day_last
28831b8b02a4SEd Tanous operator-(const year_month_day_last& ymdl, const months& dm) NOEXCEPT
28841b8b02a4SEd Tanous {
28851b8b02a4SEd Tanous     return ymdl + (-dm);
28861b8b02a4SEd Tanous }
28871b8b02a4SEd Tanous 
28881b8b02a4SEd Tanous CONSTCD11
28891b8b02a4SEd Tanous inline
28901b8b02a4SEd Tanous year_month_day_last
28911b8b02a4SEd Tanous operator+(const year_month_day_last& ymdl, const years& dy) NOEXCEPT
28921b8b02a4SEd Tanous {
28931b8b02a4SEd Tanous     return {ymdl.year()+dy, ymdl.month_day_last()};
28941b8b02a4SEd Tanous }
28951b8b02a4SEd Tanous 
28961b8b02a4SEd Tanous CONSTCD11
28971b8b02a4SEd Tanous inline
28981b8b02a4SEd Tanous year_month_day_last
28991b8b02a4SEd Tanous operator+(const years& dy, const year_month_day_last& ymdl) NOEXCEPT
29001b8b02a4SEd Tanous {
29011b8b02a4SEd Tanous     return ymdl + dy;
29021b8b02a4SEd Tanous }
29031b8b02a4SEd Tanous 
29041b8b02a4SEd Tanous CONSTCD11
29051b8b02a4SEd Tanous inline
29061b8b02a4SEd Tanous year_month_day_last
29071b8b02a4SEd Tanous operator-(const year_month_day_last& ymdl, const years& dy) NOEXCEPT
29081b8b02a4SEd Tanous {
29091b8b02a4SEd Tanous     return ymdl + (-dy);
29101b8b02a4SEd Tanous }
29111b8b02a4SEd Tanous 
29121b8b02a4SEd Tanous // year_month_day
29131b8b02a4SEd Tanous 
29141b8b02a4SEd Tanous CONSTCD11
29151b8b02a4SEd Tanous inline
29161b8b02a4SEd Tanous year_month_day::year_month_day(const date::year& y, const date::month& m,
29171b8b02a4SEd Tanous                                const date::day& d) NOEXCEPT
29181b8b02a4SEd Tanous     : y_(y)
29191b8b02a4SEd Tanous     , m_(m)
29201b8b02a4SEd Tanous     , d_(d)
29211b8b02a4SEd Tanous     {}
29221b8b02a4SEd Tanous 
29231b8b02a4SEd Tanous CONSTCD14
29241b8b02a4SEd Tanous inline
29251b8b02a4SEd Tanous year_month_day::year_month_day(const year_month_day_last& ymdl) NOEXCEPT
29261b8b02a4SEd Tanous     : y_(ymdl.year())
29271b8b02a4SEd Tanous     , m_(ymdl.month())
29281b8b02a4SEd Tanous     , d_(ymdl.day())
29291b8b02a4SEd Tanous     {}
29301b8b02a4SEd Tanous 
29311b8b02a4SEd Tanous CONSTCD14
29321b8b02a4SEd Tanous inline
29331b8b02a4SEd Tanous year_month_day::year_month_day(sys_days dp) NOEXCEPT
29341b8b02a4SEd Tanous     : year_month_day(from_days(dp.time_since_epoch()))
29351b8b02a4SEd Tanous     {}
29361b8b02a4SEd Tanous 
29371b8b02a4SEd Tanous CONSTCD14
29381b8b02a4SEd Tanous inline
29391b8b02a4SEd Tanous year_month_day::year_month_day(local_days dp) NOEXCEPT
29401b8b02a4SEd Tanous     : year_month_day(from_days(dp.time_since_epoch()))
29411b8b02a4SEd Tanous     {}
29421b8b02a4SEd Tanous 
29431b8b02a4SEd Tanous CONSTCD11 inline year year_month_day::year() const NOEXCEPT {return y_;}
29441b8b02a4SEd Tanous CONSTCD11 inline month year_month_day::month() const NOEXCEPT {return m_;}
29451b8b02a4SEd Tanous CONSTCD11 inline day year_month_day::day() const NOEXCEPT {return d_;}
29461b8b02a4SEd Tanous 
29471b8b02a4SEd Tanous template<class>
29481b8b02a4SEd Tanous CONSTCD14
29491b8b02a4SEd Tanous inline
29501b8b02a4SEd Tanous year_month_day&
29511b8b02a4SEd Tanous year_month_day::operator+=(const months& m) NOEXCEPT
29521b8b02a4SEd Tanous {
29531b8b02a4SEd Tanous     *this = *this + m;
29541b8b02a4SEd Tanous     return *this;
29551b8b02a4SEd Tanous }
29561b8b02a4SEd Tanous 
29571b8b02a4SEd Tanous template<class>
29581b8b02a4SEd Tanous CONSTCD14
29591b8b02a4SEd Tanous inline
29601b8b02a4SEd Tanous year_month_day&
29611b8b02a4SEd Tanous year_month_day::operator-=(const months& m) NOEXCEPT
29621b8b02a4SEd Tanous {
29631b8b02a4SEd Tanous     *this = *this - m;
29641b8b02a4SEd Tanous     return *this;
29651b8b02a4SEd Tanous }
29661b8b02a4SEd Tanous 
29671b8b02a4SEd Tanous CONSTCD14
29681b8b02a4SEd Tanous inline
29691b8b02a4SEd Tanous year_month_day&
29701b8b02a4SEd Tanous year_month_day::operator+=(const years& y) NOEXCEPT
29711b8b02a4SEd Tanous {
29721b8b02a4SEd Tanous     *this = *this + y;
29731b8b02a4SEd Tanous     return *this;
29741b8b02a4SEd Tanous }
29751b8b02a4SEd Tanous 
29761b8b02a4SEd Tanous CONSTCD14
29771b8b02a4SEd Tanous inline
29781b8b02a4SEd Tanous year_month_day&
29791b8b02a4SEd Tanous year_month_day::operator-=(const years& y) NOEXCEPT
29801b8b02a4SEd Tanous {
29811b8b02a4SEd Tanous     *this = *this - y;
29821b8b02a4SEd Tanous     return *this;
29831b8b02a4SEd Tanous }
29841b8b02a4SEd Tanous 
29851b8b02a4SEd Tanous CONSTCD14
29861b8b02a4SEd Tanous inline
29871b8b02a4SEd Tanous days
29881b8b02a4SEd Tanous year_month_day::to_days() const NOEXCEPT
29891b8b02a4SEd Tanous {
29901b8b02a4SEd Tanous     static_assert(std::numeric_limits<unsigned>::digits >= 18,
29911b8b02a4SEd Tanous              "This algorithm has not been ported to a 16 bit unsigned integer");
29921b8b02a4SEd Tanous     static_assert(std::numeric_limits<int>::digits >= 20,
29931b8b02a4SEd Tanous              "This algorithm has not been ported to a 16 bit signed integer");
29941b8b02a4SEd Tanous     auto const y = static_cast<int>(y_) - (m_ <= February);
29951b8b02a4SEd Tanous     auto const m = static_cast<unsigned>(m_);
29961b8b02a4SEd Tanous     auto const d = static_cast<unsigned>(d_);
29971b8b02a4SEd Tanous     auto const era = (y >= 0 ? y : y-399) / 400;
29981b8b02a4SEd Tanous     auto const yoe = static_cast<unsigned>(y - era * 400);       // [0, 399]
29991b8b02a4SEd Tanous     auto const doy = (153*(m > 2 ? m-3 : m+9) + 2)/5 + d-1;      // [0, 365]
30001b8b02a4SEd Tanous     auto const doe = yoe * 365 + yoe/4 - yoe/100 + doy;          // [0, 146096]
30011b8b02a4SEd Tanous     return days{era * 146097 + static_cast<int>(doe) - 719468};
30021b8b02a4SEd Tanous }
30031b8b02a4SEd Tanous 
30041b8b02a4SEd Tanous CONSTCD14
30051b8b02a4SEd Tanous inline
30061b8b02a4SEd Tanous year_month_day::operator sys_days() const NOEXCEPT
30071b8b02a4SEd Tanous {
30081b8b02a4SEd Tanous     return sys_days{to_days()};
30091b8b02a4SEd Tanous }
30101b8b02a4SEd Tanous 
30111b8b02a4SEd Tanous CONSTCD14
30121b8b02a4SEd Tanous inline
30131b8b02a4SEd Tanous year_month_day::operator local_days() const NOEXCEPT
30141b8b02a4SEd Tanous {
30151b8b02a4SEd Tanous     return local_days{to_days()};
30161b8b02a4SEd Tanous }
30171b8b02a4SEd Tanous 
30181b8b02a4SEd Tanous CONSTCD14
30191b8b02a4SEd Tanous inline
30201b8b02a4SEd Tanous bool
30211b8b02a4SEd Tanous year_month_day::ok() const NOEXCEPT
30221b8b02a4SEd Tanous {
30231b8b02a4SEd Tanous     if (!(y_.ok() && m_.ok()))
30241b8b02a4SEd Tanous         return false;
30251b8b02a4SEd Tanous     return date::day{1} <= d_ && d_ <= (y_ / m_ / last).day();
30261b8b02a4SEd Tanous }
30271b8b02a4SEd Tanous 
30281b8b02a4SEd Tanous CONSTCD11
30291b8b02a4SEd Tanous inline
30301b8b02a4SEd Tanous bool
30311b8b02a4SEd Tanous operator==(const year_month_day& x, const year_month_day& y) NOEXCEPT
30321b8b02a4SEd Tanous {
30331b8b02a4SEd Tanous     return x.year() == y.year() && x.month() == y.month() && x.day() == y.day();
30341b8b02a4SEd Tanous }
30351b8b02a4SEd Tanous 
30361b8b02a4SEd Tanous CONSTCD11
30371b8b02a4SEd Tanous inline
30381b8b02a4SEd Tanous bool
30391b8b02a4SEd Tanous operator!=(const year_month_day& x, const year_month_day& y) NOEXCEPT
30401b8b02a4SEd Tanous {
30411b8b02a4SEd Tanous     return !(x == y);
30421b8b02a4SEd Tanous }
30431b8b02a4SEd Tanous 
30441b8b02a4SEd Tanous CONSTCD11
30451b8b02a4SEd Tanous inline
30461b8b02a4SEd Tanous bool
30471b8b02a4SEd Tanous operator<(const year_month_day& x, const year_month_day& y) NOEXCEPT
30481b8b02a4SEd Tanous {
30491b8b02a4SEd Tanous     return x.year() < y.year() ? true
30501b8b02a4SEd Tanous         : (x.year() > y.year() ? false
30511b8b02a4SEd Tanous         : (x.month() < y.month() ? true
30521b8b02a4SEd Tanous         : (x.month() > y.month() ? false
30531b8b02a4SEd Tanous         : (x.day() < y.day()))));
30541b8b02a4SEd Tanous }
30551b8b02a4SEd Tanous 
30561b8b02a4SEd Tanous CONSTCD11
30571b8b02a4SEd Tanous inline
30581b8b02a4SEd Tanous bool
30591b8b02a4SEd Tanous operator>(const year_month_day& x, const year_month_day& y) NOEXCEPT
30601b8b02a4SEd Tanous {
30611b8b02a4SEd Tanous     return y < x;
30621b8b02a4SEd Tanous }
30631b8b02a4SEd Tanous 
30641b8b02a4SEd Tanous CONSTCD11
30651b8b02a4SEd Tanous inline
30661b8b02a4SEd Tanous bool
30671b8b02a4SEd Tanous operator<=(const year_month_day& x, const year_month_day& y) NOEXCEPT
30681b8b02a4SEd Tanous {
30691b8b02a4SEd Tanous     return !(y < x);
30701b8b02a4SEd Tanous }
30711b8b02a4SEd Tanous 
30721b8b02a4SEd Tanous CONSTCD11
30731b8b02a4SEd Tanous inline
30741b8b02a4SEd Tanous bool
30751b8b02a4SEd Tanous operator>=(const year_month_day& x, const year_month_day& y) NOEXCEPT
30761b8b02a4SEd Tanous {
30771b8b02a4SEd Tanous     return !(x < y);
30781b8b02a4SEd Tanous }
30791b8b02a4SEd Tanous 
30801b8b02a4SEd Tanous template<class CharT, class Traits>
30811b8b02a4SEd Tanous inline
30821b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
30831b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_day& ymd)
30841b8b02a4SEd Tanous {
30851b8b02a4SEd Tanous     detail::save_ostream<CharT, Traits> _(os);
30861b8b02a4SEd Tanous     os.fill('0');
30871b8b02a4SEd Tanous     os.flags(std::ios::dec | std::ios::right);
30881b8b02a4SEd Tanous     os.imbue(std::locale::classic());
30891b8b02a4SEd Tanous     os << static_cast<int>(ymd.year()) << '-';
30901b8b02a4SEd Tanous     os.width(2);
30911b8b02a4SEd Tanous     os << static_cast<unsigned>(ymd.month()) << '-';
30921b8b02a4SEd Tanous     os.width(2);
30931b8b02a4SEd Tanous     os << static_cast<unsigned>(ymd.day());
30941b8b02a4SEd Tanous     if (!ymd.ok())
30951b8b02a4SEd Tanous         os << " is not a valid year_month_day";
30961b8b02a4SEd Tanous     return os;
30971b8b02a4SEd Tanous }
30981b8b02a4SEd Tanous 
30991b8b02a4SEd Tanous CONSTCD14
31001b8b02a4SEd Tanous inline
31011b8b02a4SEd Tanous year_month_day
31021b8b02a4SEd Tanous year_month_day::from_days(days dp) NOEXCEPT
31031b8b02a4SEd Tanous {
31041b8b02a4SEd Tanous     static_assert(std::numeric_limits<unsigned>::digits >= 18,
31051b8b02a4SEd Tanous              "This algorithm has not been ported to a 16 bit unsigned integer");
31061b8b02a4SEd Tanous     static_assert(std::numeric_limits<int>::digits >= 20,
31071b8b02a4SEd Tanous              "This algorithm has not been ported to a 16 bit signed integer");
31081b8b02a4SEd Tanous     auto const z = dp.count() + 719468;
31091b8b02a4SEd Tanous     auto const era = (z >= 0 ? z : z - 146096) / 146097;
31101b8b02a4SEd Tanous     auto const doe = static_cast<unsigned>(z - era * 146097);          // [0, 146096]
31111b8b02a4SEd Tanous     auto const yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365;  // [0, 399]
31121b8b02a4SEd Tanous     auto const y = static_cast<days::rep>(yoe) + era * 400;
31131b8b02a4SEd Tanous     auto const doy = doe - (365*yoe + yoe/4 - yoe/100);                // [0, 365]
31141b8b02a4SEd Tanous     auto const mp = (5*doy + 2)/153;                                   // [0, 11]
31151b8b02a4SEd Tanous     auto const d = doy - (153*mp+2)/5 + 1;                             // [1, 31]
31161b8b02a4SEd Tanous     auto const m = mp < 10 ? mp+3 : mp-9;                              // [1, 12]
31171b8b02a4SEd Tanous     return year_month_day{date::year{y + (m <= 2)}, date::month(m), date::day(d)};
31181b8b02a4SEd Tanous }
31191b8b02a4SEd Tanous 
31201b8b02a4SEd Tanous template<class>
31211b8b02a4SEd Tanous CONSTCD14
31221b8b02a4SEd Tanous inline
31231b8b02a4SEd Tanous year_month_day
31241b8b02a4SEd Tanous operator+(const year_month_day& ymd, const months& dm) NOEXCEPT
31251b8b02a4SEd Tanous {
31261b8b02a4SEd Tanous     return (ymd.year() / ymd.month() + dm) / ymd.day();
31271b8b02a4SEd Tanous }
31281b8b02a4SEd Tanous 
31291b8b02a4SEd Tanous template<class>
31301b8b02a4SEd Tanous CONSTCD14
31311b8b02a4SEd Tanous inline
31321b8b02a4SEd Tanous year_month_day
31331b8b02a4SEd Tanous operator+(const months& dm, const year_month_day& ymd) NOEXCEPT
31341b8b02a4SEd Tanous {
31351b8b02a4SEd Tanous     return ymd + dm;
31361b8b02a4SEd Tanous }
31371b8b02a4SEd Tanous 
31381b8b02a4SEd Tanous template<class>
31391b8b02a4SEd Tanous CONSTCD14
31401b8b02a4SEd Tanous inline
31411b8b02a4SEd Tanous year_month_day
31421b8b02a4SEd Tanous operator-(const year_month_day& ymd, const months& dm) NOEXCEPT
31431b8b02a4SEd Tanous {
31441b8b02a4SEd Tanous     return ymd + (-dm);
31451b8b02a4SEd Tanous }
31461b8b02a4SEd Tanous 
31471b8b02a4SEd Tanous CONSTCD11
31481b8b02a4SEd Tanous inline
31491b8b02a4SEd Tanous year_month_day
31501b8b02a4SEd Tanous operator+(const year_month_day& ymd, const years& dy) NOEXCEPT
31511b8b02a4SEd Tanous {
31521b8b02a4SEd Tanous     return (ymd.year() + dy) / ymd.month() / ymd.day();
31531b8b02a4SEd Tanous }
31541b8b02a4SEd Tanous 
31551b8b02a4SEd Tanous CONSTCD11
31561b8b02a4SEd Tanous inline
31571b8b02a4SEd Tanous year_month_day
31581b8b02a4SEd Tanous operator+(const years& dy, const year_month_day& ymd) NOEXCEPT
31591b8b02a4SEd Tanous {
31601b8b02a4SEd Tanous     return ymd + dy;
31611b8b02a4SEd Tanous }
31621b8b02a4SEd Tanous 
31631b8b02a4SEd Tanous CONSTCD11
31641b8b02a4SEd Tanous inline
31651b8b02a4SEd Tanous year_month_day
31661b8b02a4SEd Tanous operator-(const year_month_day& ymd, const years& dy) NOEXCEPT
31671b8b02a4SEd Tanous {
31681b8b02a4SEd Tanous     return ymd + (-dy);
31691b8b02a4SEd Tanous }
31701b8b02a4SEd Tanous 
31711b8b02a4SEd Tanous // year_month_weekday
31721b8b02a4SEd Tanous 
31731b8b02a4SEd Tanous CONSTCD11
31741b8b02a4SEd Tanous inline
31751b8b02a4SEd Tanous year_month_weekday::year_month_weekday(const date::year& y, const date::month& m,
31761b8b02a4SEd Tanous                                        const date::weekday_indexed& wdi)
31771b8b02a4SEd Tanous         NOEXCEPT
31781b8b02a4SEd Tanous     : y_(y)
31791b8b02a4SEd Tanous     , m_(m)
31801b8b02a4SEd Tanous     , wdi_(wdi)
31811b8b02a4SEd Tanous     {}
31821b8b02a4SEd Tanous 
31831b8b02a4SEd Tanous CONSTCD14
31841b8b02a4SEd Tanous inline
31851b8b02a4SEd Tanous year_month_weekday::year_month_weekday(const sys_days& dp) NOEXCEPT
31861b8b02a4SEd Tanous     : year_month_weekday(from_days(dp.time_since_epoch()))
31871b8b02a4SEd Tanous     {}
31881b8b02a4SEd Tanous 
31891b8b02a4SEd Tanous CONSTCD14
31901b8b02a4SEd Tanous inline
31911b8b02a4SEd Tanous year_month_weekday::year_month_weekday(const local_days& dp) NOEXCEPT
31921b8b02a4SEd Tanous     : year_month_weekday(from_days(dp.time_since_epoch()))
31931b8b02a4SEd Tanous     {}
31941b8b02a4SEd Tanous 
31951b8b02a4SEd Tanous template<class>
31961b8b02a4SEd Tanous CONSTCD14
31971b8b02a4SEd Tanous inline
31981b8b02a4SEd Tanous year_month_weekday&
31991b8b02a4SEd Tanous year_month_weekday::operator+=(const months& m) NOEXCEPT
32001b8b02a4SEd Tanous {
32011b8b02a4SEd Tanous     *this = *this + m;
32021b8b02a4SEd Tanous     return *this;
32031b8b02a4SEd Tanous }
32041b8b02a4SEd Tanous 
32051b8b02a4SEd Tanous template<class>
32061b8b02a4SEd Tanous CONSTCD14
32071b8b02a4SEd Tanous inline
32081b8b02a4SEd Tanous year_month_weekday&
32091b8b02a4SEd Tanous year_month_weekday::operator-=(const months& m) NOEXCEPT
32101b8b02a4SEd Tanous {
32111b8b02a4SEd Tanous     *this = *this - m;
32121b8b02a4SEd Tanous     return *this;
32131b8b02a4SEd Tanous }
32141b8b02a4SEd Tanous 
32151b8b02a4SEd Tanous CONSTCD14
32161b8b02a4SEd Tanous inline
32171b8b02a4SEd Tanous year_month_weekday&
32181b8b02a4SEd Tanous year_month_weekday::operator+=(const years& y) NOEXCEPT
32191b8b02a4SEd Tanous {
32201b8b02a4SEd Tanous     *this = *this + y;
32211b8b02a4SEd Tanous     return *this;
32221b8b02a4SEd Tanous }
32231b8b02a4SEd Tanous 
32241b8b02a4SEd Tanous CONSTCD14
32251b8b02a4SEd Tanous inline
32261b8b02a4SEd Tanous year_month_weekday&
32271b8b02a4SEd Tanous year_month_weekday::operator-=(const years& y) NOEXCEPT
32281b8b02a4SEd Tanous {
32291b8b02a4SEd Tanous     *this = *this - y;
32301b8b02a4SEd Tanous     return *this;
32311b8b02a4SEd Tanous }
32321b8b02a4SEd Tanous 
32331b8b02a4SEd Tanous CONSTCD11 inline year year_month_weekday::year() const NOEXCEPT {return y_;}
32341b8b02a4SEd Tanous CONSTCD11 inline month year_month_weekday::month() const NOEXCEPT {return m_;}
32351b8b02a4SEd Tanous 
32361b8b02a4SEd Tanous CONSTCD11
32371b8b02a4SEd Tanous inline
32381b8b02a4SEd Tanous weekday
32391b8b02a4SEd Tanous year_month_weekday::weekday() const NOEXCEPT
32401b8b02a4SEd Tanous {
32411b8b02a4SEd Tanous     return wdi_.weekday();
32421b8b02a4SEd Tanous }
32431b8b02a4SEd Tanous 
32441b8b02a4SEd Tanous CONSTCD11
32451b8b02a4SEd Tanous inline
32461b8b02a4SEd Tanous unsigned
32471b8b02a4SEd Tanous year_month_weekday::index() const NOEXCEPT
32481b8b02a4SEd Tanous {
32491b8b02a4SEd Tanous     return wdi_.index();
32501b8b02a4SEd Tanous }
32511b8b02a4SEd Tanous 
32521b8b02a4SEd Tanous CONSTCD11
32531b8b02a4SEd Tanous inline
32541b8b02a4SEd Tanous weekday_indexed
32551b8b02a4SEd Tanous year_month_weekday::weekday_indexed() const NOEXCEPT
32561b8b02a4SEd Tanous {
32571b8b02a4SEd Tanous     return wdi_;
32581b8b02a4SEd Tanous }
32591b8b02a4SEd Tanous 
32601b8b02a4SEd Tanous CONSTCD14
32611b8b02a4SEd Tanous inline
32621b8b02a4SEd Tanous year_month_weekday::operator sys_days() const NOEXCEPT
32631b8b02a4SEd Tanous {
32641b8b02a4SEd Tanous     return sys_days{to_days()};
32651b8b02a4SEd Tanous }
32661b8b02a4SEd Tanous 
32671b8b02a4SEd Tanous CONSTCD14
32681b8b02a4SEd Tanous inline
32691b8b02a4SEd Tanous year_month_weekday::operator local_days() const NOEXCEPT
32701b8b02a4SEd Tanous {
32711b8b02a4SEd Tanous     return local_days{to_days()};
32721b8b02a4SEd Tanous }
32731b8b02a4SEd Tanous 
32741b8b02a4SEd Tanous CONSTCD14
32751b8b02a4SEd Tanous inline
32761b8b02a4SEd Tanous bool
32771b8b02a4SEd Tanous year_month_weekday::ok() const NOEXCEPT
32781b8b02a4SEd Tanous {
32791b8b02a4SEd Tanous     if (!y_.ok() || !m_.ok() || !wdi_.weekday().ok() || wdi_.index() < 1)
32801b8b02a4SEd Tanous         return false;
32811b8b02a4SEd Tanous     if (wdi_.index() <= 4)
32821b8b02a4SEd Tanous         return true;
32831b8b02a4SEd Tanous     auto d2 = wdi_.weekday() - date::weekday(static_cast<sys_days>(y_/m_/1)) +
32841b8b02a4SEd Tanous                   days((wdi_.index()-1)*7 + 1);
32851b8b02a4SEd Tanous     return static_cast<unsigned>(d2.count()) <= static_cast<unsigned>((y_/m_/last).day());
32861b8b02a4SEd Tanous }
32871b8b02a4SEd Tanous 
32881b8b02a4SEd Tanous CONSTCD14
32891b8b02a4SEd Tanous inline
32901b8b02a4SEd Tanous year_month_weekday
32911b8b02a4SEd Tanous year_month_weekday::from_days(days d) NOEXCEPT
32921b8b02a4SEd Tanous {
32931b8b02a4SEd Tanous     sys_days dp{d};
32941b8b02a4SEd Tanous     auto const wd = date::weekday(dp);
32951b8b02a4SEd Tanous     auto const ymd = year_month_day(dp);
32961b8b02a4SEd Tanous     return {ymd.year(), ymd.month(), wd[(static_cast<unsigned>(ymd.day())-1)/7+1]};
32971b8b02a4SEd Tanous }
32981b8b02a4SEd Tanous 
32991b8b02a4SEd Tanous CONSTCD14
33001b8b02a4SEd Tanous inline
33011b8b02a4SEd Tanous days
33021b8b02a4SEd Tanous year_month_weekday::to_days() const NOEXCEPT
33031b8b02a4SEd Tanous {
33041b8b02a4SEd Tanous     auto d = sys_days(y_/m_/1);
33051b8b02a4SEd Tanous     return (d + (wdi_.weekday() - date::weekday(d) + days{(wdi_.index()-1)*7})
33061b8b02a4SEd Tanous            ).time_since_epoch();
33071b8b02a4SEd Tanous }
33081b8b02a4SEd Tanous 
33091b8b02a4SEd Tanous CONSTCD11
33101b8b02a4SEd Tanous inline
33111b8b02a4SEd Tanous bool
33121b8b02a4SEd Tanous operator==(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT
33131b8b02a4SEd Tanous {
33141b8b02a4SEd Tanous     return x.year() == y.year() && x.month() == y.month() &&
33151b8b02a4SEd Tanous            x.weekday_indexed() == y.weekday_indexed();
33161b8b02a4SEd Tanous }
33171b8b02a4SEd Tanous 
33181b8b02a4SEd Tanous CONSTCD11
33191b8b02a4SEd Tanous inline
33201b8b02a4SEd Tanous bool
33211b8b02a4SEd Tanous operator!=(const year_month_weekday& x, const year_month_weekday& y) NOEXCEPT
33221b8b02a4SEd Tanous {
33231b8b02a4SEd Tanous     return !(x == y);
33241b8b02a4SEd Tanous }
33251b8b02a4SEd Tanous 
33261b8b02a4SEd Tanous template<class CharT, class Traits>
33271b8b02a4SEd Tanous inline
33281b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
33291b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday& ymwdi)
33301b8b02a4SEd Tanous {
33311b8b02a4SEd Tanous     detail::low_level_fmt(os, ymwdi.year()) << '/';
33321b8b02a4SEd Tanous     detail::low_level_fmt(os, ymwdi.month()) << '/';
33331b8b02a4SEd Tanous     detail::low_level_fmt(os, ymwdi.weekday_indexed());
33341b8b02a4SEd Tanous     if (!ymwdi.ok())
33351b8b02a4SEd Tanous         os << " is not a valid year_month_weekday";
33361b8b02a4SEd Tanous     return os;
33371b8b02a4SEd Tanous }
33381b8b02a4SEd Tanous 
33391b8b02a4SEd Tanous template<class>
33401b8b02a4SEd Tanous CONSTCD14
33411b8b02a4SEd Tanous inline
33421b8b02a4SEd Tanous year_month_weekday
33431b8b02a4SEd Tanous operator+(const year_month_weekday& ymwd, const months& dm) NOEXCEPT
33441b8b02a4SEd Tanous {
33451b8b02a4SEd Tanous     return (ymwd.year() / ymwd.month() + dm) / ymwd.weekday_indexed();
33461b8b02a4SEd Tanous }
33471b8b02a4SEd Tanous 
33481b8b02a4SEd Tanous template<class>
33491b8b02a4SEd Tanous CONSTCD14
33501b8b02a4SEd Tanous inline
33511b8b02a4SEd Tanous year_month_weekday
33521b8b02a4SEd Tanous operator+(const months& dm, const year_month_weekday& ymwd) NOEXCEPT
33531b8b02a4SEd Tanous {
33541b8b02a4SEd Tanous     return ymwd + dm;
33551b8b02a4SEd Tanous }
33561b8b02a4SEd Tanous 
33571b8b02a4SEd Tanous template<class>
33581b8b02a4SEd Tanous CONSTCD14
33591b8b02a4SEd Tanous inline
33601b8b02a4SEd Tanous year_month_weekday
33611b8b02a4SEd Tanous operator-(const year_month_weekday& ymwd, const months& dm) NOEXCEPT
33621b8b02a4SEd Tanous {
33631b8b02a4SEd Tanous     return ymwd + (-dm);
33641b8b02a4SEd Tanous }
33651b8b02a4SEd Tanous 
33661b8b02a4SEd Tanous CONSTCD11
33671b8b02a4SEd Tanous inline
33681b8b02a4SEd Tanous year_month_weekday
33691b8b02a4SEd Tanous operator+(const year_month_weekday& ymwd, const years& dy) NOEXCEPT
33701b8b02a4SEd Tanous {
33711b8b02a4SEd Tanous     return {ymwd.year()+dy, ymwd.month(), ymwd.weekday_indexed()};
33721b8b02a4SEd Tanous }
33731b8b02a4SEd Tanous 
33741b8b02a4SEd Tanous CONSTCD11
33751b8b02a4SEd Tanous inline
33761b8b02a4SEd Tanous year_month_weekday
33771b8b02a4SEd Tanous operator+(const years& dy, const year_month_weekday& ymwd) NOEXCEPT
33781b8b02a4SEd Tanous {
33791b8b02a4SEd Tanous     return ymwd + dy;
33801b8b02a4SEd Tanous }
33811b8b02a4SEd Tanous 
33821b8b02a4SEd Tanous CONSTCD11
33831b8b02a4SEd Tanous inline
33841b8b02a4SEd Tanous year_month_weekday
33851b8b02a4SEd Tanous operator-(const year_month_weekday& ymwd, const years& dy) NOEXCEPT
33861b8b02a4SEd Tanous {
33871b8b02a4SEd Tanous     return ymwd + (-dy);
33881b8b02a4SEd Tanous }
33891b8b02a4SEd Tanous 
33901b8b02a4SEd Tanous // year_month_weekday_last
33911b8b02a4SEd Tanous 
33921b8b02a4SEd Tanous CONSTCD11
33931b8b02a4SEd Tanous inline
33941b8b02a4SEd Tanous year_month_weekday_last::year_month_weekday_last(const date::year& y,
33951b8b02a4SEd Tanous                                                  const date::month& m,
33961b8b02a4SEd Tanous                                                  const date::weekday_last& wdl) NOEXCEPT
33971b8b02a4SEd Tanous     : y_(y)
33981b8b02a4SEd Tanous     , m_(m)
33991b8b02a4SEd Tanous     , wdl_(wdl)
34001b8b02a4SEd Tanous     {}
34011b8b02a4SEd Tanous 
34021b8b02a4SEd Tanous template<class>
34031b8b02a4SEd Tanous CONSTCD14
34041b8b02a4SEd Tanous inline
34051b8b02a4SEd Tanous year_month_weekday_last&
34061b8b02a4SEd Tanous year_month_weekday_last::operator+=(const months& m) NOEXCEPT
34071b8b02a4SEd Tanous {
34081b8b02a4SEd Tanous     *this = *this + m;
34091b8b02a4SEd Tanous     return *this;
34101b8b02a4SEd Tanous }
34111b8b02a4SEd Tanous 
34121b8b02a4SEd Tanous template<class>
34131b8b02a4SEd Tanous CONSTCD14
34141b8b02a4SEd Tanous inline
34151b8b02a4SEd Tanous year_month_weekday_last&
34161b8b02a4SEd Tanous year_month_weekday_last::operator-=(const months& m) NOEXCEPT
34171b8b02a4SEd Tanous {
34181b8b02a4SEd Tanous     *this = *this - m;
34191b8b02a4SEd Tanous     return *this;
34201b8b02a4SEd Tanous }
34211b8b02a4SEd Tanous 
34221b8b02a4SEd Tanous CONSTCD14
34231b8b02a4SEd Tanous inline
34241b8b02a4SEd Tanous year_month_weekday_last&
34251b8b02a4SEd Tanous year_month_weekday_last::operator+=(const years& y) NOEXCEPT
34261b8b02a4SEd Tanous {
34271b8b02a4SEd Tanous     *this = *this + y;
34281b8b02a4SEd Tanous     return *this;
34291b8b02a4SEd Tanous }
34301b8b02a4SEd Tanous 
34311b8b02a4SEd Tanous CONSTCD14
34321b8b02a4SEd Tanous inline
34331b8b02a4SEd Tanous year_month_weekday_last&
34341b8b02a4SEd Tanous year_month_weekday_last::operator-=(const years& y) NOEXCEPT
34351b8b02a4SEd Tanous {
34361b8b02a4SEd Tanous     *this = *this - y;
34371b8b02a4SEd Tanous     return *this;
34381b8b02a4SEd Tanous }
34391b8b02a4SEd Tanous 
34401b8b02a4SEd Tanous CONSTCD11 inline year year_month_weekday_last::year() const NOEXCEPT {return y_;}
34411b8b02a4SEd Tanous CONSTCD11 inline month year_month_weekday_last::month() const NOEXCEPT {return m_;}
34421b8b02a4SEd Tanous 
34431b8b02a4SEd Tanous CONSTCD11
34441b8b02a4SEd Tanous inline
34451b8b02a4SEd Tanous weekday
34461b8b02a4SEd Tanous year_month_weekday_last::weekday() const NOEXCEPT
34471b8b02a4SEd Tanous {
34481b8b02a4SEd Tanous     return wdl_.weekday();
34491b8b02a4SEd Tanous }
34501b8b02a4SEd Tanous 
34511b8b02a4SEd Tanous CONSTCD11
34521b8b02a4SEd Tanous inline
34531b8b02a4SEd Tanous weekday_last
34541b8b02a4SEd Tanous year_month_weekday_last::weekday_last() const NOEXCEPT
34551b8b02a4SEd Tanous {
34561b8b02a4SEd Tanous     return wdl_;
34571b8b02a4SEd Tanous }
34581b8b02a4SEd Tanous 
34591b8b02a4SEd Tanous CONSTCD14
34601b8b02a4SEd Tanous inline
34611b8b02a4SEd Tanous year_month_weekday_last::operator sys_days() const NOEXCEPT
34621b8b02a4SEd Tanous {
34631b8b02a4SEd Tanous     return sys_days{to_days()};
34641b8b02a4SEd Tanous }
34651b8b02a4SEd Tanous 
34661b8b02a4SEd Tanous CONSTCD14
34671b8b02a4SEd Tanous inline
34681b8b02a4SEd Tanous year_month_weekday_last::operator local_days() const NOEXCEPT
34691b8b02a4SEd Tanous {
34701b8b02a4SEd Tanous     return local_days{to_days()};
34711b8b02a4SEd Tanous }
34721b8b02a4SEd Tanous 
34731b8b02a4SEd Tanous CONSTCD11
34741b8b02a4SEd Tanous inline
34751b8b02a4SEd Tanous bool
34761b8b02a4SEd Tanous year_month_weekday_last::ok() const NOEXCEPT
34771b8b02a4SEd Tanous {
34781b8b02a4SEd Tanous     return y_.ok() && m_.ok() && wdl_.ok();
34791b8b02a4SEd Tanous }
34801b8b02a4SEd Tanous 
34811b8b02a4SEd Tanous CONSTCD14
34821b8b02a4SEd Tanous inline
34831b8b02a4SEd Tanous days
34841b8b02a4SEd Tanous year_month_weekday_last::to_days() const NOEXCEPT
34851b8b02a4SEd Tanous {
34861b8b02a4SEd Tanous     auto const d = sys_days(y_/m_/last);
34871b8b02a4SEd Tanous     return (d - (date::weekday{d} - wdl_.weekday())).time_since_epoch();
34881b8b02a4SEd Tanous }
34891b8b02a4SEd Tanous 
34901b8b02a4SEd Tanous CONSTCD11
34911b8b02a4SEd Tanous inline
34921b8b02a4SEd Tanous bool
34931b8b02a4SEd Tanous operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT
34941b8b02a4SEd Tanous {
34951b8b02a4SEd Tanous     return x.year() == y.year() && x.month() == y.month() &&
34961b8b02a4SEd Tanous            x.weekday_last() == y.weekday_last();
34971b8b02a4SEd Tanous }
34981b8b02a4SEd Tanous 
34991b8b02a4SEd Tanous CONSTCD11
35001b8b02a4SEd Tanous inline
35011b8b02a4SEd Tanous bool
35021b8b02a4SEd Tanous operator!=(const year_month_weekday_last& x, const year_month_weekday_last& y) NOEXCEPT
35031b8b02a4SEd Tanous {
35041b8b02a4SEd Tanous     return !(x == y);
35051b8b02a4SEd Tanous }
35061b8b02a4SEd Tanous 
35071b8b02a4SEd Tanous template<class CharT, class Traits>
35081b8b02a4SEd Tanous inline
35091b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
35101b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const year_month_weekday_last& ymwdl)
35111b8b02a4SEd Tanous {
35121b8b02a4SEd Tanous     detail::low_level_fmt(os, ymwdl.year()) << '/';
35131b8b02a4SEd Tanous     detail::low_level_fmt(os, ymwdl.month()) << '/';
35141b8b02a4SEd Tanous     detail::low_level_fmt(os, ymwdl.weekday_last());
35151b8b02a4SEd Tanous     if (!ymwdl.ok())
35161b8b02a4SEd Tanous         os << " is not a valid year_month_weekday_last";
35171b8b02a4SEd Tanous     return os;
35181b8b02a4SEd Tanous }
35191b8b02a4SEd Tanous 
35201b8b02a4SEd Tanous template<class>
35211b8b02a4SEd Tanous CONSTCD14
35221b8b02a4SEd Tanous inline
35231b8b02a4SEd Tanous year_month_weekday_last
35241b8b02a4SEd Tanous operator+(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT
35251b8b02a4SEd Tanous {
35261b8b02a4SEd Tanous     return (ymwdl.year() / ymwdl.month() + dm) / ymwdl.weekday_last();
35271b8b02a4SEd Tanous }
35281b8b02a4SEd Tanous 
35291b8b02a4SEd Tanous template<class>
35301b8b02a4SEd Tanous CONSTCD14
35311b8b02a4SEd Tanous inline
35321b8b02a4SEd Tanous year_month_weekday_last
35331b8b02a4SEd Tanous operator+(const months& dm, const year_month_weekday_last& ymwdl) NOEXCEPT
35341b8b02a4SEd Tanous {
35351b8b02a4SEd Tanous     return ymwdl + dm;
35361b8b02a4SEd Tanous }
35371b8b02a4SEd Tanous 
35381b8b02a4SEd Tanous template<class>
35391b8b02a4SEd Tanous CONSTCD14
35401b8b02a4SEd Tanous inline
35411b8b02a4SEd Tanous year_month_weekday_last
35421b8b02a4SEd Tanous operator-(const year_month_weekday_last& ymwdl, const months& dm) NOEXCEPT
35431b8b02a4SEd Tanous {
35441b8b02a4SEd Tanous     return ymwdl + (-dm);
35451b8b02a4SEd Tanous }
35461b8b02a4SEd Tanous 
35471b8b02a4SEd Tanous CONSTCD11
35481b8b02a4SEd Tanous inline
35491b8b02a4SEd Tanous year_month_weekday_last
35501b8b02a4SEd Tanous operator+(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT
35511b8b02a4SEd Tanous {
35521b8b02a4SEd Tanous     return {ymwdl.year()+dy, ymwdl.month(), ymwdl.weekday_last()};
35531b8b02a4SEd Tanous }
35541b8b02a4SEd Tanous 
35551b8b02a4SEd Tanous CONSTCD11
35561b8b02a4SEd Tanous inline
35571b8b02a4SEd Tanous year_month_weekday_last
35581b8b02a4SEd Tanous operator+(const years& dy, const year_month_weekday_last& ymwdl) NOEXCEPT
35591b8b02a4SEd Tanous {
35601b8b02a4SEd Tanous     return ymwdl + dy;
35611b8b02a4SEd Tanous }
35621b8b02a4SEd Tanous 
35631b8b02a4SEd Tanous CONSTCD11
35641b8b02a4SEd Tanous inline
35651b8b02a4SEd Tanous year_month_weekday_last
35661b8b02a4SEd Tanous operator-(const year_month_weekday_last& ymwdl, const years& dy) NOEXCEPT
35671b8b02a4SEd Tanous {
35681b8b02a4SEd Tanous     return ymwdl + (-dy);
35691b8b02a4SEd Tanous }
35701b8b02a4SEd Tanous 
35711b8b02a4SEd Tanous // year_month from operator/()
35721b8b02a4SEd Tanous 
35731b8b02a4SEd Tanous CONSTCD11
35741b8b02a4SEd Tanous inline
35751b8b02a4SEd Tanous year_month
35761b8b02a4SEd Tanous operator/(const year& y, const month& m) NOEXCEPT
35771b8b02a4SEd Tanous {
35781b8b02a4SEd Tanous     return {y, m};
35791b8b02a4SEd Tanous }
35801b8b02a4SEd Tanous 
35811b8b02a4SEd Tanous CONSTCD11
35821b8b02a4SEd Tanous inline
35831b8b02a4SEd Tanous year_month
35841b8b02a4SEd Tanous operator/(const year& y, int   m) NOEXCEPT
35851b8b02a4SEd Tanous {
35861b8b02a4SEd Tanous     return y / month(static_cast<unsigned>(m));
35871b8b02a4SEd Tanous }
35881b8b02a4SEd Tanous 
35891b8b02a4SEd Tanous // month_day from operator/()
35901b8b02a4SEd Tanous 
35911b8b02a4SEd Tanous CONSTCD11
35921b8b02a4SEd Tanous inline
35931b8b02a4SEd Tanous month_day
35941b8b02a4SEd Tanous operator/(const month& m, const day& d) NOEXCEPT
35951b8b02a4SEd Tanous {
35961b8b02a4SEd Tanous     return {m, d};
35971b8b02a4SEd Tanous }
35981b8b02a4SEd Tanous 
35991b8b02a4SEd Tanous CONSTCD11
36001b8b02a4SEd Tanous inline
36011b8b02a4SEd Tanous month_day
36021b8b02a4SEd Tanous operator/(const day& d, const month& m) NOEXCEPT
36031b8b02a4SEd Tanous {
36041b8b02a4SEd Tanous     return m / d;
36051b8b02a4SEd Tanous }
36061b8b02a4SEd Tanous 
36071b8b02a4SEd Tanous CONSTCD11
36081b8b02a4SEd Tanous inline
36091b8b02a4SEd Tanous month_day
36101b8b02a4SEd Tanous operator/(const month& m, int d) NOEXCEPT
36111b8b02a4SEd Tanous {
36121b8b02a4SEd Tanous     return m / day(static_cast<unsigned>(d));
36131b8b02a4SEd Tanous }
36141b8b02a4SEd Tanous 
36151b8b02a4SEd Tanous CONSTCD11
36161b8b02a4SEd Tanous inline
36171b8b02a4SEd Tanous month_day
36181b8b02a4SEd Tanous operator/(int m, const day& d) NOEXCEPT
36191b8b02a4SEd Tanous {
36201b8b02a4SEd Tanous     return month(static_cast<unsigned>(m)) / d;
36211b8b02a4SEd Tanous }
36221b8b02a4SEd Tanous 
36231b8b02a4SEd Tanous CONSTCD11 inline month_day operator/(const day& d, int m) NOEXCEPT {return m / d;}
36241b8b02a4SEd Tanous 
36251b8b02a4SEd Tanous // month_day_last from operator/()
36261b8b02a4SEd Tanous 
36271b8b02a4SEd Tanous CONSTCD11
36281b8b02a4SEd Tanous inline
36291b8b02a4SEd Tanous month_day_last
36301b8b02a4SEd Tanous operator/(const month& m, last_spec) NOEXCEPT
36311b8b02a4SEd Tanous {
36321b8b02a4SEd Tanous     return month_day_last{m};
36331b8b02a4SEd Tanous }
36341b8b02a4SEd Tanous 
36351b8b02a4SEd Tanous CONSTCD11
36361b8b02a4SEd Tanous inline
36371b8b02a4SEd Tanous month_day_last
36381b8b02a4SEd Tanous operator/(last_spec, const month& m) NOEXCEPT
36391b8b02a4SEd Tanous {
36401b8b02a4SEd Tanous     return m/last;
36411b8b02a4SEd Tanous }
36421b8b02a4SEd Tanous 
36431b8b02a4SEd Tanous CONSTCD11
36441b8b02a4SEd Tanous inline
36451b8b02a4SEd Tanous month_day_last
36461b8b02a4SEd Tanous operator/(int m, last_spec) NOEXCEPT
36471b8b02a4SEd Tanous {
36481b8b02a4SEd Tanous     return month(static_cast<unsigned>(m))/last;
36491b8b02a4SEd Tanous }
36501b8b02a4SEd Tanous 
36511b8b02a4SEd Tanous CONSTCD11
36521b8b02a4SEd Tanous inline
36531b8b02a4SEd Tanous month_day_last
36541b8b02a4SEd Tanous operator/(last_spec, int m) NOEXCEPT
36551b8b02a4SEd Tanous {
36561b8b02a4SEd Tanous     return m/last;
36571b8b02a4SEd Tanous }
36581b8b02a4SEd Tanous 
36591b8b02a4SEd Tanous // month_weekday from operator/()
36601b8b02a4SEd Tanous 
36611b8b02a4SEd Tanous CONSTCD11
36621b8b02a4SEd Tanous inline
36631b8b02a4SEd Tanous month_weekday
36641b8b02a4SEd Tanous operator/(const month& m, const weekday_indexed& wdi) NOEXCEPT
36651b8b02a4SEd Tanous {
36661b8b02a4SEd Tanous     return {m, wdi};
36671b8b02a4SEd Tanous }
36681b8b02a4SEd Tanous 
36691b8b02a4SEd Tanous CONSTCD11
36701b8b02a4SEd Tanous inline
36711b8b02a4SEd Tanous month_weekday
36721b8b02a4SEd Tanous operator/(const weekday_indexed& wdi, const month& m) NOEXCEPT
36731b8b02a4SEd Tanous {
36741b8b02a4SEd Tanous     return m / wdi;
36751b8b02a4SEd Tanous }
36761b8b02a4SEd Tanous 
36771b8b02a4SEd Tanous CONSTCD11
36781b8b02a4SEd Tanous inline
36791b8b02a4SEd Tanous month_weekday
36801b8b02a4SEd Tanous operator/(int m, const weekday_indexed& wdi) NOEXCEPT
36811b8b02a4SEd Tanous {
36821b8b02a4SEd Tanous     return month(static_cast<unsigned>(m)) / wdi;
36831b8b02a4SEd Tanous }
36841b8b02a4SEd Tanous 
36851b8b02a4SEd Tanous CONSTCD11
36861b8b02a4SEd Tanous inline
36871b8b02a4SEd Tanous month_weekday
36881b8b02a4SEd Tanous operator/(const weekday_indexed& wdi, int m) NOEXCEPT
36891b8b02a4SEd Tanous {
36901b8b02a4SEd Tanous     return m / wdi;
36911b8b02a4SEd Tanous }
36921b8b02a4SEd Tanous 
36931b8b02a4SEd Tanous // month_weekday_last from operator/()
36941b8b02a4SEd Tanous 
36951b8b02a4SEd Tanous CONSTCD11
36961b8b02a4SEd Tanous inline
36971b8b02a4SEd Tanous month_weekday_last
36981b8b02a4SEd Tanous operator/(const month& m, const weekday_last& wdl) NOEXCEPT
36991b8b02a4SEd Tanous {
37001b8b02a4SEd Tanous     return {m, wdl};
37011b8b02a4SEd Tanous }
37021b8b02a4SEd Tanous 
37031b8b02a4SEd Tanous CONSTCD11
37041b8b02a4SEd Tanous inline
37051b8b02a4SEd Tanous month_weekday_last
37061b8b02a4SEd Tanous operator/(const weekday_last& wdl, const month& m) NOEXCEPT
37071b8b02a4SEd Tanous {
37081b8b02a4SEd Tanous     return m / wdl;
37091b8b02a4SEd Tanous }
37101b8b02a4SEd Tanous 
37111b8b02a4SEd Tanous CONSTCD11
37121b8b02a4SEd Tanous inline
37131b8b02a4SEd Tanous month_weekday_last
37141b8b02a4SEd Tanous operator/(int m, const weekday_last& wdl) NOEXCEPT
37151b8b02a4SEd Tanous {
37161b8b02a4SEd Tanous     return month(static_cast<unsigned>(m)) / wdl;
37171b8b02a4SEd Tanous }
37181b8b02a4SEd Tanous 
37191b8b02a4SEd Tanous CONSTCD11
37201b8b02a4SEd Tanous inline
37211b8b02a4SEd Tanous month_weekday_last
37221b8b02a4SEd Tanous operator/(const weekday_last& wdl, int m) NOEXCEPT
37231b8b02a4SEd Tanous {
37241b8b02a4SEd Tanous     return m / wdl;
37251b8b02a4SEd Tanous }
37261b8b02a4SEd Tanous 
37271b8b02a4SEd Tanous // year_month_day from operator/()
37281b8b02a4SEd Tanous 
37291b8b02a4SEd Tanous CONSTCD11
37301b8b02a4SEd Tanous inline
37311b8b02a4SEd Tanous year_month_day
37321b8b02a4SEd Tanous operator/(const year_month& ym, const day& d) NOEXCEPT
37331b8b02a4SEd Tanous {
37341b8b02a4SEd Tanous     return {ym.year(), ym.month(), d};
37351b8b02a4SEd Tanous }
37361b8b02a4SEd Tanous 
37371b8b02a4SEd Tanous CONSTCD11
37381b8b02a4SEd Tanous inline
37391b8b02a4SEd Tanous year_month_day
37401b8b02a4SEd Tanous operator/(const year_month& ym, int d)  NOEXCEPT
37411b8b02a4SEd Tanous {
37421b8b02a4SEd Tanous     return ym / day(static_cast<unsigned>(d));
37431b8b02a4SEd Tanous }
37441b8b02a4SEd Tanous 
37451b8b02a4SEd Tanous CONSTCD11
37461b8b02a4SEd Tanous inline
37471b8b02a4SEd Tanous year_month_day
37481b8b02a4SEd Tanous operator/(const year& y, const month_day& md) NOEXCEPT
37491b8b02a4SEd Tanous {
37501b8b02a4SEd Tanous     return y / md.month() / md.day();
37511b8b02a4SEd Tanous }
37521b8b02a4SEd Tanous 
37531b8b02a4SEd Tanous CONSTCD11
37541b8b02a4SEd Tanous inline
37551b8b02a4SEd Tanous year_month_day
37561b8b02a4SEd Tanous operator/(int y, const month_day& md) NOEXCEPT
37571b8b02a4SEd Tanous {
37581b8b02a4SEd Tanous     return year(y) / md;
37591b8b02a4SEd Tanous }
37601b8b02a4SEd Tanous 
37611b8b02a4SEd Tanous CONSTCD11
37621b8b02a4SEd Tanous inline
37631b8b02a4SEd Tanous year_month_day
37641b8b02a4SEd Tanous operator/(const month_day& md, const year& y)  NOEXCEPT
37651b8b02a4SEd Tanous {
37661b8b02a4SEd Tanous     return y / md;
37671b8b02a4SEd Tanous }
37681b8b02a4SEd Tanous 
37691b8b02a4SEd Tanous CONSTCD11
37701b8b02a4SEd Tanous inline
37711b8b02a4SEd Tanous year_month_day
37721b8b02a4SEd Tanous operator/(const month_day& md, int y) NOEXCEPT
37731b8b02a4SEd Tanous {
37741b8b02a4SEd Tanous     return year(y) / md;
37751b8b02a4SEd Tanous }
37761b8b02a4SEd Tanous 
37771b8b02a4SEd Tanous // year_month_day_last from operator/()
37781b8b02a4SEd Tanous 
37791b8b02a4SEd Tanous CONSTCD11
37801b8b02a4SEd Tanous inline
37811b8b02a4SEd Tanous year_month_day_last
37821b8b02a4SEd Tanous operator/(const year_month& ym, last_spec) NOEXCEPT
37831b8b02a4SEd Tanous {
37841b8b02a4SEd Tanous     return {ym.year(), month_day_last{ym.month()}};
37851b8b02a4SEd Tanous }
37861b8b02a4SEd Tanous 
37871b8b02a4SEd Tanous CONSTCD11
37881b8b02a4SEd Tanous inline
37891b8b02a4SEd Tanous year_month_day_last
37901b8b02a4SEd Tanous operator/(const year& y, const month_day_last& mdl) NOEXCEPT
37911b8b02a4SEd Tanous {
37921b8b02a4SEd Tanous     return {y, mdl};
37931b8b02a4SEd Tanous }
37941b8b02a4SEd Tanous 
37951b8b02a4SEd Tanous CONSTCD11
37961b8b02a4SEd Tanous inline
37971b8b02a4SEd Tanous year_month_day_last
37981b8b02a4SEd Tanous operator/(int y, const month_day_last& mdl) NOEXCEPT
37991b8b02a4SEd Tanous {
38001b8b02a4SEd Tanous     return year(y) / mdl;
38011b8b02a4SEd Tanous }
38021b8b02a4SEd Tanous 
38031b8b02a4SEd Tanous CONSTCD11
38041b8b02a4SEd Tanous inline
38051b8b02a4SEd Tanous year_month_day_last
38061b8b02a4SEd Tanous operator/(const month_day_last& mdl, const year& y) NOEXCEPT
38071b8b02a4SEd Tanous {
38081b8b02a4SEd Tanous     return y / mdl;
38091b8b02a4SEd Tanous }
38101b8b02a4SEd Tanous 
38111b8b02a4SEd Tanous CONSTCD11
38121b8b02a4SEd Tanous inline
38131b8b02a4SEd Tanous year_month_day_last
38141b8b02a4SEd Tanous operator/(const month_day_last& mdl, int y) NOEXCEPT
38151b8b02a4SEd Tanous {
38161b8b02a4SEd Tanous     return year(y) / mdl;
38171b8b02a4SEd Tanous }
38181b8b02a4SEd Tanous 
38191b8b02a4SEd Tanous // year_month_weekday from operator/()
38201b8b02a4SEd Tanous 
38211b8b02a4SEd Tanous CONSTCD11
38221b8b02a4SEd Tanous inline
38231b8b02a4SEd Tanous year_month_weekday
38241b8b02a4SEd Tanous operator/(const year_month& ym, const weekday_indexed& wdi) NOEXCEPT
38251b8b02a4SEd Tanous {
38261b8b02a4SEd Tanous     return {ym.year(), ym.month(), wdi};
38271b8b02a4SEd Tanous }
38281b8b02a4SEd Tanous 
38291b8b02a4SEd Tanous CONSTCD11
38301b8b02a4SEd Tanous inline
38311b8b02a4SEd Tanous year_month_weekday
38321b8b02a4SEd Tanous operator/(const year& y, const month_weekday& mwd) NOEXCEPT
38331b8b02a4SEd Tanous {
38341b8b02a4SEd Tanous     return {y, mwd.month(), mwd.weekday_indexed()};
38351b8b02a4SEd Tanous }
38361b8b02a4SEd Tanous 
38371b8b02a4SEd Tanous CONSTCD11
38381b8b02a4SEd Tanous inline
38391b8b02a4SEd Tanous year_month_weekday
38401b8b02a4SEd Tanous operator/(int y, const month_weekday& mwd) NOEXCEPT
38411b8b02a4SEd Tanous {
38421b8b02a4SEd Tanous     return year(y) / mwd;
38431b8b02a4SEd Tanous }
38441b8b02a4SEd Tanous 
38451b8b02a4SEd Tanous CONSTCD11
38461b8b02a4SEd Tanous inline
38471b8b02a4SEd Tanous year_month_weekday
38481b8b02a4SEd Tanous operator/(const month_weekday& mwd, const year& y) NOEXCEPT
38491b8b02a4SEd Tanous {
38501b8b02a4SEd Tanous     return y / mwd;
38511b8b02a4SEd Tanous }
38521b8b02a4SEd Tanous 
38531b8b02a4SEd Tanous CONSTCD11
38541b8b02a4SEd Tanous inline
38551b8b02a4SEd Tanous year_month_weekday
38561b8b02a4SEd Tanous operator/(const month_weekday& mwd, int y) NOEXCEPT
38571b8b02a4SEd Tanous {
38581b8b02a4SEd Tanous     return year(y) / mwd;
38591b8b02a4SEd Tanous }
38601b8b02a4SEd Tanous 
38611b8b02a4SEd Tanous // year_month_weekday_last from operator/()
38621b8b02a4SEd Tanous 
38631b8b02a4SEd Tanous CONSTCD11
38641b8b02a4SEd Tanous inline
38651b8b02a4SEd Tanous year_month_weekday_last
38661b8b02a4SEd Tanous operator/(const year_month& ym, const weekday_last& wdl) NOEXCEPT
38671b8b02a4SEd Tanous {
38681b8b02a4SEd Tanous     return {ym.year(), ym.month(), wdl};
38691b8b02a4SEd Tanous }
38701b8b02a4SEd Tanous 
38711b8b02a4SEd Tanous CONSTCD11
38721b8b02a4SEd Tanous inline
38731b8b02a4SEd Tanous year_month_weekday_last
38741b8b02a4SEd Tanous operator/(const year& y, const month_weekday_last& mwdl) NOEXCEPT
38751b8b02a4SEd Tanous {
38761b8b02a4SEd Tanous     return {y, mwdl.month(), mwdl.weekday_last()};
38771b8b02a4SEd Tanous }
38781b8b02a4SEd Tanous 
38791b8b02a4SEd Tanous CONSTCD11
38801b8b02a4SEd Tanous inline
38811b8b02a4SEd Tanous year_month_weekday_last
38821b8b02a4SEd Tanous operator/(int y, const month_weekday_last& mwdl) NOEXCEPT
38831b8b02a4SEd Tanous {
38841b8b02a4SEd Tanous     return year(y) / mwdl;
38851b8b02a4SEd Tanous }
38861b8b02a4SEd Tanous 
38871b8b02a4SEd Tanous CONSTCD11
38881b8b02a4SEd Tanous inline
38891b8b02a4SEd Tanous year_month_weekday_last
38901b8b02a4SEd Tanous operator/(const month_weekday_last& mwdl, const year& y) NOEXCEPT
38911b8b02a4SEd Tanous {
38921b8b02a4SEd Tanous     return y / mwdl;
38931b8b02a4SEd Tanous }
38941b8b02a4SEd Tanous 
38951b8b02a4SEd Tanous CONSTCD11
38961b8b02a4SEd Tanous inline
38971b8b02a4SEd Tanous year_month_weekday_last
38981b8b02a4SEd Tanous operator/(const month_weekday_last& mwdl, int y) NOEXCEPT
38991b8b02a4SEd Tanous {
39001b8b02a4SEd Tanous     return year(y) / mwdl;
39011b8b02a4SEd Tanous }
39021b8b02a4SEd Tanous 
39031b8b02a4SEd Tanous template <class Duration>
39041b8b02a4SEd Tanous struct fields;
39051b8b02a4SEd Tanous 
39061b8b02a4SEd Tanous template <class CharT, class Traits, class Duration>
39071b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
39081b8b02a4SEd Tanous to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
39091b8b02a4SEd Tanous           const fields<Duration>& fds, const std::string* abbrev = nullptr,
39101b8b02a4SEd Tanous           const std::chrono::seconds* offset_sec = nullptr);
39111b8b02a4SEd Tanous 
39121b8b02a4SEd Tanous template <class CharT, class Traits, class Duration, class Alloc>
39131b8b02a4SEd Tanous std::basic_istream<CharT, Traits>&
39141b8b02a4SEd Tanous from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
39151b8b02a4SEd Tanous             fields<Duration>& fds, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
39161b8b02a4SEd Tanous             std::chrono::minutes* offset = nullptr);
39171b8b02a4SEd Tanous 
39181b8b02a4SEd Tanous // hh_mm_ss
39191b8b02a4SEd Tanous 
39201b8b02a4SEd Tanous namespace detail
39211b8b02a4SEd Tanous {
39221b8b02a4SEd Tanous 
39231b8b02a4SEd Tanous struct undocumented {explicit undocumented() = default;};
39241b8b02a4SEd Tanous 
39251b8b02a4SEd Tanous // width<n>::value is the number of fractional decimal digits in 1/n
39261b8b02a4SEd Tanous // width<0>::value and width<1>::value are defined to be 0
39271b8b02a4SEd Tanous // If 1/n takes more than 18 fractional decimal digits,
39281b8b02a4SEd Tanous //   the result is truncated to 19.
39291b8b02a4SEd Tanous // Example:  width<2>::value    ==  1
39301b8b02a4SEd Tanous // Example:  width<3>::value    == 19
39311b8b02a4SEd Tanous // Example:  width<4>::value    ==  2
39321b8b02a4SEd Tanous // Example:  width<10>::value   ==  1
39331b8b02a4SEd Tanous // Example:  width<1000>::value ==  3
39341b8b02a4SEd Tanous template <std::uint64_t n, std::uint64_t d, unsigned w = 0,
39351b8b02a4SEd Tanous           bool should_continue = n%d != 0 && (w < 19)>
39361b8b02a4SEd Tanous struct width
39371b8b02a4SEd Tanous {
39381b8b02a4SEd Tanous     static_assert(d > 0, "width called with zero denominator");
39391b8b02a4SEd Tanous     static CONSTDATA unsigned value = 1 + width<n%d*10, d, w+1>::value;
39401b8b02a4SEd Tanous };
39411b8b02a4SEd Tanous 
39421b8b02a4SEd Tanous template <std::uint64_t n, std::uint64_t d, unsigned w>
39431b8b02a4SEd Tanous struct width<n, d, w, false>
39441b8b02a4SEd Tanous {
39451b8b02a4SEd Tanous     static CONSTDATA unsigned value = 0;
39461b8b02a4SEd Tanous };
39471b8b02a4SEd Tanous 
39481b8b02a4SEd Tanous template <unsigned exp>
39491b8b02a4SEd Tanous struct static_pow10
39501b8b02a4SEd Tanous {
39511b8b02a4SEd Tanous private:
39521b8b02a4SEd Tanous     static CONSTDATA std::uint64_t h = static_pow10<exp/2>::value;
39531b8b02a4SEd Tanous public:
39541b8b02a4SEd Tanous     static CONSTDATA std::uint64_t value = h * h * (exp % 2 ? 10 : 1);
39551b8b02a4SEd Tanous };
39561b8b02a4SEd Tanous 
39571b8b02a4SEd Tanous template <>
39581b8b02a4SEd Tanous struct static_pow10<0>
39591b8b02a4SEd Tanous {
39601b8b02a4SEd Tanous     static CONSTDATA std::uint64_t value = 1;
39611b8b02a4SEd Tanous };
39621b8b02a4SEd Tanous 
39631b8b02a4SEd Tanous template <class Duration>
39641b8b02a4SEd Tanous class decimal_format_seconds
39651b8b02a4SEd Tanous {
39661b8b02a4SEd Tanous     using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
39671b8b02a4SEd Tanous     using rep = typename CT::rep;
39681b8b02a4SEd Tanous     static unsigned CONSTDATA trial_width =
39691b8b02a4SEd Tanous         detail::width<CT::period::num, CT::period::den>::value;
39701b8b02a4SEd Tanous public:
39711b8b02a4SEd Tanous     static unsigned CONSTDATA width = trial_width < 19 ? trial_width : 6u;
39721b8b02a4SEd Tanous     using precision = std::chrono::duration<rep,
39731b8b02a4SEd Tanous                                             std::ratio<1, static_pow10<width>::value>>;
39741b8b02a4SEd Tanous 
39751b8b02a4SEd Tanous private:
39761b8b02a4SEd Tanous     std::chrono::seconds s_;
39771b8b02a4SEd Tanous     precision            sub_s_;
39781b8b02a4SEd Tanous 
39791b8b02a4SEd Tanous public:
39801b8b02a4SEd Tanous     CONSTCD11 decimal_format_seconds()
39811b8b02a4SEd Tanous         : s_()
39821b8b02a4SEd Tanous         , sub_s_()
39831b8b02a4SEd Tanous         {}
39841b8b02a4SEd Tanous 
39851b8b02a4SEd Tanous     CONSTCD11 explicit decimal_format_seconds(const Duration& d) NOEXCEPT
39861b8b02a4SEd Tanous         : s_(std::chrono::duration_cast<std::chrono::seconds>(d))
39871b8b02a4SEd Tanous         , sub_s_(std::chrono::duration_cast<precision>(d - s_))
39881b8b02a4SEd Tanous         {}
39891b8b02a4SEd Tanous 
39901b8b02a4SEd Tanous     CONSTCD14 std::chrono::seconds& seconds() NOEXCEPT {return s_;}
39911b8b02a4SEd Tanous     CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_;}
39921b8b02a4SEd Tanous     CONSTCD11 precision subseconds() const NOEXCEPT {return sub_s_;}
39931b8b02a4SEd Tanous 
39941b8b02a4SEd Tanous     CONSTCD14 precision to_duration() const NOEXCEPT
39951b8b02a4SEd Tanous     {
39961b8b02a4SEd Tanous         return s_ + sub_s_;
39971b8b02a4SEd Tanous     }
39981b8b02a4SEd Tanous 
39991b8b02a4SEd Tanous     CONSTCD11 bool in_conventional_range() const NOEXCEPT
40001b8b02a4SEd Tanous     {
40011b8b02a4SEd Tanous         return sub_s_ < std::chrono::seconds{1} && s_ < std::chrono::minutes{1};
40021b8b02a4SEd Tanous     }
40031b8b02a4SEd Tanous 
40041b8b02a4SEd Tanous     template <class CharT, class Traits>
40051b8b02a4SEd Tanous     friend
40061b8b02a4SEd Tanous     std::basic_ostream<CharT, Traits>&
40071b8b02a4SEd Tanous     operator<<(std::basic_ostream<CharT, Traits>& os, const decimal_format_seconds& x)
40081b8b02a4SEd Tanous     {
40091b8b02a4SEd Tanous         return x.print(os, std::chrono::treat_as_floating_point<rep>{});
40101b8b02a4SEd Tanous     }
40111b8b02a4SEd Tanous 
40121b8b02a4SEd Tanous     template <class CharT, class Traits>
40131b8b02a4SEd Tanous     std::basic_ostream<CharT, Traits>&
40141b8b02a4SEd Tanous     print(std::basic_ostream<CharT, Traits>& os, std::true_type) const
40151b8b02a4SEd Tanous     {
40161b8b02a4SEd Tanous         date::detail::save_ostream<CharT, Traits> _(os);
40171b8b02a4SEd Tanous         std::chrono::duration<rep> d = s_ + sub_s_;
40181b8b02a4SEd Tanous         if (d < std::chrono::seconds{10})
40191b8b02a4SEd Tanous             os << '0';
40201b8b02a4SEd Tanous         os.precision(width+6);
40211b8b02a4SEd Tanous         os << std::fixed << d.count();
40221b8b02a4SEd Tanous         return os;
40231b8b02a4SEd Tanous     }
40241b8b02a4SEd Tanous 
40251b8b02a4SEd Tanous     template <class CharT, class Traits>
40261b8b02a4SEd Tanous     std::basic_ostream<CharT, Traits>&
40271b8b02a4SEd Tanous     print(std::basic_ostream<CharT, Traits>& os, std::false_type) const
40281b8b02a4SEd Tanous     {
40291b8b02a4SEd Tanous         date::detail::save_ostream<CharT, Traits> _(os);
40301b8b02a4SEd Tanous         os.fill('0');
40311b8b02a4SEd Tanous         os.flags(std::ios::dec | std::ios::right);
40321b8b02a4SEd Tanous         os.width(2);
40331b8b02a4SEd Tanous         os << s_.count();
40341b8b02a4SEd Tanous         if (width > 0)
40351b8b02a4SEd Tanous         {
40361b8b02a4SEd Tanous #if !ONLY_C_LOCALE
40371b8b02a4SEd Tanous             os << std::use_facet<std::numpunct<CharT>>(os.getloc()).decimal_point();
40381b8b02a4SEd Tanous #else
40391b8b02a4SEd Tanous             os << '.';
40401b8b02a4SEd Tanous #endif
40411b8b02a4SEd Tanous             date::detail::save_ostream<CharT, Traits> _s(os);
40421b8b02a4SEd Tanous             os.imbue(std::locale::classic());
40431b8b02a4SEd Tanous             os.width(width);
40441b8b02a4SEd Tanous             os << sub_s_.count();
40451b8b02a4SEd Tanous         }
40461b8b02a4SEd Tanous         return os;
40471b8b02a4SEd Tanous     }
40481b8b02a4SEd Tanous };
40491b8b02a4SEd Tanous 
40501b8b02a4SEd Tanous template <class Rep, class Period>
40511b8b02a4SEd Tanous inline
40521b8b02a4SEd Tanous CONSTCD11
40531b8b02a4SEd Tanous typename std::enable_if
40541b8b02a4SEd Tanous          <
40551b8b02a4SEd Tanous             std::numeric_limits<Rep>::is_signed,
40561b8b02a4SEd Tanous             std::chrono::duration<Rep, Period>
40571b8b02a4SEd Tanous          >::type
40581b8b02a4SEd Tanous abs(std::chrono::duration<Rep, Period> d)
40591b8b02a4SEd Tanous {
40601b8b02a4SEd Tanous     return d >= d.zero() ? +d : -d;
40611b8b02a4SEd Tanous }
40621b8b02a4SEd Tanous 
40631b8b02a4SEd Tanous template <class Rep, class Period>
40641b8b02a4SEd Tanous inline
40651b8b02a4SEd Tanous CONSTCD11
40661b8b02a4SEd Tanous typename std::enable_if
40671b8b02a4SEd Tanous          <
40681b8b02a4SEd Tanous             !std::numeric_limits<Rep>::is_signed,
40691b8b02a4SEd Tanous             std::chrono::duration<Rep, Period>
40701b8b02a4SEd Tanous          >::type
40711b8b02a4SEd Tanous abs(std::chrono::duration<Rep, Period> d)
40721b8b02a4SEd Tanous {
40731b8b02a4SEd Tanous     return d;
40741b8b02a4SEd Tanous }
40751b8b02a4SEd Tanous 
40761b8b02a4SEd Tanous }  // namespace detail
40771b8b02a4SEd Tanous 
40781b8b02a4SEd Tanous template <class Duration>
40791b8b02a4SEd Tanous class hh_mm_ss
40801b8b02a4SEd Tanous {
40811b8b02a4SEd Tanous     using dfs = detail::decimal_format_seconds<typename std::common_type<Duration,
40821b8b02a4SEd Tanous                                                std::chrono::seconds>::type>;
40831b8b02a4SEd Tanous 
40841b8b02a4SEd Tanous     std::chrono::hours h_;
40851b8b02a4SEd Tanous     std::chrono::minutes m_;
40861b8b02a4SEd Tanous     dfs s_;
40871b8b02a4SEd Tanous     bool neg_;
40881b8b02a4SEd Tanous 
40891b8b02a4SEd Tanous public:
40901b8b02a4SEd Tanous     static unsigned CONSTDATA fractional_width = dfs::width;
40911b8b02a4SEd Tanous     using precision = typename dfs::precision;
40921b8b02a4SEd Tanous 
40931b8b02a4SEd Tanous     CONSTCD11 hh_mm_ss() NOEXCEPT
40941b8b02a4SEd Tanous         : hh_mm_ss(Duration::zero())
40951b8b02a4SEd Tanous         {}
40961b8b02a4SEd Tanous 
40971b8b02a4SEd Tanous     CONSTCD11 explicit hh_mm_ss(Duration d) NOEXCEPT
40981b8b02a4SEd Tanous         : h_(std::chrono::duration_cast<std::chrono::hours>(detail::abs(d)))
40991b8b02a4SEd Tanous         , m_(std::chrono::duration_cast<std::chrono::minutes>(detail::abs(d)) - h_)
41001b8b02a4SEd Tanous         , s_(detail::abs(d) - h_ - m_)
41011b8b02a4SEd Tanous         , neg_(d < Duration::zero())
41021b8b02a4SEd Tanous         {}
41031b8b02a4SEd Tanous 
41041b8b02a4SEd Tanous     CONSTCD11 std::chrono::hours hours() const NOEXCEPT {return h_;}
41051b8b02a4SEd Tanous     CONSTCD11 std::chrono::minutes minutes() const NOEXCEPT {return m_;}
41061b8b02a4SEd Tanous     CONSTCD11 std::chrono::seconds seconds() const NOEXCEPT {return s_.seconds();}
41071b8b02a4SEd Tanous     CONSTCD14 std::chrono::seconds&
41081b8b02a4SEd Tanous         seconds(detail::undocumented) NOEXCEPT {return s_.seconds();}
41091b8b02a4SEd Tanous     CONSTCD11 precision subseconds() const NOEXCEPT {return s_.subseconds();}
41101b8b02a4SEd Tanous     CONSTCD11 bool is_negative() const NOEXCEPT {return neg_;}
41111b8b02a4SEd Tanous 
41121b8b02a4SEd Tanous     CONSTCD11 explicit operator  precision()   const NOEXCEPT {return to_duration();}
41131b8b02a4SEd Tanous     CONSTCD11          precision to_duration() const NOEXCEPT
41141b8b02a4SEd Tanous         {return (s_.to_duration() + m_ + h_) * (1-2*neg_);}
41151b8b02a4SEd Tanous 
41161b8b02a4SEd Tanous     CONSTCD11 bool in_conventional_range() const NOEXCEPT
41171b8b02a4SEd Tanous     {
41181b8b02a4SEd Tanous         return !neg_ && h_ < days{1} && m_ < std::chrono::hours{1} &&
41191b8b02a4SEd Tanous                s_.in_conventional_range();
41201b8b02a4SEd Tanous     }
41211b8b02a4SEd Tanous 
41221b8b02a4SEd Tanous private:
41231b8b02a4SEd Tanous 
41241b8b02a4SEd Tanous     template <class charT, class traits>
41251b8b02a4SEd Tanous     friend
41261b8b02a4SEd Tanous     std::basic_ostream<charT, traits>&
41271b8b02a4SEd Tanous     operator<<(std::basic_ostream<charT, traits>& os, hh_mm_ss const& tod)
41281b8b02a4SEd Tanous     {
41291b8b02a4SEd Tanous         if (tod.is_negative())
41301b8b02a4SEd Tanous             os << '-';
41311b8b02a4SEd Tanous         if (tod.h_ < std::chrono::hours{10})
41321b8b02a4SEd Tanous             os << '0';
41331b8b02a4SEd Tanous         os << tod.h_.count() << ':';
41341b8b02a4SEd Tanous         if (tod.m_ < std::chrono::minutes{10})
41351b8b02a4SEd Tanous             os << '0';
41361b8b02a4SEd Tanous         os << tod.m_.count() << ':' << tod.s_;
41371b8b02a4SEd Tanous         return os;
41381b8b02a4SEd Tanous     }
41391b8b02a4SEd Tanous 
41401b8b02a4SEd Tanous     template <class CharT, class Traits, class Duration2>
41411b8b02a4SEd Tanous     friend
41421b8b02a4SEd Tanous     std::basic_ostream<CharT, Traits>&
41431b8b02a4SEd Tanous     date::to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
41441b8b02a4SEd Tanous           const fields<Duration2>& fds, const std::string* abbrev,
41451b8b02a4SEd Tanous           const std::chrono::seconds* offset_sec);
41461b8b02a4SEd Tanous 
41471b8b02a4SEd Tanous     template <class CharT, class Traits, class Duration2, class Alloc>
41481b8b02a4SEd Tanous     friend
41491b8b02a4SEd Tanous     std::basic_istream<CharT, Traits>&
41501b8b02a4SEd Tanous     date::from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
41511b8b02a4SEd Tanous           fields<Duration2>& fds,
41521b8b02a4SEd Tanous           std::basic_string<CharT, Traits, Alloc>* abbrev, std::chrono::minutes* offset);
41531b8b02a4SEd Tanous };
41541b8b02a4SEd Tanous 
41551b8b02a4SEd Tanous inline
41561b8b02a4SEd Tanous CONSTCD14
41571b8b02a4SEd Tanous bool
41581b8b02a4SEd Tanous is_am(std::chrono::hours const& h) NOEXCEPT
41591b8b02a4SEd Tanous {
41601b8b02a4SEd Tanous     using std::chrono::hours;
41611b8b02a4SEd Tanous     return hours{0} <= h && h < hours{12};
41621b8b02a4SEd Tanous }
41631b8b02a4SEd Tanous 
41641b8b02a4SEd Tanous inline
41651b8b02a4SEd Tanous CONSTCD14
41661b8b02a4SEd Tanous bool
41671b8b02a4SEd Tanous is_pm(std::chrono::hours const& h) NOEXCEPT
41681b8b02a4SEd Tanous {
41691b8b02a4SEd Tanous     using std::chrono::hours;
41701b8b02a4SEd Tanous     return hours{12} <= h && h < hours{24};
41711b8b02a4SEd Tanous }
41721b8b02a4SEd Tanous 
41731b8b02a4SEd Tanous inline
41741b8b02a4SEd Tanous CONSTCD14
41751b8b02a4SEd Tanous std::chrono::hours
41761b8b02a4SEd Tanous make12(std::chrono::hours h) NOEXCEPT
41771b8b02a4SEd Tanous {
41781b8b02a4SEd Tanous     using std::chrono::hours;
41791b8b02a4SEd Tanous     if (h < hours{12})
41801b8b02a4SEd Tanous     {
41811b8b02a4SEd Tanous         if (h == hours{0})
41821b8b02a4SEd Tanous             h = hours{12};
41831b8b02a4SEd Tanous     }
41841b8b02a4SEd Tanous     else
41851b8b02a4SEd Tanous     {
41861b8b02a4SEd Tanous         if (h != hours{12})
41871b8b02a4SEd Tanous             h = h - hours{12};
41881b8b02a4SEd Tanous     }
41891b8b02a4SEd Tanous     return h;
41901b8b02a4SEd Tanous }
41911b8b02a4SEd Tanous 
41921b8b02a4SEd Tanous inline
41931b8b02a4SEd Tanous CONSTCD14
41941b8b02a4SEd Tanous std::chrono::hours
41951b8b02a4SEd Tanous make24(std::chrono::hours h, bool is_pm) NOEXCEPT
41961b8b02a4SEd Tanous {
41971b8b02a4SEd Tanous     using std::chrono::hours;
41981b8b02a4SEd Tanous     if (is_pm)
41991b8b02a4SEd Tanous     {
42001b8b02a4SEd Tanous         if (h != hours{12})
42011b8b02a4SEd Tanous             h = h + hours{12};
42021b8b02a4SEd Tanous     }
42031b8b02a4SEd Tanous     else if (h == hours{12})
42041b8b02a4SEd Tanous         h = hours{0};
42051b8b02a4SEd Tanous     return h;
42061b8b02a4SEd Tanous }
42071b8b02a4SEd Tanous 
42081b8b02a4SEd Tanous template <class Duration>
42091b8b02a4SEd Tanous using time_of_day = hh_mm_ss<Duration>;
42101b8b02a4SEd Tanous 
42111b8b02a4SEd Tanous template <class Rep, class Period>
42121b8b02a4SEd Tanous CONSTCD11
42131b8b02a4SEd Tanous inline
42141b8b02a4SEd Tanous hh_mm_ss<std::chrono::duration<Rep, Period>>
42151b8b02a4SEd Tanous make_time(const std::chrono::duration<Rep, Period>& d)
42161b8b02a4SEd Tanous {
42171b8b02a4SEd Tanous     return hh_mm_ss<std::chrono::duration<Rep, Period>>(d);
42181b8b02a4SEd Tanous }
42191b8b02a4SEd Tanous 
42201b8b02a4SEd Tanous template <class CharT, class Traits, class Duration>
42211b8b02a4SEd Tanous inline
42221b8b02a4SEd Tanous typename std::enable_if
42231b8b02a4SEd Tanous <
42241b8b02a4SEd Tanous     !std::is_convertible<Duration, days>::value,
42251b8b02a4SEd Tanous     std::basic_ostream<CharT, Traits>&
42261b8b02a4SEd Tanous >::type
42271b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const sys_time<Duration>& tp)
42281b8b02a4SEd Tanous {
42291b8b02a4SEd Tanous     auto const dp = date::floor<days>(tp);
42301b8b02a4SEd Tanous     return os << year_month_day(dp) << ' ' << make_time(tp-dp);
42311b8b02a4SEd Tanous }
42321b8b02a4SEd Tanous 
42331b8b02a4SEd Tanous template <class CharT, class Traits>
42341b8b02a4SEd Tanous inline
42351b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
42361b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const sys_days& dp)
42371b8b02a4SEd Tanous {
42381b8b02a4SEd Tanous     return os << year_month_day(dp);
42391b8b02a4SEd Tanous }
42401b8b02a4SEd Tanous 
42411b8b02a4SEd Tanous template <class CharT, class Traits, class Duration>
42421b8b02a4SEd Tanous inline
42431b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
42441b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os, const local_time<Duration>& ut)
42451b8b02a4SEd Tanous {
42461b8b02a4SEd Tanous     return (os << sys_time<Duration>{ut.time_since_epoch()});
42471b8b02a4SEd Tanous }
42481b8b02a4SEd Tanous 
42491b8b02a4SEd Tanous namespace detail
42501b8b02a4SEd Tanous {
42511b8b02a4SEd Tanous 
42521b8b02a4SEd Tanous template <class CharT, std::size_t N>
42531b8b02a4SEd Tanous class string_literal;
42541b8b02a4SEd Tanous 
42551b8b02a4SEd Tanous template <class CharT1, class CharT2, std::size_t N1, std::size_t N2>
42561b8b02a4SEd Tanous inline
42571b8b02a4SEd Tanous CONSTCD14
42581b8b02a4SEd Tanous string_literal<typename std::conditional<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>::type,
42591b8b02a4SEd Tanous                N1 + N2 - 1>
42601b8b02a4SEd Tanous operator+(const string_literal<CharT1, N1>& x, const string_literal<CharT2, N2>& y) NOEXCEPT;
42611b8b02a4SEd Tanous 
42621b8b02a4SEd Tanous template <class CharT, std::size_t N>
42631b8b02a4SEd Tanous class string_literal
42641b8b02a4SEd Tanous {
42651b8b02a4SEd Tanous     CharT p_[N];
42661b8b02a4SEd Tanous 
42671b8b02a4SEd Tanous     CONSTCD11 string_literal() NOEXCEPT
42681b8b02a4SEd Tanous       : p_{}
42691b8b02a4SEd Tanous     {}
42701b8b02a4SEd Tanous 
42711b8b02a4SEd Tanous public:
42721b8b02a4SEd Tanous     using const_iterator = const CharT*;
42731b8b02a4SEd Tanous 
42741b8b02a4SEd Tanous     string_literal(string_literal const&) = default;
42751b8b02a4SEd Tanous     string_literal& operator=(string_literal const&) = delete;
42761b8b02a4SEd Tanous 
42771b8b02a4SEd Tanous     template <std::size_t N1 = 2,
42781b8b02a4SEd Tanous               class = typename std::enable_if<N1 == N>::type>
42791b8b02a4SEd Tanous     CONSTCD11 string_literal(CharT c) NOEXCEPT
42801b8b02a4SEd Tanous         : p_{c}
42811b8b02a4SEd Tanous     {
42821b8b02a4SEd Tanous     }
42831b8b02a4SEd Tanous 
42841b8b02a4SEd Tanous     template <std::size_t N1 = 3,
42851b8b02a4SEd Tanous               class = typename std::enable_if<N1 == N>::type>
42861b8b02a4SEd Tanous     CONSTCD11 string_literal(CharT c1, CharT c2) NOEXCEPT
42871b8b02a4SEd Tanous         : p_{c1, c2}
42881b8b02a4SEd Tanous     {
42891b8b02a4SEd Tanous     }
42901b8b02a4SEd Tanous 
42911b8b02a4SEd Tanous     template <std::size_t N1 = 4,
42921b8b02a4SEd Tanous               class = typename std::enable_if<N1 == N>::type>
42931b8b02a4SEd Tanous     CONSTCD11 string_literal(CharT c1, CharT c2, CharT c3) NOEXCEPT
42941b8b02a4SEd Tanous         : p_{c1, c2, c3}
42951b8b02a4SEd Tanous     {
42961b8b02a4SEd Tanous     }
42971b8b02a4SEd Tanous 
42981b8b02a4SEd Tanous     CONSTCD14 string_literal(const CharT(&a)[N]) NOEXCEPT
42991b8b02a4SEd Tanous         : p_{}
43001b8b02a4SEd Tanous     {
43011b8b02a4SEd Tanous         for (std::size_t i = 0; i < N; ++i)
43021b8b02a4SEd Tanous             p_[i] = a[i];
43031b8b02a4SEd Tanous     }
43041b8b02a4SEd Tanous 
43051b8b02a4SEd Tanous     template <class U = CharT,
43061b8b02a4SEd Tanous               class = typename std::enable_if<(1 < sizeof(U))>::type>
43071b8b02a4SEd Tanous     CONSTCD14 string_literal(const char(&a)[N]) NOEXCEPT
43081b8b02a4SEd Tanous         : p_{}
43091b8b02a4SEd Tanous     {
43101b8b02a4SEd Tanous         for (std::size_t i = 0; i < N; ++i)
43111b8b02a4SEd Tanous             p_[i] = a[i];
43121b8b02a4SEd Tanous     }
43131b8b02a4SEd Tanous 
43141b8b02a4SEd Tanous     template <class CharT2,
43151b8b02a4SEd Tanous               class = typename std::enable_if<!std::is_same<CharT2, CharT>::value>::type>
43161b8b02a4SEd Tanous     CONSTCD14 string_literal(string_literal<CharT2, N> const& a) NOEXCEPT
43171b8b02a4SEd Tanous         : p_{}
43181b8b02a4SEd Tanous     {
43191b8b02a4SEd Tanous         for (std::size_t i = 0; i < N; ++i)
43201b8b02a4SEd Tanous             p_[i] = a[i];
43211b8b02a4SEd Tanous     }
43221b8b02a4SEd Tanous 
43231b8b02a4SEd Tanous     CONSTCD11 const CharT* data() const NOEXCEPT {return p_;}
43241b8b02a4SEd Tanous     CONSTCD11 std::size_t size() const NOEXCEPT {return N-1;}
43251b8b02a4SEd Tanous 
43261b8b02a4SEd Tanous     CONSTCD11 const_iterator begin() const NOEXCEPT {return p_;}
43271b8b02a4SEd Tanous     CONSTCD11 const_iterator end()   const NOEXCEPT {return p_ + N-1;}
43281b8b02a4SEd Tanous 
43291b8b02a4SEd Tanous     CONSTCD11 CharT const& operator[](std::size_t n) const NOEXCEPT
43301b8b02a4SEd Tanous     {
43311b8b02a4SEd Tanous         return p_[n];
43321b8b02a4SEd Tanous     }
43331b8b02a4SEd Tanous 
43341b8b02a4SEd Tanous     template <class Traits>
43351b8b02a4SEd Tanous     friend
43361b8b02a4SEd Tanous     std::basic_ostream<CharT, Traits>&
43371b8b02a4SEd Tanous     operator<<(std::basic_ostream<CharT, Traits>& os, const string_literal& s)
43381b8b02a4SEd Tanous     {
43391b8b02a4SEd Tanous         return os << s.p_;
43401b8b02a4SEd Tanous     }
43411b8b02a4SEd Tanous 
43421b8b02a4SEd Tanous     template <class CharT1, class CharT2, std::size_t N1, std::size_t N2>
43431b8b02a4SEd Tanous     friend
43441b8b02a4SEd Tanous     CONSTCD14
43451b8b02a4SEd Tanous     string_literal<typename std::conditional<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>::type,
43461b8b02a4SEd Tanous                    N1 + N2 - 1>
43471b8b02a4SEd Tanous     operator+(const string_literal<CharT1, N1>& x, const string_literal<CharT2, N2>& y) NOEXCEPT;
43481b8b02a4SEd Tanous };
43491b8b02a4SEd Tanous 
43501b8b02a4SEd Tanous template <class CharT>
43511b8b02a4SEd Tanous CONSTCD11
43521b8b02a4SEd Tanous inline
43531b8b02a4SEd Tanous string_literal<CharT, 3>
43541b8b02a4SEd Tanous operator+(const string_literal<CharT, 2>& x, const string_literal<CharT, 2>& y) NOEXCEPT
43551b8b02a4SEd Tanous {
43561b8b02a4SEd Tanous   return string_literal<CharT, 3>(x[0], y[0]);
43571b8b02a4SEd Tanous }
43581b8b02a4SEd Tanous 
43591b8b02a4SEd Tanous template <class CharT>
43601b8b02a4SEd Tanous CONSTCD11
43611b8b02a4SEd Tanous inline
43621b8b02a4SEd Tanous string_literal<CharT, 4>
43631b8b02a4SEd Tanous operator+(const string_literal<CharT, 3>& x, const string_literal<CharT, 2>& y) NOEXCEPT
43641b8b02a4SEd Tanous {
43651b8b02a4SEd Tanous   return string_literal<CharT, 4>(x[0], x[1], y[0]);
43661b8b02a4SEd Tanous }
43671b8b02a4SEd Tanous 
43681b8b02a4SEd Tanous template <class CharT1, class CharT2, std::size_t N1, std::size_t N2>
43691b8b02a4SEd Tanous CONSTCD14
43701b8b02a4SEd Tanous inline
43711b8b02a4SEd Tanous string_literal<typename std::conditional<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>::type,
43721b8b02a4SEd Tanous                N1 + N2 - 1>
43731b8b02a4SEd Tanous operator+(const string_literal<CharT1, N1>& x, const string_literal<CharT2, N2>& y) NOEXCEPT
43741b8b02a4SEd Tanous {
43751b8b02a4SEd Tanous     using CT = typename std::conditional<sizeof(CharT2) <= sizeof(CharT1), CharT1, CharT2>::type;
43761b8b02a4SEd Tanous 
43771b8b02a4SEd Tanous     string_literal<CT, N1 + N2 - 1> r;
43781b8b02a4SEd Tanous     std::size_t i = 0;
43791b8b02a4SEd Tanous     for (; i < N1-1; ++i)
43801b8b02a4SEd Tanous        r.p_[i] = CT(x.p_[i]);
43811b8b02a4SEd Tanous     for (std::size_t j = 0; j < N2; ++j, ++i)
43821b8b02a4SEd Tanous        r.p_[i] = CT(y.p_[j]);
43831b8b02a4SEd Tanous 
43841b8b02a4SEd Tanous     return r;
43851b8b02a4SEd Tanous }
43861b8b02a4SEd Tanous 
43871b8b02a4SEd Tanous 
43881b8b02a4SEd Tanous template <class CharT, class Traits, class Alloc, std::size_t N>
43891b8b02a4SEd Tanous inline
43901b8b02a4SEd Tanous std::basic_string<CharT, Traits, Alloc>
43911b8b02a4SEd Tanous operator+(std::basic_string<CharT, Traits, Alloc> x, const string_literal<CharT, N>& y)
43921b8b02a4SEd Tanous {
43931b8b02a4SEd Tanous     x.append(y.data(), y.size());
43941b8b02a4SEd Tanous     return x;
43951b8b02a4SEd Tanous }
43961b8b02a4SEd Tanous 
43971b8b02a4SEd Tanous #if __cplusplus >= 201402  && (!defined(__EDG_VERSION__) || __EDG_VERSION__ > 411) \
43981b8b02a4SEd Tanous                            && (!defined(__SUNPRO_CC) || __SUNPRO_CC > 0x5150)
43991b8b02a4SEd Tanous 
44001b8b02a4SEd Tanous template <class CharT,
44011b8b02a4SEd Tanous           class = std::enable_if_t<std::is_same<CharT, char>::value ||
44021b8b02a4SEd Tanous                                    std::is_same<CharT, wchar_t>::value ||
44031b8b02a4SEd Tanous                                    std::is_same<CharT, char16_t>::value ||
44041b8b02a4SEd Tanous                                    std::is_same<CharT, char32_t>::value>>
44051b8b02a4SEd Tanous CONSTCD14
44061b8b02a4SEd Tanous inline
44071b8b02a4SEd Tanous string_literal<CharT, 2>
44081b8b02a4SEd Tanous msl(CharT c) NOEXCEPT
44091b8b02a4SEd Tanous {
44101b8b02a4SEd Tanous     return string_literal<CharT, 2>{c};
44111b8b02a4SEd Tanous }
44121b8b02a4SEd Tanous 
44131b8b02a4SEd Tanous CONSTCD14
44141b8b02a4SEd Tanous inline
44151b8b02a4SEd Tanous std::size_t
44161b8b02a4SEd Tanous to_string_len(std::intmax_t i)
44171b8b02a4SEd Tanous {
44181b8b02a4SEd Tanous     std::size_t r = 0;
44191b8b02a4SEd Tanous     do
44201b8b02a4SEd Tanous     {
44211b8b02a4SEd Tanous         i /= 10;
44221b8b02a4SEd Tanous         ++r;
44231b8b02a4SEd Tanous     } while (i > 0);
44241b8b02a4SEd Tanous     return r;
44251b8b02a4SEd Tanous }
44261b8b02a4SEd Tanous 
44271b8b02a4SEd Tanous template <std::intmax_t N>
44281b8b02a4SEd Tanous CONSTCD14
44291b8b02a4SEd Tanous inline
44301b8b02a4SEd Tanous std::enable_if_t
44311b8b02a4SEd Tanous <
44321b8b02a4SEd Tanous     N < 10,
44331b8b02a4SEd Tanous     string_literal<char, to_string_len(N)+1>
44341b8b02a4SEd Tanous >
44351b8b02a4SEd Tanous msl() NOEXCEPT
44361b8b02a4SEd Tanous {
44371b8b02a4SEd Tanous     return msl(char(N % 10 + '0'));
44381b8b02a4SEd Tanous }
44391b8b02a4SEd Tanous 
44401b8b02a4SEd Tanous template <std::intmax_t N>
44411b8b02a4SEd Tanous CONSTCD14
44421b8b02a4SEd Tanous inline
44431b8b02a4SEd Tanous std::enable_if_t
44441b8b02a4SEd Tanous <
44451b8b02a4SEd Tanous     10 <= N,
44461b8b02a4SEd Tanous     string_literal<char, to_string_len(N)+1>
44471b8b02a4SEd Tanous >
44481b8b02a4SEd Tanous msl() NOEXCEPT
44491b8b02a4SEd Tanous {
44501b8b02a4SEd Tanous     return msl<N/10>() + msl(char(N % 10 + '0'));
44511b8b02a4SEd Tanous }
44521b8b02a4SEd Tanous 
44531b8b02a4SEd Tanous template <class CharT, std::intmax_t N, std::intmax_t D>
44541b8b02a4SEd Tanous CONSTCD14
44551b8b02a4SEd Tanous inline
44561b8b02a4SEd Tanous std::enable_if_t
44571b8b02a4SEd Tanous <
44581b8b02a4SEd Tanous     std::ratio<N, D>::type::den != 1,
44591b8b02a4SEd Tanous     string_literal<CharT, to_string_len(std::ratio<N, D>::type::num) +
44601b8b02a4SEd Tanous                           to_string_len(std::ratio<N, D>::type::den) + 4>
44611b8b02a4SEd Tanous >
44621b8b02a4SEd Tanous msl(std::ratio<N, D>) NOEXCEPT
44631b8b02a4SEd Tanous {
44641b8b02a4SEd Tanous     using R = typename std::ratio<N, D>::type;
44651b8b02a4SEd Tanous     return msl(CharT{'['}) + msl<R::num>() + msl(CharT{'/'}) +
44661b8b02a4SEd Tanous                              msl<R::den>() + msl(CharT{']'});
44671b8b02a4SEd Tanous }
44681b8b02a4SEd Tanous 
44691b8b02a4SEd Tanous template <class CharT, std::intmax_t N, std::intmax_t D>
44701b8b02a4SEd Tanous CONSTCD14
44711b8b02a4SEd Tanous inline
44721b8b02a4SEd Tanous std::enable_if_t
44731b8b02a4SEd Tanous <
44741b8b02a4SEd Tanous     std::ratio<N, D>::type::den == 1,
44751b8b02a4SEd Tanous     string_literal<CharT, to_string_len(std::ratio<N, D>::type::num) + 3>
44761b8b02a4SEd Tanous >
44771b8b02a4SEd Tanous msl(std::ratio<N, D>) NOEXCEPT
44781b8b02a4SEd Tanous {
44791b8b02a4SEd Tanous     using R = typename std::ratio<N, D>::type;
44801b8b02a4SEd Tanous     return msl(CharT{'['}) + msl<R::num>() + msl(CharT{']'});
44811b8b02a4SEd Tanous }
44821b8b02a4SEd Tanous 
44831b8b02a4SEd Tanous 
44841b8b02a4SEd Tanous #else  // __cplusplus < 201402 || (defined(__EDG_VERSION__) && __EDG_VERSION__ <= 411)
44851b8b02a4SEd Tanous 
44861b8b02a4SEd Tanous inline
44871b8b02a4SEd Tanous std::string
44881b8b02a4SEd Tanous to_string(std::uint64_t x)
44891b8b02a4SEd Tanous {
44901b8b02a4SEd Tanous     return std::to_string(x);
44911b8b02a4SEd Tanous }
44921b8b02a4SEd Tanous 
44931b8b02a4SEd Tanous template <class CharT>
44941b8b02a4SEd Tanous inline
44951b8b02a4SEd Tanous std::basic_string<CharT>
44961b8b02a4SEd Tanous to_string(std::uint64_t x)
44971b8b02a4SEd Tanous {
44981b8b02a4SEd Tanous     auto y = std::to_string(x);
44991b8b02a4SEd Tanous     return std::basic_string<CharT>(y.begin(), y.end());
45001b8b02a4SEd Tanous }
45011b8b02a4SEd Tanous 
45021b8b02a4SEd Tanous template <class CharT, std::intmax_t N, std::intmax_t D>
45031b8b02a4SEd Tanous inline
45041b8b02a4SEd Tanous typename std::enable_if
45051b8b02a4SEd Tanous <
45061b8b02a4SEd Tanous     std::ratio<N, D>::type::den != 1,
45071b8b02a4SEd Tanous     std::basic_string<CharT>
45081b8b02a4SEd Tanous >::type
45091b8b02a4SEd Tanous msl(std::ratio<N, D>)
45101b8b02a4SEd Tanous {
45111b8b02a4SEd Tanous     using R = typename std::ratio<N, D>::type;
45121b8b02a4SEd Tanous     return std::basic_string<CharT>(1, '[') + to_string<CharT>(R::num) + CharT{'/'} +
45131b8b02a4SEd Tanous                                               to_string<CharT>(R::den) + CharT{']'};
45141b8b02a4SEd Tanous }
45151b8b02a4SEd Tanous 
45161b8b02a4SEd Tanous template <class CharT, std::intmax_t N, std::intmax_t D>
45171b8b02a4SEd Tanous inline
45181b8b02a4SEd Tanous typename std::enable_if
45191b8b02a4SEd Tanous <
45201b8b02a4SEd Tanous     std::ratio<N, D>::type::den == 1,
45211b8b02a4SEd Tanous     std::basic_string<CharT>
45221b8b02a4SEd Tanous >::type
45231b8b02a4SEd Tanous msl(std::ratio<N, D>)
45241b8b02a4SEd Tanous {
45251b8b02a4SEd Tanous     using R = typename std::ratio<N, D>::type;
45261b8b02a4SEd Tanous     return std::basic_string<CharT>(1, '[') + to_string<CharT>(R::num) + CharT{']'};
45271b8b02a4SEd Tanous }
45281b8b02a4SEd Tanous 
45291b8b02a4SEd Tanous #endif  // __cplusplus < 201402 || (defined(__EDG_VERSION__) && __EDG_VERSION__ <= 411)
45301b8b02a4SEd Tanous 
45311b8b02a4SEd Tanous template <class CharT>
45321b8b02a4SEd Tanous CONSTCD11
45331b8b02a4SEd Tanous inline
45341b8b02a4SEd Tanous string_literal<CharT, 2>
45351b8b02a4SEd Tanous msl(std::atto) NOEXCEPT
45361b8b02a4SEd Tanous {
45371b8b02a4SEd Tanous     return string_literal<CharT, 2>{'a'};
45381b8b02a4SEd Tanous }
45391b8b02a4SEd Tanous 
45401b8b02a4SEd Tanous template <class CharT>
45411b8b02a4SEd Tanous CONSTCD11
45421b8b02a4SEd Tanous inline
45431b8b02a4SEd Tanous string_literal<CharT, 2>
45441b8b02a4SEd Tanous msl(std::femto) NOEXCEPT
45451b8b02a4SEd Tanous {
45461b8b02a4SEd Tanous     return string_literal<CharT, 2>{'f'};
45471b8b02a4SEd Tanous }
45481b8b02a4SEd Tanous 
45491b8b02a4SEd Tanous template <class CharT>
45501b8b02a4SEd Tanous CONSTCD11
45511b8b02a4SEd Tanous inline
45521b8b02a4SEd Tanous string_literal<CharT, 2>
45531b8b02a4SEd Tanous msl(std::pico) NOEXCEPT
45541b8b02a4SEd Tanous {
45551b8b02a4SEd Tanous     return string_literal<CharT, 2>{'p'};
45561b8b02a4SEd Tanous }
45571b8b02a4SEd Tanous 
45581b8b02a4SEd Tanous template <class CharT>
45591b8b02a4SEd Tanous CONSTCD11
45601b8b02a4SEd Tanous inline
45611b8b02a4SEd Tanous string_literal<CharT, 2>
45621b8b02a4SEd Tanous msl(std::nano) NOEXCEPT
45631b8b02a4SEd Tanous {
45641b8b02a4SEd Tanous     return string_literal<CharT, 2>{'n'};
45651b8b02a4SEd Tanous }
45661b8b02a4SEd Tanous 
45671b8b02a4SEd Tanous template <class CharT>
45681b8b02a4SEd Tanous CONSTCD11
45691b8b02a4SEd Tanous inline
45701b8b02a4SEd Tanous typename std::enable_if
45711b8b02a4SEd Tanous <
45721b8b02a4SEd Tanous     std::is_same<CharT, char>::value,
45731b8b02a4SEd Tanous     string_literal<char, 3>
45741b8b02a4SEd Tanous >::type
45751b8b02a4SEd Tanous msl(std::micro) NOEXCEPT
45761b8b02a4SEd Tanous {
45771b8b02a4SEd Tanous     return string_literal<char, 3>{'\xC2', '\xB5'};
45781b8b02a4SEd Tanous }
45791b8b02a4SEd Tanous 
45801b8b02a4SEd Tanous template <class CharT>
45811b8b02a4SEd Tanous CONSTCD11
45821b8b02a4SEd Tanous inline
45831b8b02a4SEd Tanous typename std::enable_if
45841b8b02a4SEd Tanous <
45851b8b02a4SEd Tanous     !std::is_same<CharT, char>::value,
45861b8b02a4SEd Tanous     string_literal<CharT, 2>
45871b8b02a4SEd Tanous >::type
45881b8b02a4SEd Tanous msl(std::micro) NOEXCEPT
45891b8b02a4SEd Tanous {
45901b8b02a4SEd Tanous     return string_literal<CharT, 2>{CharT{static_cast<unsigned char>('\xB5')}};
45911b8b02a4SEd Tanous }
45921b8b02a4SEd Tanous 
45931b8b02a4SEd Tanous template <class CharT>
45941b8b02a4SEd Tanous CONSTCD11
45951b8b02a4SEd Tanous inline
45961b8b02a4SEd Tanous string_literal<CharT, 2>
45971b8b02a4SEd Tanous msl(std::milli) NOEXCEPT
45981b8b02a4SEd Tanous {
45991b8b02a4SEd Tanous     return string_literal<CharT, 2>{'m'};
46001b8b02a4SEd Tanous }
46011b8b02a4SEd Tanous 
46021b8b02a4SEd Tanous template <class CharT>
46031b8b02a4SEd Tanous CONSTCD11
46041b8b02a4SEd Tanous inline
46051b8b02a4SEd Tanous string_literal<CharT, 2>
46061b8b02a4SEd Tanous msl(std::centi) NOEXCEPT
46071b8b02a4SEd Tanous {
46081b8b02a4SEd Tanous     return string_literal<CharT, 2>{'c'};
46091b8b02a4SEd Tanous }
46101b8b02a4SEd Tanous 
46111b8b02a4SEd Tanous template <class CharT>
46121b8b02a4SEd Tanous CONSTCD11
46131b8b02a4SEd Tanous inline
46141b8b02a4SEd Tanous string_literal<CharT, 3>
46151b8b02a4SEd Tanous msl(std::deca) NOEXCEPT
46161b8b02a4SEd Tanous {
46171b8b02a4SEd Tanous     return string_literal<CharT, 3>{'d', 'a'};
46181b8b02a4SEd Tanous }
46191b8b02a4SEd Tanous 
46201b8b02a4SEd Tanous template <class CharT>
46211b8b02a4SEd Tanous CONSTCD11
46221b8b02a4SEd Tanous inline
46231b8b02a4SEd Tanous string_literal<CharT, 2>
46241b8b02a4SEd Tanous msl(std::deci) NOEXCEPT
46251b8b02a4SEd Tanous {
46261b8b02a4SEd Tanous     return string_literal<CharT, 2>{'d'};
46271b8b02a4SEd Tanous }
46281b8b02a4SEd Tanous 
46291b8b02a4SEd Tanous template <class CharT>
46301b8b02a4SEd Tanous CONSTCD11
46311b8b02a4SEd Tanous inline
46321b8b02a4SEd Tanous string_literal<CharT, 2>
46331b8b02a4SEd Tanous msl(std::hecto) NOEXCEPT
46341b8b02a4SEd Tanous {
46351b8b02a4SEd Tanous     return string_literal<CharT, 2>{'h'};
46361b8b02a4SEd Tanous }
46371b8b02a4SEd Tanous 
46381b8b02a4SEd Tanous template <class CharT>
46391b8b02a4SEd Tanous CONSTCD11
46401b8b02a4SEd Tanous inline
46411b8b02a4SEd Tanous string_literal<CharT, 2>
46421b8b02a4SEd Tanous msl(std::kilo) NOEXCEPT
46431b8b02a4SEd Tanous {
46441b8b02a4SEd Tanous     return string_literal<CharT, 2>{'k'};
46451b8b02a4SEd Tanous }
46461b8b02a4SEd Tanous 
46471b8b02a4SEd Tanous template <class CharT>
46481b8b02a4SEd Tanous CONSTCD11
46491b8b02a4SEd Tanous inline
46501b8b02a4SEd Tanous string_literal<CharT, 2>
46511b8b02a4SEd Tanous msl(std::mega) NOEXCEPT
46521b8b02a4SEd Tanous {
46531b8b02a4SEd Tanous     return string_literal<CharT, 2>{'M'};
46541b8b02a4SEd Tanous }
46551b8b02a4SEd Tanous 
46561b8b02a4SEd Tanous template <class CharT>
46571b8b02a4SEd Tanous CONSTCD11
46581b8b02a4SEd Tanous inline
46591b8b02a4SEd Tanous string_literal<CharT, 2>
46601b8b02a4SEd Tanous msl(std::giga) NOEXCEPT
46611b8b02a4SEd Tanous {
46621b8b02a4SEd Tanous     return string_literal<CharT, 2>{'G'};
46631b8b02a4SEd Tanous }
46641b8b02a4SEd Tanous 
46651b8b02a4SEd Tanous template <class CharT>
46661b8b02a4SEd Tanous CONSTCD11
46671b8b02a4SEd Tanous inline
46681b8b02a4SEd Tanous string_literal<CharT, 2>
46691b8b02a4SEd Tanous msl(std::tera) NOEXCEPT
46701b8b02a4SEd Tanous {
46711b8b02a4SEd Tanous     return string_literal<CharT, 2>{'T'};
46721b8b02a4SEd Tanous }
46731b8b02a4SEd Tanous 
46741b8b02a4SEd Tanous template <class CharT>
46751b8b02a4SEd Tanous CONSTCD11
46761b8b02a4SEd Tanous inline
46771b8b02a4SEd Tanous string_literal<CharT, 2>
46781b8b02a4SEd Tanous msl(std::peta) NOEXCEPT
46791b8b02a4SEd Tanous {
46801b8b02a4SEd Tanous     return string_literal<CharT, 2>{'P'};
46811b8b02a4SEd Tanous }
46821b8b02a4SEd Tanous 
46831b8b02a4SEd Tanous template <class CharT>
46841b8b02a4SEd Tanous CONSTCD11
46851b8b02a4SEd Tanous inline
46861b8b02a4SEd Tanous string_literal<CharT, 2>
46871b8b02a4SEd Tanous msl(std::exa) NOEXCEPT
46881b8b02a4SEd Tanous {
46891b8b02a4SEd Tanous     return string_literal<CharT, 2>{'E'};
46901b8b02a4SEd Tanous }
46911b8b02a4SEd Tanous 
46921b8b02a4SEd Tanous template <class CharT, class Period>
46931b8b02a4SEd Tanous CONSTCD11
46941b8b02a4SEd Tanous inline
46951b8b02a4SEd Tanous auto
46961b8b02a4SEd Tanous get_units(Period p)
46971b8b02a4SEd Tanous  -> decltype(msl<CharT>(p) + string_literal<CharT, 2>{'s'})
46981b8b02a4SEd Tanous {
46991b8b02a4SEd Tanous     return msl<CharT>(p) + string_literal<CharT, 2>{'s'};
47001b8b02a4SEd Tanous }
47011b8b02a4SEd Tanous 
47021b8b02a4SEd Tanous template <class CharT>
47031b8b02a4SEd Tanous CONSTCD11
47041b8b02a4SEd Tanous inline
47051b8b02a4SEd Tanous string_literal<CharT, 2>
47061b8b02a4SEd Tanous get_units(std::ratio<1>)
47071b8b02a4SEd Tanous {
47081b8b02a4SEd Tanous     return string_literal<CharT, 2>{'s'};
47091b8b02a4SEd Tanous }
47101b8b02a4SEd Tanous 
47111b8b02a4SEd Tanous template <class CharT>
47121b8b02a4SEd Tanous CONSTCD11
47131b8b02a4SEd Tanous inline
47141b8b02a4SEd Tanous string_literal<CharT, 2>
47151b8b02a4SEd Tanous get_units(std::ratio<3600>)
47161b8b02a4SEd Tanous {
47171b8b02a4SEd Tanous     return string_literal<CharT, 2>{'h'};
47181b8b02a4SEd Tanous }
47191b8b02a4SEd Tanous 
47201b8b02a4SEd Tanous template <class CharT>
47211b8b02a4SEd Tanous CONSTCD11
47221b8b02a4SEd Tanous inline
47231b8b02a4SEd Tanous string_literal<CharT, 4>
47241b8b02a4SEd Tanous get_units(std::ratio<60>)
47251b8b02a4SEd Tanous {
47261b8b02a4SEd Tanous     return string_literal<CharT, 4>{'m', 'i', 'n'};
47271b8b02a4SEd Tanous }
47281b8b02a4SEd Tanous 
47291b8b02a4SEd Tanous template <class CharT>
47301b8b02a4SEd Tanous CONSTCD11
47311b8b02a4SEd Tanous inline
47321b8b02a4SEd Tanous string_literal<CharT, 2>
47331b8b02a4SEd Tanous get_units(std::ratio<86400>)
47341b8b02a4SEd Tanous {
47351b8b02a4SEd Tanous     return string_literal<CharT, 2>{'d'};
47361b8b02a4SEd Tanous }
47371b8b02a4SEd Tanous 
47381b8b02a4SEd Tanous template <class CharT, class Traits = std::char_traits<CharT>>
47391b8b02a4SEd Tanous struct make_string;
47401b8b02a4SEd Tanous 
47411b8b02a4SEd Tanous template <>
47421b8b02a4SEd Tanous struct make_string<char>
47431b8b02a4SEd Tanous {
47441b8b02a4SEd Tanous     template <class Rep>
47451b8b02a4SEd Tanous     static
47461b8b02a4SEd Tanous     std::string
47471b8b02a4SEd Tanous     from(Rep n)
47481b8b02a4SEd Tanous     {
47491b8b02a4SEd Tanous         return std::to_string(n);
47501b8b02a4SEd Tanous     }
47511b8b02a4SEd Tanous };
47521b8b02a4SEd Tanous 
47531b8b02a4SEd Tanous template <class Traits>
47541b8b02a4SEd Tanous struct make_string<char, Traits>
47551b8b02a4SEd Tanous {
47561b8b02a4SEd Tanous     template <class Rep>
47571b8b02a4SEd Tanous     static
47581b8b02a4SEd Tanous     std::basic_string<char, Traits>
47591b8b02a4SEd Tanous     from(Rep n)
47601b8b02a4SEd Tanous     {
47611b8b02a4SEd Tanous         auto s = std::to_string(n);
47621b8b02a4SEd Tanous         return std::basic_string<char, Traits>(s.begin(), s.end());
47631b8b02a4SEd Tanous     }
47641b8b02a4SEd Tanous };
47651b8b02a4SEd Tanous 
47661b8b02a4SEd Tanous template <>
47671b8b02a4SEd Tanous struct make_string<wchar_t>
47681b8b02a4SEd Tanous {
47691b8b02a4SEd Tanous     template <class Rep>
47701b8b02a4SEd Tanous     static
47711b8b02a4SEd Tanous     std::wstring
47721b8b02a4SEd Tanous     from(Rep n)
47731b8b02a4SEd Tanous     {
47741b8b02a4SEd Tanous         return std::to_wstring(n);
47751b8b02a4SEd Tanous     }
47761b8b02a4SEd Tanous };
47771b8b02a4SEd Tanous 
47781b8b02a4SEd Tanous template <class Traits>
47791b8b02a4SEd Tanous struct make_string<wchar_t, Traits>
47801b8b02a4SEd Tanous {
47811b8b02a4SEd Tanous     template <class Rep>
47821b8b02a4SEd Tanous     static
47831b8b02a4SEd Tanous     std::basic_string<wchar_t, Traits>
47841b8b02a4SEd Tanous     from(Rep n)
47851b8b02a4SEd Tanous     {
47861b8b02a4SEd Tanous         auto s = std::to_wstring(n);
47871b8b02a4SEd Tanous         return std::basic_string<wchar_t, Traits>(s.begin(), s.end());
47881b8b02a4SEd Tanous     }
47891b8b02a4SEd Tanous };
47901b8b02a4SEd Tanous 
47911b8b02a4SEd Tanous }  // namespace detail
47921b8b02a4SEd Tanous 
47931b8b02a4SEd Tanous // to_stream
47941b8b02a4SEd Tanous 
47951b8b02a4SEd Tanous CONSTDATA year nanyear{-32768};
47961b8b02a4SEd Tanous 
47971b8b02a4SEd Tanous template <class Duration>
47981b8b02a4SEd Tanous struct fields
47991b8b02a4SEd Tanous {
48001b8b02a4SEd Tanous     year_month_day        ymd{nanyear/0/0};
48011b8b02a4SEd Tanous     weekday               wd{8u};
48021b8b02a4SEd Tanous     hh_mm_ss<Duration>    tod{};
48031b8b02a4SEd Tanous     bool                  has_tod = false;
48041b8b02a4SEd Tanous 
48051b8b02a4SEd Tanous #if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ <= 409)
48061b8b02a4SEd Tanous     fields() : ymd{nanyear/0/0}, wd{8u}, tod{}, has_tod{false} {}
48071b8b02a4SEd Tanous #else
48081b8b02a4SEd Tanous     fields() = default;
48091b8b02a4SEd Tanous #endif
48101b8b02a4SEd Tanous 
48111b8b02a4SEd Tanous     fields(year_month_day ymd_) : ymd(ymd_) {}
48121b8b02a4SEd Tanous     fields(weekday wd_) : wd(wd_) {}
48131b8b02a4SEd Tanous     fields(hh_mm_ss<Duration> tod_) : tod(tod_), has_tod(true) {}
48141b8b02a4SEd Tanous 
48151b8b02a4SEd Tanous     fields(year_month_day ymd_, weekday wd_) : ymd(ymd_), wd(wd_) {}
48161b8b02a4SEd Tanous     fields(year_month_day ymd_, hh_mm_ss<Duration> tod_) : ymd(ymd_), tod(tod_),
48171b8b02a4SEd Tanous                                                            has_tod(true) {}
48181b8b02a4SEd Tanous 
48191b8b02a4SEd Tanous     fields(weekday wd_, hh_mm_ss<Duration> tod_) : wd(wd_), tod(tod_), has_tod(true) {}
48201b8b02a4SEd Tanous 
48211b8b02a4SEd Tanous     fields(year_month_day ymd_, weekday wd_, hh_mm_ss<Duration> tod_)
48221b8b02a4SEd Tanous         : ymd(ymd_)
48231b8b02a4SEd Tanous         , wd(wd_)
48241b8b02a4SEd Tanous         , tod(tod_)
48251b8b02a4SEd Tanous         , has_tod(true)
48261b8b02a4SEd Tanous         {}
48271b8b02a4SEd Tanous };
48281b8b02a4SEd Tanous 
48291b8b02a4SEd Tanous namespace detail
48301b8b02a4SEd Tanous {
48311b8b02a4SEd Tanous 
48321b8b02a4SEd Tanous template <class CharT, class Traits, class Duration>
48331b8b02a4SEd Tanous unsigned
48341b8b02a4SEd Tanous extract_weekday(std::basic_ostream<CharT, Traits>& os, const fields<Duration>& fds)
48351b8b02a4SEd Tanous {
48361b8b02a4SEd Tanous     if (!fds.ymd.ok() && !fds.wd.ok())
48371b8b02a4SEd Tanous     {
48381b8b02a4SEd Tanous         // fds does not contain a valid weekday
48391b8b02a4SEd Tanous         os.setstate(std::ios::failbit);
48401b8b02a4SEd Tanous         return 8;
48411b8b02a4SEd Tanous     }
48421b8b02a4SEd Tanous     weekday wd;
48431b8b02a4SEd Tanous     if (fds.ymd.ok())
48441b8b02a4SEd Tanous     {
48451b8b02a4SEd Tanous         wd = weekday{sys_days(fds.ymd)};
48461b8b02a4SEd Tanous         if (fds.wd.ok() && wd != fds.wd)
48471b8b02a4SEd Tanous         {
48481b8b02a4SEd Tanous             // fds.ymd and fds.wd are inconsistent
48491b8b02a4SEd Tanous             os.setstate(std::ios::failbit);
48501b8b02a4SEd Tanous             return 8;
48511b8b02a4SEd Tanous         }
48521b8b02a4SEd Tanous     }
48531b8b02a4SEd Tanous     else
48541b8b02a4SEd Tanous         wd = fds.wd;
48551b8b02a4SEd Tanous     return static_cast<unsigned>((wd - Sunday).count());
48561b8b02a4SEd Tanous }
48571b8b02a4SEd Tanous 
48581b8b02a4SEd Tanous template <class CharT, class Traits, class Duration>
48591b8b02a4SEd Tanous unsigned
48601b8b02a4SEd Tanous extract_month(std::basic_ostream<CharT, Traits>& os, const fields<Duration>& fds)
48611b8b02a4SEd Tanous {
48621b8b02a4SEd Tanous     if (!fds.ymd.month().ok())
48631b8b02a4SEd Tanous     {
48641b8b02a4SEd Tanous         // fds does not contain a valid month
48651b8b02a4SEd Tanous         os.setstate(std::ios::failbit);
48661b8b02a4SEd Tanous         return 0;
48671b8b02a4SEd Tanous     }
48681b8b02a4SEd Tanous     return static_cast<unsigned>(fds.ymd.month());
48691b8b02a4SEd Tanous }
48701b8b02a4SEd Tanous 
48711b8b02a4SEd Tanous }  // namespace detail
48721b8b02a4SEd Tanous 
48731b8b02a4SEd Tanous #if ONLY_C_LOCALE
48741b8b02a4SEd Tanous 
48751b8b02a4SEd Tanous namespace detail
48761b8b02a4SEd Tanous {
48771b8b02a4SEd Tanous 
48781b8b02a4SEd Tanous inline
48791b8b02a4SEd Tanous std::pair<const std::string*, const std::string*>
48801b8b02a4SEd Tanous weekday_names()
48811b8b02a4SEd Tanous {
48821b8b02a4SEd Tanous     static const std::string nm[] =
48831b8b02a4SEd Tanous     {
48841b8b02a4SEd Tanous         "Sunday",
48851b8b02a4SEd Tanous         "Monday",
48861b8b02a4SEd Tanous         "Tuesday",
48871b8b02a4SEd Tanous         "Wednesday",
48881b8b02a4SEd Tanous         "Thursday",
48891b8b02a4SEd Tanous         "Friday",
48901b8b02a4SEd Tanous         "Saturday",
48911b8b02a4SEd Tanous         "Sun",
48921b8b02a4SEd Tanous         "Mon",
48931b8b02a4SEd Tanous         "Tue",
48941b8b02a4SEd Tanous         "Wed",
48951b8b02a4SEd Tanous         "Thu",
48961b8b02a4SEd Tanous         "Fri",
48971b8b02a4SEd Tanous         "Sat"
48981b8b02a4SEd Tanous     };
48991b8b02a4SEd Tanous     return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0]));
49001b8b02a4SEd Tanous }
49011b8b02a4SEd Tanous 
49021b8b02a4SEd Tanous inline
49031b8b02a4SEd Tanous std::pair<const std::string*, const std::string*>
49041b8b02a4SEd Tanous month_names()
49051b8b02a4SEd Tanous {
49061b8b02a4SEd Tanous     static const std::string nm[] =
49071b8b02a4SEd Tanous     {
49081b8b02a4SEd Tanous         "January",
49091b8b02a4SEd Tanous         "February",
49101b8b02a4SEd Tanous         "March",
49111b8b02a4SEd Tanous         "April",
49121b8b02a4SEd Tanous         "May",
49131b8b02a4SEd Tanous         "June",
49141b8b02a4SEd Tanous         "July",
49151b8b02a4SEd Tanous         "August",
49161b8b02a4SEd Tanous         "September",
49171b8b02a4SEd Tanous         "October",
49181b8b02a4SEd Tanous         "November",
49191b8b02a4SEd Tanous         "December",
49201b8b02a4SEd Tanous         "Jan",
49211b8b02a4SEd Tanous         "Feb",
49221b8b02a4SEd Tanous         "Mar",
49231b8b02a4SEd Tanous         "Apr",
49241b8b02a4SEd Tanous         "May",
49251b8b02a4SEd Tanous         "Jun",
49261b8b02a4SEd Tanous         "Jul",
49271b8b02a4SEd Tanous         "Aug",
49281b8b02a4SEd Tanous         "Sep",
49291b8b02a4SEd Tanous         "Oct",
49301b8b02a4SEd Tanous         "Nov",
49311b8b02a4SEd Tanous         "Dec"
49321b8b02a4SEd Tanous     };
49331b8b02a4SEd Tanous     return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0]));
49341b8b02a4SEd Tanous }
49351b8b02a4SEd Tanous 
49361b8b02a4SEd Tanous inline
49371b8b02a4SEd Tanous std::pair<const std::string*, const std::string*>
49381b8b02a4SEd Tanous ampm_names()
49391b8b02a4SEd Tanous {
49401b8b02a4SEd Tanous     static const std::string nm[] =
49411b8b02a4SEd Tanous     {
49421b8b02a4SEd Tanous         "AM",
49431b8b02a4SEd Tanous         "PM"
49441b8b02a4SEd Tanous     };
49451b8b02a4SEd Tanous     return std::make_pair(nm, nm+sizeof(nm)/sizeof(nm[0]));
49461b8b02a4SEd Tanous }
49471b8b02a4SEd Tanous 
49481b8b02a4SEd Tanous template <class CharT, class Traits, class FwdIter>
49491b8b02a4SEd Tanous FwdIter
49501b8b02a4SEd Tanous scan_keyword(std::basic_istream<CharT, Traits>& is, FwdIter kb, FwdIter ke)
49511b8b02a4SEd Tanous {
49521b8b02a4SEd Tanous     size_t nkw = static_cast<size_t>(std::distance(kb, ke));
49531b8b02a4SEd Tanous     const unsigned char doesnt_match = '\0';
49541b8b02a4SEd Tanous     const unsigned char might_match = '\1';
49551b8b02a4SEd Tanous     const unsigned char does_match = '\2';
49561b8b02a4SEd Tanous     unsigned char statbuf[100];
49571b8b02a4SEd Tanous     unsigned char* status = statbuf;
49581b8b02a4SEd Tanous     std::unique_ptr<unsigned char, void(*)(void*)> stat_hold(0, free);
49591b8b02a4SEd Tanous     if (nkw > sizeof(statbuf))
49601b8b02a4SEd Tanous     {
49611b8b02a4SEd Tanous         status = (unsigned char*)std::malloc(nkw);
49621b8b02a4SEd Tanous         if (status == nullptr)
49631b8b02a4SEd Tanous             std::terminate();
49641b8b02a4SEd Tanous         stat_hold.reset(status);
49651b8b02a4SEd Tanous     }
49661b8b02a4SEd Tanous     size_t n_might_match = nkw;  // At this point, any keyword might match
49671b8b02a4SEd Tanous     size_t n_does_match = 0;     // but none of them definitely do
49681b8b02a4SEd Tanous     // Initialize all statuses to might_match, except for "" keywords are does_match
49691b8b02a4SEd Tanous     unsigned char* st = status;
49701b8b02a4SEd Tanous     for (auto ky = kb; ky != ke; ++ky, ++st)
49711b8b02a4SEd Tanous     {
49721b8b02a4SEd Tanous         if (!ky->empty())
49731b8b02a4SEd Tanous             *st = might_match;
49741b8b02a4SEd Tanous         else
49751b8b02a4SEd Tanous         {
49761b8b02a4SEd Tanous             *st = does_match;
49771b8b02a4SEd Tanous             --n_might_match;
49781b8b02a4SEd Tanous             ++n_does_match;
49791b8b02a4SEd Tanous         }
49801b8b02a4SEd Tanous     }
49811b8b02a4SEd Tanous     // While there might be a match, test keywords against the next CharT
49821b8b02a4SEd Tanous     for (size_t indx = 0; is && n_might_match > 0; ++indx)
49831b8b02a4SEd Tanous     {
49841b8b02a4SEd Tanous         // Peek at the next CharT but don't consume it
49851b8b02a4SEd Tanous         auto ic = is.peek();
49861b8b02a4SEd Tanous         if (ic == EOF)
49871b8b02a4SEd Tanous         {
49881b8b02a4SEd Tanous             is.setstate(std::ios::eofbit);
49891b8b02a4SEd Tanous             break;
49901b8b02a4SEd Tanous         }
49911b8b02a4SEd Tanous         auto c = static_cast<char>(toupper(static_cast<unsigned char>(ic)));
49921b8b02a4SEd Tanous         bool consume = false;
49931b8b02a4SEd Tanous         // For each keyword which might match, see if the indx character is c
49941b8b02a4SEd Tanous         // If a match if found, consume c
49951b8b02a4SEd Tanous         // If a match is found, and that is the last character in the keyword,
49961b8b02a4SEd Tanous         //    then that keyword matches.
49971b8b02a4SEd Tanous         // If the keyword doesn't match this character, then change the keyword
49981b8b02a4SEd Tanous         //    to doesn't match
49991b8b02a4SEd Tanous         st = status;
50001b8b02a4SEd Tanous         for (auto ky = kb; ky != ke; ++ky, ++st)
50011b8b02a4SEd Tanous         {
50021b8b02a4SEd Tanous             if (*st == might_match)
50031b8b02a4SEd Tanous             {
50041b8b02a4SEd Tanous                 if (c == static_cast<char>(toupper(static_cast<unsigned char>((*ky)[indx]))))
50051b8b02a4SEd Tanous                 {
50061b8b02a4SEd Tanous                     consume = true;
50071b8b02a4SEd Tanous                     if (ky->size() == indx+1)
50081b8b02a4SEd Tanous                     {
50091b8b02a4SEd Tanous                         *st = does_match;
50101b8b02a4SEd Tanous                         --n_might_match;
50111b8b02a4SEd Tanous                         ++n_does_match;
50121b8b02a4SEd Tanous                     }
50131b8b02a4SEd Tanous                 }
50141b8b02a4SEd Tanous                 else
50151b8b02a4SEd Tanous                 {
50161b8b02a4SEd Tanous                     *st = doesnt_match;
50171b8b02a4SEd Tanous                     --n_might_match;
50181b8b02a4SEd Tanous                 }
50191b8b02a4SEd Tanous             }
50201b8b02a4SEd Tanous         }
50211b8b02a4SEd Tanous         // consume if we matched a character
50221b8b02a4SEd Tanous         if (consume)
50231b8b02a4SEd Tanous         {
50241b8b02a4SEd Tanous             (void)is.get();
50251b8b02a4SEd Tanous             // If we consumed a character and there might be a matched keyword that
50261b8b02a4SEd Tanous             //   was marked matched on a previous iteration, then such keywords
50271b8b02a4SEd Tanous             //   are now marked as not matching.
50281b8b02a4SEd Tanous             if (n_might_match + n_does_match > 1)
50291b8b02a4SEd Tanous             {
50301b8b02a4SEd Tanous                 st = status;
50311b8b02a4SEd Tanous                 for (auto ky = kb; ky != ke; ++ky, ++st)
50321b8b02a4SEd Tanous                 {
50331b8b02a4SEd Tanous                     if (*st == does_match && ky->size() != indx+1)
50341b8b02a4SEd Tanous                     {
50351b8b02a4SEd Tanous                         *st = doesnt_match;
50361b8b02a4SEd Tanous                         --n_does_match;
50371b8b02a4SEd Tanous                     }
50381b8b02a4SEd Tanous                 }
50391b8b02a4SEd Tanous             }
50401b8b02a4SEd Tanous         }
50411b8b02a4SEd Tanous     }
50421b8b02a4SEd Tanous     // We've exited the loop because we hit eof and/or we have no more "might matches".
50431b8b02a4SEd Tanous     // Return the first matching result
50441b8b02a4SEd Tanous     for (st = status; kb != ke; ++kb, ++st)
50451b8b02a4SEd Tanous         if (*st == does_match)
50461b8b02a4SEd Tanous             break;
50471b8b02a4SEd Tanous     if (kb == ke)
50481b8b02a4SEd Tanous         is.setstate(std::ios::failbit);
50491b8b02a4SEd Tanous     return kb;
50501b8b02a4SEd Tanous }
50511b8b02a4SEd Tanous 
50521b8b02a4SEd Tanous }  // namespace detail
50531b8b02a4SEd Tanous 
50541b8b02a4SEd Tanous #endif  // ONLY_C_LOCALE
50551b8b02a4SEd Tanous 
50561b8b02a4SEd Tanous template <class CharT, class Traits, class Duration>
50571b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
50581b8b02a4SEd Tanous to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
50591b8b02a4SEd Tanous           const fields<Duration>& fds, const std::string* abbrev,
50601b8b02a4SEd Tanous           const std::chrono::seconds* offset_sec)
50611b8b02a4SEd Tanous {
50621b8b02a4SEd Tanous #if ONLY_C_LOCALE
50631b8b02a4SEd Tanous     using detail::weekday_names;
50641b8b02a4SEd Tanous     using detail::month_names;
50651b8b02a4SEd Tanous     using detail::ampm_names;
50661b8b02a4SEd Tanous #endif
50671b8b02a4SEd Tanous     using detail::save_ostream;
50681b8b02a4SEd Tanous     using detail::get_units;
50691b8b02a4SEd Tanous     using detail::extract_weekday;
50701b8b02a4SEd Tanous     using detail::extract_month;
50711b8b02a4SEd Tanous     using std::ios;
50721b8b02a4SEd Tanous     using std::chrono::duration_cast;
50731b8b02a4SEd Tanous     using std::chrono::seconds;
50741b8b02a4SEd Tanous     using std::chrono::minutes;
50751b8b02a4SEd Tanous     using std::chrono::hours;
50761b8b02a4SEd Tanous     date::detail::save_ostream<CharT, Traits> ss(os);
50771b8b02a4SEd Tanous     os.fill(' ');
50781b8b02a4SEd Tanous     os.flags(std::ios::skipws | std::ios::dec);
50791b8b02a4SEd Tanous     os.width(0);
50801b8b02a4SEd Tanous     tm tm{};
50811b8b02a4SEd Tanous     bool insert_negative = fds.has_tod && fds.tod.to_duration() < Duration::zero();
50821b8b02a4SEd Tanous #if !ONLY_C_LOCALE
50831b8b02a4SEd Tanous     auto& facet = std::use_facet<std::time_put<CharT>>(os.getloc());
50841b8b02a4SEd Tanous #endif
50851b8b02a4SEd Tanous     const CharT* command = nullptr;
50861b8b02a4SEd Tanous     CharT modified = CharT{};
50871b8b02a4SEd Tanous     for (; *fmt; ++fmt)
50881b8b02a4SEd Tanous     {
50891b8b02a4SEd Tanous         switch (*fmt)
50901b8b02a4SEd Tanous         {
50911b8b02a4SEd Tanous         case 'a':
50921b8b02a4SEd Tanous         case 'A':
50931b8b02a4SEd Tanous             if (command)
50941b8b02a4SEd Tanous             {
50951b8b02a4SEd Tanous                 if (modified == CharT{})
50961b8b02a4SEd Tanous                 {
50971b8b02a4SEd Tanous                     tm.tm_wday = static_cast<int>(extract_weekday(os, fds));
50981b8b02a4SEd Tanous                     if (os.fail())
50991b8b02a4SEd Tanous                         return os;
51001b8b02a4SEd Tanous #if !ONLY_C_LOCALE
51011b8b02a4SEd Tanous                     const CharT f[] = {'%', *fmt};
51021b8b02a4SEd Tanous                     facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
51031b8b02a4SEd Tanous #else  // ONLY_C_LOCALE
51041b8b02a4SEd Tanous                     os << weekday_names().first[tm.tm_wday+7*(*fmt == 'a')];
51051b8b02a4SEd Tanous #endif  // ONLY_C_LOCALE
51061b8b02a4SEd Tanous                 }
51071b8b02a4SEd Tanous                 else
51081b8b02a4SEd Tanous                 {
51091b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
51101b8b02a4SEd Tanous                     modified = CharT{};
51111b8b02a4SEd Tanous                 }
51121b8b02a4SEd Tanous                 command = nullptr;
51131b8b02a4SEd Tanous             }
51141b8b02a4SEd Tanous             else
51151b8b02a4SEd Tanous                 os << *fmt;
51161b8b02a4SEd Tanous             break;
51171b8b02a4SEd Tanous         case 'b':
51181b8b02a4SEd Tanous         case 'B':
51191b8b02a4SEd Tanous         case 'h':
51201b8b02a4SEd Tanous             if (command)
51211b8b02a4SEd Tanous             {
51221b8b02a4SEd Tanous                 if (modified == CharT{})
51231b8b02a4SEd Tanous                 {
51241b8b02a4SEd Tanous                     tm.tm_mon = static_cast<int>(extract_month(os, fds)) - 1;
51251b8b02a4SEd Tanous #if !ONLY_C_LOCALE
51261b8b02a4SEd Tanous                     const CharT f[] = {'%', *fmt};
51271b8b02a4SEd Tanous                     facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
51281b8b02a4SEd Tanous #else  // ONLY_C_LOCALE
51291b8b02a4SEd Tanous                     os << month_names().first[tm.tm_mon+12*(*fmt != 'B')];
51301b8b02a4SEd Tanous #endif  // ONLY_C_LOCALE
51311b8b02a4SEd Tanous                 }
51321b8b02a4SEd Tanous                 else
51331b8b02a4SEd Tanous                 {
51341b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
51351b8b02a4SEd Tanous                     modified = CharT{};
51361b8b02a4SEd Tanous                 }
51371b8b02a4SEd Tanous                 command = nullptr;
51381b8b02a4SEd Tanous             }
51391b8b02a4SEd Tanous             else
51401b8b02a4SEd Tanous                 os << *fmt;
51411b8b02a4SEd Tanous             break;
51421b8b02a4SEd Tanous         case 'c':
51431b8b02a4SEd Tanous         case 'x':
51441b8b02a4SEd Tanous             if (command)
51451b8b02a4SEd Tanous             {
51461b8b02a4SEd Tanous                 if (modified == CharT{'O'})
51471b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
51481b8b02a4SEd Tanous                 else
51491b8b02a4SEd Tanous                 {
51501b8b02a4SEd Tanous                     if (!fds.ymd.ok())
51511b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
51521b8b02a4SEd Tanous                     if (*fmt == 'c' && !fds.has_tod)
51531b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
51541b8b02a4SEd Tanous #if !ONLY_C_LOCALE
51551b8b02a4SEd Tanous                     tm = std::tm{};
51561b8b02a4SEd Tanous                     auto const& ymd = fds.ymd;
51571b8b02a4SEd Tanous                     auto ld = local_days(ymd);
51581b8b02a4SEd Tanous                     if (*fmt == 'c')
51591b8b02a4SEd Tanous                     {
51601b8b02a4SEd Tanous                         tm.tm_sec = static_cast<int>(fds.tod.seconds().count());
51611b8b02a4SEd Tanous                         tm.tm_min = static_cast<int>(fds.tod.minutes().count());
51621b8b02a4SEd Tanous                         tm.tm_hour = static_cast<int>(fds.tod.hours().count());
51631b8b02a4SEd Tanous                     }
51641b8b02a4SEd Tanous                     tm.tm_mday = static_cast<int>(static_cast<unsigned>(ymd.day()));
51651b8b02a4SEd Tanous                     tm.tm_mon = static_cast<int>(extract_month(os, fds) - 1);
51661b8b02a4SEd Tanous                     tm.tm_year = static_cast<int>(ymd.year()) - 1900;
51671b8b02a4SEd Tanous                     tm.tm_wday = static_cast<int>(extract_weekday(os, fds));
51681b8b02a4SEd Tanous                     if (os.fail())
51691b8b02a4SEd Tanous                         return os;
51701b8b02a4SEd Tanous                     tm.tm_yday = static_cast<int>((ld - local_days(ymd.year()/1/1)).count());
51711b8b02a4SEd Tanous                     CharT f[3] = {'%'};
51721b8b02a4SEd Tanous                     auto fe = std::begin(f) + 1;
51731b8b02a4SEd Tanous                     if (modified == CharT{'E'})
51741b8b02a4SEd Tanous                         *fe++ = modified;
51751b8b02a4SEd Tanous                     *fe++ = *fmt;
51761b8b02a4SEd Tanous                     facet.put(os, os, os.fill(), &tm, std::begin(f), fe);
51771b8b02a4SEd Tanous #else  // ONLY_C_LOCALE
51781b8b02a4SEd Tanous                     if (*fmt == 'c')
51791b8b02a4SEd Tanous                     {
51801b8b02a4SEd Tanous                         auto wd = static_cast<int>(extract_weekday(os, fds));
51811b8b02a4SEd Tanous                         os << weekday_names().first[static_cast<unsigned>(wd)+7]
51821b8b02a4SEd Tanous                            << ' ';
51831b8b02a4SEd Tanous                         os << month_names().first[extract_month(os, fds)-1+12] << ' ';
51841b8b02a4SEd Tanous                         auto d = static_cast<int>(static_cast<unsigned>(fds.ymd.day()));
51851b8b02a4SEd Tanous                         if (d < 10)
51861b8b02a4SEd Tanous                             os << ' ';
51871b8b02a4SEd Tanous                         os << d << ' '
51881b8b02a4SEd Tanous                            << make_time(duration_cast<seconds>(fds.tod.to_duration()))
51891b8b02a4SEd Tanous                            << ' ' << fds.ymd.year();
51901b8b02a4SEd Tanous 
51911b8b02a4SEd Tanous                     }
51921b8b02a4SEd Tanous                     else  // *fmt == 'x'
51931b8b02a4SEd Tanous                     {
51941b8b02a4SEd Tanous                         auto const& ymd = fds.ymd;
51951b8b02a4SEd Tanous                         save_ostream<CharT, Traits> _(os);
51961b8b02a4SEd Tanous                         os.fill('0');
51971b8b02a4SEd Tanous                         os.flags(std::ios::dec | std::ios::right);
51981b8b02a4SEd Tanous                         os.width(2);
51991b8b02a4SEd Tanous                         os << static_cast<unsigned>(ymd.month()) << CharT{'/'};
52001b8b02a4SEd Tanous                         os.width(2);
52011b8b02a4SEd Tanous                         os << static_cast<unsigned>(ymd.day()) << CharT{'/'};
52021b8b02a4SEd Tanous                         os.width(2);
52031b8b02a4SEd Tanous                         os << static_cast<int>(ymd.year()) % 100;
52041b8b02a4SEd Tanous                     }
52051b8b02a4SEd Tanous #endif  // ONLY_C_LOCALE
52061b8b02a4SEd Tanous                 }
52071b8b02a4SEd Tanous                 command = nullptr;
52081b8b02a4SEd Tanous                 modified = CharT{};
52091b8b02a4SEd Tanous             }
52101b8b02a4SEd Tanous             else
52111b8b02a4SEd Tanous                 os << *fmt;
52121b8b02a4SEd Tanous             break;
52131b8b02a4SEd Tanous         case 'C':
52141b8b02a4SEd Tanous             if (command)
52151b8b02a4SEd Tanous             {
52161b8b02a4SEd Tanous                 if (modified == CharT{'O'})
52171b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
52181b8b02a4SEd Tanous                 else
52191b8b02a4SEd Tanous                 {
52201b8b02a4SEd Tanous                     if (!fds.ymd.year().ok())
52211b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
52221b8b02a4SEd Tanous                     auto y = static_cast<int>(fds.ymd.year());
52231b8b02a4SEd Tanous #if !ONLY_C_LOCALE
52241b8b02a4SEd Tanous                     if (modified == CharT{})
52251b8b02a4SEd Tanous #endif
52261b8b02a4SEd Tanous                     {
52271b8b02a4SEd Tanous                         save_ostream<CharT, Traits> _(os);
52281b8b02a4SEd Tanous                         os.fill('0');
52291b8b02a4SEd Tanous                         os.flags(std::ios::dec | std::ios::right);
52301b8b02a4SEd Tanous                         if (y >= 0)
52311b8b02a4SEd Tanous                         {
52321b8b02a4SEd Tanous                             os.width(2);
52331b8b02a4SEd Tanous                             os << y/100;
52341b8b02a4SEd Tanous                         }
52351b8b02a4SEd Tanous                         else
52361b8b02a4SEd Tanous                         {
52371b8b02a4SEd Tanous                             os << CharT{'-'};
52381b8b02a4SEd Tanous                             os.width(2);
52391b8b02a4SEd Tanous                             os << -(y-99)/100;
52401b8b02a4SEd Tanous                         }
52411b8b02a4SEd Tanous                     }
52421b8b02a4SEd Tanous #if !ONLY_C_LOCALE
52431b8b02a4SEd Tanous                     else if (modified == CharT{'E'})
52441b8b02a4SEd Tanous                     {
52451b8b02a4SEd Tanous                         tm.tm_year = y - 1900;
52461b8b02a4SEd Tanous                         CharT f[3] = {'%', 'E', 'C'};
52471b8b02a4SEd Tanous                         facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
52481b8b02a4SEd Tanous                     }
52491b8b02a4SEd Tanous #endif
52501b8b02a4SEd Tanous                 }
52511b8b02a4SEd Tanous                 command = nullptr;
52521b8b02a4SEd Tanous                 modified = CharT{};
52531b8b02a4SEd Tanous             }
52541b8b02a4SEd Tanous             else
52551b8b02a4SEd Tanous                 os << *fmt;
52561b8b02a4SEd Tanous             break;
52571b8b02a4SEd Tanous         case 'd':
52581b8b02a4SEd Tanous         case 'e':
52591b8b02a4SEd Tanous             if (command)
52601b8b02a4SEd Tanous             {
52611b8b02a4SEd Tanous                 if (modified == CharT{'E'})
52621b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
52631b8b02a4SEd Tanous                 else
52641b8b02a4SEd Tanous                 {
52651b8b02a4SEd Tanous                     if (!fds.ymd.day().ok())
52661b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
52671b8b02a4SEd Tanous                     auto d = static_cast<int>(static_cast<unsigned>(fds.ymd.day()));
52681b8b02a4SEd Tanous #if !ONLY_C_LOCALE
52691b8b02a4SEd Tanous                     if (modified == CharT{})
52701b8b02a4SEd Tanous #endif
52711b8b02a4SEd Tanous                     {
52721b8b02a4SEd Tanous                         save_ostream<CharT, Traits> _(os);
52731b8b02a4SEd Tanous                         if (*fmt == CharT{'d'})
52741b8b02a4SEd Tanous                             os.fill('0');
52751b8b02a4SEd Tanous                         else
52761b8b02a4SEd Tanous                             os.fill(' ');
52771b8b02a4SEd Tanous                         os.flags(std::ios::dec | std::ios::right);
52781b8b02a4SEd Tanous                         os.width(2);
52791b8b02a4SEd Tanous                         os << d;
52801b8b02a4SEd Tanous                     }
52811b8b02a4SEd Tanous #if !ONLY_C_LOCALE
52821b8b02a4SEd Tanous                     else if (modified == CharT{'O'})
52831b8b02a4SEd Tanous                     {
52841b8b02a4SEd Tanous                         tm.tm_mday = d;
52851b8b02a4SEd Tanous                         CharT f[3] = {'%', 'O', *fmt};
52861b8b02a4SEd Tanous                         facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
52871b8b02a4SEd Tanous                     }
52881b8b02a4SEd Tanous #endif
52891b8b02a4SEd Tanous                 }
52901b8b02a4SEd Tanous                 command = nullptr;
52911b8b02a4SEd Tanous                 modified = CharT{};
52921b8b02a4SEd Tanous             }
52931b8b02a4SEd Tanous             else
52941b8b02a4SEd Tanous                 os << *fmt;
52951b8b02a4SEd Tanous             break;
52961b8b02a4SEd Tanous         case 'D':
52971b8b02a4SEd Tanous             if (command)
52981b8b02a4SEd Tanous             {
52991b8b02a4SEd Tanous                 if (modified == CharT{})
53001b8b02a4SEd Tanous                 {
53011b8b02a4SEd Tanous                     if (!fds.ymd.ok())
53021b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
53031b8b02a4SEd Tanous                     auto const& ymd = fds.ymd;
53041b8b02a4SEd Tanous                     save_ostream<CharT, Traits> _(os);
53051b8b02a4SEd Tanous                     os.fill('0');
53061b8b02a4SEd Tanous                     os.flags(std::ios::dec | std::ios::right);
53071b8b02a4SEd Tanous                     os.width(2);
53081b8b02a4SEd Tanous                     os << static_cast<unsigned>(ymd.month()) << CharT{'/'};
53091b8b02a4SEd Tanous                     os.width(2);
53101b8b02a4SEd Tanous                     os << static_cast<unsigned>(ymd.day()) << CharT{'/'};
53111b8b02a4SEd Tanous                     os.width(2);
53121b8b02a4SEd Tanous                     os << static_cast<int>(ymd.year()) % 100;
53131b8b02a4SEd Tanous                 }
53141b8b02a4SEd Tanous                 else
53151b8b02a4SEd Tanous                 {
53161b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
53171b8b02a4SEd Tanous                     modified = CharT{};
53181b8b02a4SEd Tanous                 }
53191b8b02a4SEd Tanous                 command = nullptr;
53201b8b02a4SEd Tanous             }
53211b8b02a4SEd Tanous             else
53221b8b02a4SEd Tanous                 os << *fmt;
53231b8b02a4SEd Tanous             break;
53241b8b02a4SEd Tanous         case 'F':
53251b8b02a4SEd Tanous             if (command)
53261b8b02a4SEd Tanous             {
53271b8b02a4SEd Tanous                 if (modified == CharT{})
53281b8b02a4SEd Tanous                 {
53291b8b02a4SEd Tanous                     if (!fds.ymd.ok())
53301b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
53311b8b02a4SEd Tanous                     auto const& ymd = fds.ymd;
53321b8b02a4SEd Tanous                     save_ostream<CharT, Traits> _(os);
53331b8b02a4SEd Tanous                     os.imbue(std::locale::classic());
53341b8b02a4SEd Tanous                     os.fill('0');
53351b8b02a4SEd Tanous                     os.flags(std::ios::dec | std::ios::right);
53361b8b02a4SEd Tanous                     os.width(4);
53371b8b02a4SEd Tanous                     os << static_cast<int>(ymd.year()) << CharT{'-'};
53381b8b02a4SEd Tanous                     os.width(2);
53391b8b02a4SEd Tanous                     os << static_cast<unsigned>(ymd.month()) << CharT{'-'};
53401b8b02a4SEd Tanous                     os.width(2);
53411b8b02a4SEd Tanous                     os << static_cast<unsigned>(ymd.day());
53421b8b02a4SEd Tanous                 }
53431b8b02a4SEd Tanous                 else
53441b8b02a4SEd Tanous                 {
53451b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
53461b8b02a4SEd Tanous                     modified = CharT{};
53471b8b02a4SEd Tanous                 }
53481b8b02a4SEd Tanous                 command = nullptr;
53491b8b02a4SEd Tanous             }
53501b8b02a4SEd Tanous             else
53511b8b02a4SEd Tanous                 os << *fmt;
53521b8b02a4SEd Tanous             break;
53531b8b02a4SEd Tanous         case 'g':
53541b8b02a4SEd Tanous         case 'G':
53551b8b02a4SEd Tanous             if (command)
53561b8b02a4SEd Tanous             {
53571b8b02a4SEd Tanous                 if (modified == CharT{})
53581b8b02a4SEd Tanous                 {
53591b8b02a4SEd Tanous                     if (!fds.ymd.ok())
53601b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
53611b8b02a4SEd Tanous                     auto ld = local_days(fds.ymd);
53621b8b02a4SEd Tanous                     auto y = year_month_day{ld + days{3}}.year();
53631b8b02a4SEd Tanous                     auto start = local_days((y-years{1})/December/Thursday[last]) +
53641b8b02a4SEd Tanous                                  (Monday-Thursday);
53651b8b02a4SEd Tanous                     if (ld < start)
53661b8b02a4SEd Tanous                         --y;
53671b8b02a4SEd Tanous                     if (*fmt == CharT{'G'})
53681b8b02a4SEd Tanous                         os << y;
53691b8b02a4SEd Tanous                     else
53701b8b02a4SEd Tanous                     {
53711b8b02a4SEd Tanous                         save_ostream<CharT, Traits> _(os);
53721b8b02a4SEd Tanous                         os.fill('0');
53731b8b02a4SEd Tanous                         os.flags(std::ios::dec | std::ios::right);
53741b8b02a4SEd Tanous                         os.width(2);
53751b8b02a4SEd Tanous                         os << std::abs(static_cast<int>(y)) % 100;
53761b8b02a4SEd Tanous                     }
53771b8b02a4SEd Tanous                 }
53781b8b02a4SEd Tanous                 else
53791b8b02a4SEd Tanous                 {
53801b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
53811b8b02a4SEd Tanous                     modified = CharT{};
53821b8b02a4SEd Tanous                 }
53831b8b02a4SEd Tanous                 command = nullptr;
53841b8b02a4SEd Tanous             }
53851b8b02a4SEd Tanous             else
53861b8b02a4SEd Tanous                 os << *fmt;
53871b8b02a4SEd Tanous             break;
53881b8b02a4SEd Tanous         case 'H':
53891b8b02a4SEd Tanous         case 'I':
53901b8b02a4SEd Tanous             if (command)
53911b8b02a4SEd Tanous             {
53921b8b02a4SEd Tanous                 if (modified == CharT{'E'})
53931b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
53941b8b02a4SEd Tanous                 else
53951b8b02a4SEd Tanous                 {
53961b8b02a4SEd Tanous                     if (!fds.has_tod)
53971b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
53981b8b02a4SEd Tanous                     if (insert_negative)
53991b8b02a4SEd Tanous                     {
54001b8b02a4SEd Tanous                         os << '-';
54011b8b02a4SEd Tanous                         insert_negative = false;
54021b8b02a4SEd Tanous                     }
54031b8b02a4SEd Tanous                     auto hms = fds.tod;
54041b8b02a4SEd Tanous #if !ONLY_C_LOCALE
54051b8b02a4SEd Tanous                     if (modified == CharT{})
54061b8b02a4SEd Tanous #endif
54071b8b02a4SEd Tanous                     {
54081b8b02a4SEd Tanous                         auto h = *fmt == CharT{'I'} ? date::make12(hms.hours()) : hms.hours();
54091b8b02a4SEd Tanous                         if (h < hours{10})
54101b8b02a4SEd Tanous                             os << CharT{'0'};
54111b8b02a4SEd Tanous                         os << h.count();
54121b8b02a4SEd Tanous                     }
54131b8b02a4SEd Tanous #if !ONLY_C_LOCALE
54141b8b02a4SEd Tanous                     else if (modified == CharT{'O'})
54151b8b02a4SEd Tanous                     {
54161b8b02a4SEd Tanous                         const CharT f[] = {'%', modified, *fmt};
54171b8b02a4SEd Tanous                         tm.tm_hour = static_cast<int>(hms.hours().count());
54181b8b02a4SEd Tanous                         facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
54191b8b02a4SEd Tanous                     }
54201b8b02a4SEd Tanous #endif
54211b8b02a4SEd Tanous                 }
54221b8b02a4SEd Tanous                 modified = CharT{};
54231b8b02a4SEd Tanous                 command = nullptr;
54241b8b02a4SEd Tanous             }
54251b8b02a4SEd Tanous             else
54261b8b02a4SEd Tanous                 os << *fmt;
54271b8b02a4SEd Tanous             break;
54281b8b02a4SEd Tanous         case 'j':
54291b8b02a4SEd Tanous             if (command)
54301b8b02a4SEd Tanous             {
54311b8b02a4SEd Tanous                 if (modified == CharT{})
54321b8b02a4SEd Tanous                 {
54331b8b02a4SEd Tanous                     if (fds.ymd.ok() || fds.has_tod)
54341b8b02a4SEd Tanous                     {
54351b8b02a4SEd Tanous                         days doy;
54361b8b02a4SEd Tanous                         if (fds.ymd.ok())
54371b8b02a4SEd Tanous                         {
54381b8b02a4SEd Tanous                             auto ld = local_days(fds.ymd);
54391b8b02a4SEd Tanous                             auto y = fds.ymd.year();
54401b8b02a4SEd Tanous                             doy = ld - local_days(y/January/1) + days{1};
54411b8b02a4SEd Tanous                         }
54421b8b02a4SEd Tanous                         else
54431b8b02a4SEd Tanous                         {
54441b8b02a4SEd Tanous                             doy = duration_cast<days>(fds.tod.to_duration());
54451b8b02a4SEd Tanous                         }
54461b8b02a4SEd Tanous                         save_ostream<CharT, Traits> _(os);
54471b8b02a4SEd Tanous                         os.fill('0');
54481b8b02a4SEd Tanous                         os.flags(std::ios::dec | std::ios::right);
54491b8b02a4SEd Tanous                         os.width(3);
54501b8b02a4SEd Tanous                         os << doy.count();
54511b8b02a4SEd Tanous                     }
54521b8b02a4SEd Tanous                     else
54531b8b02a4SEd Tanous                     {
54541b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
54551b8b02a4SEd Tanous                     }
54561b8b02a4SEd Tanous                 }
54571b8b02a4SEd Tanous                 else
54581b8b02a4SEd Tanous                 {
54591b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
54601b8b02a4SEd Tanous                     modified = CharT{};
54611b8b02a4SEd Tanous                 }
54621b8b02a4SEd Tanous                 command = nullptr;
54631b8b02a4SEd Tanous             }
54641b8b02a4SEd Tanous             else
54651b8b02a4SEd Tanous                 os << *fmt;
54661b8b02a4SEd Tanous             break;
54671b8b02a4SEd Tanous         case 'm':
54681b8b02a4SEd Tanous             if (command)
54691b8b02a4SEd Tanous             {
54701b8b02a4SEd Tanous                 if (modified == CharT{'E'})
54711b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
54721b8b02a4SEd Tanous                 else
54731b8b02a4SEd Tanous                 {
54741b8b02a4SEd Tanous                     if (!fds.ymd.month().ok())
54751b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
54761b8b02a4SEd Tanous                     auto m = static_cast<unsigned>(fds.ymd.month());
54771b8b02a4SEd Tanous #if !ONLY_C_LOCALE
54781b8b02a4SEd Tanous                     if (modified == CharT{})
54791b8b02a4SEd Tanous #endif
54801b8b02a4SEd Tanous                     {
54811b8b02a4SEd Tanous                         if (m < 10)
54821b8b02a4SEd Tanous                             os << CharT{'0'};
54831b8b02a4SEd Tanous                         os << m;
54841b8b02a4SEd Tanous                     }
54851b8b02a4SEd Tanous #if !ONLY_C_LOCALE
54861b8b02a4SEd Tanous                     else if (modified == CharT{'O'})
54871b8b02a4SEd Tanous                     {
54881b8b02a4SEd Tanous                         const CharT f[] = {'%', modified, *fmt};
54891b8b02a4SEd Tanous                         tm.tm_mon = static_cast<int>(m-1);
54901b8b02a4SEd Tanous                         facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
54911b8b02a4SEd Tanous                     }
54921b8b02a4SEd Tanous #endif
54931b8b02a4SEd Tanous                 }
54941b8b02a4SEd Tanous                 modified = CharT{};
54951b8b02a4SEd Tanous                 command = nullptr;
54961b8b02a4SEd Tanous             }
54971b8b02a4SEd Tanous             else
54981b8b02a4SEd Tanous                 os << *fmt;
54991b8b02a4SEd Tanous             break;
55001b8b02a4SEd Tanous         case 'M':
55011b8b02a4SEd Tanous             if (command)
55021b8b02a4SEd Tanous             {
55031b8b02a4SEd Tanous                 if (modified == CharT{'E'})
55041b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
55051b8b02a4SEd Tanous                 else
55061b8b02a4SEd Tanous                 {
55071b8b02a4SEd Tanous                     if (!fds.has_tod)
55081b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
55091b8b02a4SEd Tanous                     if (insert_negative)
55101b8b02a4SEd Tanous                     {
55111b8b02a4SEd Tanous                         os << '-';
55121b8b02a4SEd Tanous                         insert_negative = false;
55131b8b02a4SEd Tanous                     }
55141b8b02a4SEd Tanous #if !ONLY_C_LOCALE
55151b8b02a4SEd Tanous                     if (modified == CharT{})
55161b8b02a4SEd Tanous #endif
55171b8b02a4SEd Tanous                     {
55181b8b02a4SEd Tanous                         if (fds.tod.minutes() < minutes{10})
55191b8b02a4SEd Tanous                             os << CharT{'0'};
55201b8b02a4SEd Tanous                         os << fds.tod.minutes().count();
55211b8b02a4SEd Tanous                     }
55221b8b02a4SEd Tanous #if !ONLY_C_LOCALE
55231b8b02a4SEd Tanous                     else if (modified == CharT{'O'})
55241b8b02a4SEd Tanous                     {
55251b8b02a4SEd Tanous                         const CharT f[] = {'%', modified, *fmt};
55261b8b02a4SEd Tanous                         tm.tm_min = static_cast<int>(fds.tod.minutes().count());
55271b8b02a4SEd Tanous                         facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
55281b8b02a4SEd Tanous                     }
55291b8b02a4SEd Tanous #endif
55301b8b02a4SEd Tanous                 }
55311b8b02a4SEd Tanous                 modified = CharT{};
55321b8b02a4SEd Tanous                 command = nullptr;
55331b8b02a4SEd Tanous             }
55341b8b02a4SEd Tanous             else
55351b8b02a4SEd Tanous                 os << *fmt;
55361b8b02a4SEd Tanous             break;
55371b8b02a4SEd Tanous         case 'n':
55381b8b02a4SEd Tanous             if (command)
55391b8b02a4SEd Tanous             {
55401b8b02a4SEd Tanous                 if (modified == CharT{})
55411b8b02a4SEd Tanous                     os << CharT{'\n'};
55421b8b02a4SEd Tanous                 else
55431b8b02a4SEd Tanous                 {
55441b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
55451b8b02a4SEd Tanous                     modified = CharT{};
55461b8b02a4SEd Tanous                 }
55471b8b02a4SEd Tanous                 command = nullptr;
55481b8b02a4SEd Tanous             }
55491b8b02a4SEd Tanous             else
55501b8b02a4SEd Tanous                 os << *fmt;
55511b8b02a4SEd Tanous             break;
55521b8b02a4SEd Tanous         case 'p':
55531b8b02a4SEd Tanous             if (command)
55541b8b02a4SEd Tanous             {
55551b8b02a4SEd Tanous                 if (modified == CharT{})
55561b8b02a4SEd Tanous                 {
55571b8b02a4SEd Tanous                     if (!fds.has_tod)
55581b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
55591b8b02a4SEd Tanous #if !ONLY_C_LOCALE
55601b8b02a4SEd Tanous                     const CharT f[] = {'%', *fmt};
55611b8b02a4SEd Tanous                     tm.tm_hour = static_cast<int>(fds.tod.hours().count());
55621b8b02a4SEd Tanous                     facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
55631b8b02a4SEd Tanous #else
55641b8b02a4SEd Tanous                     if (date::is_am(fds.tod.hours()))
55651b8b02a4SEd Tanous                         os << ampm_names().first[0];
55661b8b02a4SEd Tanous                     else
55671b8b02a4SEd Tanous                         os << ampm_names().first[1];
55681b8b02a4SEd Tanous #endif
55691b8b02a4SEd Tanous                 }
55701b8b02a4SEd Tanous                 else
55711b8b02a4SEd Tanous                 {
55721b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
55731b8b02a4SEd Tanous                 }
55741b8b02a4SEd Tanous                 modified = CharT{};
55751b8b02a4SEd Tanous                 command = nullptr;
55761b8b02a4SEd Tanous             }
55771b8b02a4SEd Tanous             else
55781b8b02a4SEd Tanous                 os << *fmt;
55791b8b02a4SEd Tanous             break;
55801b8b02a4SEd Tanous         case 'Q':
55811b8b02a4SEd Tanous         case 'q':
55821b8b02a4SEd Tanous             if (command)
55831b8b02a4SEd Tanous             {
55841b8b02a4SEd Tanous                 if (modified == CharT{})
55851b8b02a4SEd Tanous                 {
55861b8b02a4SEd Tanous                     if (!fds.has_tod)
55871b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
55881b8b02a4SEd Tanous                     auto d = fds.tod.to_duration();
55891b8b02a4SEd Tanous                     if (*fmt == 'q')
55901b8b02a4SEd Tanous                         os << get_units<CharT>(typename decltype(d)::period::type{});
55911b8b02a4SEd Tanous                     else
55921b8b02a4SEd Tanous                         os << d.count();
55931b8b02a4SEd Tanous                 }
55941b8b02a4SEd Tanous                 else
55951b8b02a4SEd Tanous                 {
55961b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
55971b8b02a4SEd Tanous                 }
55981b8b02a4SEd Tanous                 modified = CharT{};
55991b8b02a4SEd Tanous                 command = nullptr;
56001b8b02a4SEd Tanous             }
56011b8b02a4SEd Tanous             else
56021b8b02a4SEd Tanous                 os << *fmt;
56031b8b02a4SEd Tanous             break;
56041b8b02a4SEd Tanous         case 'r':
56051b8b02a4SEd Tanous             if (command)
56061b8b02a4SEd Tanous             {
56071b8b02a4SEd Tanous                 if (modified == CharT{})
56081b8b02a4SEd Tanous                 {
56091b8b02a4SEd Tanous                     if (!fds.has_tod)
56101b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
56111b8b02a4SEd Tanous #if !ONLY_C_LOCALE
56121b8b02a4SEd Tanous                     const CharT f[] = {'%', *fmt};
56131b8b02a4SEd Tanous                     tm.tm_hour = static_cast<int>(fds.tod.hours().count());
56141b8b02a4SEd Tanous                     tm.tm_min = static_cast<int>(fds.tod.minutes().count());
56151b8b02a4SEd Tanous                     tm.tm_sec = static_cast<int>(fds.tod.seconds().count());
56161b8b02a4SEd Tanous                     facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
56171b8b02a4SEd Tanous #else
56181b8b02a4SEd Tanous                     hh_mm_ss<seconds> tod(duration_cast<seconds>(fds.tod.to_duration()));
56191b8b02a4SEd Tanous                     save_ostream<CharT, Traits> _(os);
56201b8b02a4SEd Tanous                     os.fill('0');
56211b8b02a4SEd Tanous                     os.width(2);
56221b8b02a4SEd Tanous                     os << date::make12(tod.hours()).count() << CharT{':'};
56231b8b02a4SEd Tanous                     os.width(2);
56241b8b02a4SEd Tanous                     os << tod.minutes().count() << CharT{':'};
56251b8b02a4SEd Tanous                     os.width(2);
56261b8b02a4SEd Tanous                     os << tod.seconds().count() << CharT{' '};
56271b8b02a4SEd Tanous                     if (date::is_am(tod.hours()))
56281b8b02a4SEd Tanous                         os << ampm_names().first[0];
56291b8b02a4SEd Tanous                     else
56301b8b02a4SEd Tanous                         os << ampm_names().first[1];
56311b8b02a4SEd Tanous #endif
56321b8b02a4SEd Tanous                 }
56331b8b02a4SEd Tanous                 else
56341b8b02a4SEd Tanous                 {
56351b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
56361b8b02a4SEd Tanous                 }
56371b8b02a4SEd Tanous                 modified = CharT{};
56381b8b02a4SEd Tanous                 command = nullptr;
56391b8b02a4SEd Tanous             }
56401b8b02a4SEd Tanous             else
56411b8b02a4SEd Tanous                 os << *fmt;
56421b8b02a4SEd Tanous             break;
56431b8b02a4SEd Tanous         case 'R':
56441b8b02a4SEd Tanous             if (command)
56451b8b02a4SEd Tanous             {
56461b8b02a4SEd Tanous                 if (modified == CharT{})
56471b8b02a4SEd Tanous                 {
56481b8b02a4SEd Tanous                     if (!fds.has_tod)
56491b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
56501b8b02a4SEd Tanous                     if (fds.tod.hours() < hours{10})
56511b8b02a4SEd Tanous                         os << CharT{'0'};
56521b8b02a4SEd Tanous                     os << fds.tod.hours().count() << CharT{':'};
56531b8b02a4SEd Tanous                     if (fds.tod.minutes() < minutes{10})
56541b8b02a4SEd Tanous                         os << CharT{'0'};
56551b8b02a4SEd Tanous                     os << fds.tod.minutes().count();
56561b8b02a4SEd Tanous                 }
56571b8b02a4SEd Tanous                 else
56581b8b02a4SEd Tanous                 {
56591b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
56601b8b02a4SEd Tanous                     modified = CharT{};
56611b8b02a4SEd Tanous                 }
56621b8b02a4SEd Tanous                 command = nullptr;
56631b8b02a4SEd Tanous             }
56641b8b02a4SEd Tanous             else
56651b8b02a4SEd Tanous                 os << *fmt;
56661b8b02a4SEd Tanous             break;
56671b8b02a4SEd Tanous         case 'S':
56681b8b02a4SEd Tanous             if (command)
56691b8b02a4SEd Tanous             {
56701b8b02a4SEd Tanous                 if (modified == CharT{'E'})
56711b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
56721b8b02a4SEd Tanous                 else
56731b8b02a4SEd Tanous                 {
56741b8b02a4SEd Tanous                     if (!fds.has_tod)
56751b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
56761b8b02a4SEd Tanous                     if (insert_negative)
56771b8b02a4SEd Tanous                     {
56781b8b02a4SEd Tanous                         os << '-';
56791b8b02a4SEd Tanous                         insert_negative = false;
56801b8b02a4SEd Tanous                     }
56811b8b02a4SEd Tanous #if !ONLY_C_LOCALE
56821b8b02a4SEd Tanous                     if (modified == CharT{})
56831b8b02a4SEd Tanous #endif
56841b8b02a4SEd Tanous                     {
56851b8b02a4SEd Tanous                         os << fds.tod.s_;
56861b8b02a4SEd Tanous                     }
56871b8b02a4SEd Tanous #if !ONLY_C_LOCALE
56881b8b02a4SEd Tanous                     else if (modified == CharT{'O'})
56891b8b02a4SEd Tanous                     {
56901b8b02a4SEd Tanous                         const CharT f[] = {'%', modified, *fmt};
56911b8b02a4SEd Tanous                         tm.tm_sec = static_cast<int>(fds.tod.s_.seconds().count());
56921b8b02a4SEd Tanous                         facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
56931b8b02a4SEd Tanous                     }
56941b8b02a4SEd Tanous #endif
56951b8b02a4SEd Tanous                 }
56961b8b02a4SEd Tanous                 modified = CharT{};
56971b8b02a4SEd Tanous                 command = nullptr;
56981b8b02a4SEd Tanous             }
56991b8b02a4SEd Tanous             else
57001b8b02a4SEd Tanous                 os << *fmt;
57011b8b02a4SEd Tanous             break;
57021b8b02a4SEd Tanous         case 't':
57031b8b02a4SEd Tanous             if (command)
57041b8b02a4SEd Tanous             {
57051b8b02a4SEd Tanous                 if (modified == CharT{})
57061b8b02a4SEd Tanous                     os << CharT{'\t'};
57071b8b02a4SEd Tanous                 else
57081b8b02a4SEd Tanous                 {
57091b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
57101b8b02a4SEd Tanous                     modified = CharT{};
57111b8b02a4SEd Tanous                 }
57121b8b02a4SEd Tanous                 command = nullptr;
57131b8b02a4SEd Tanous             }
57141b8b02a4SEd Tanous             else
57151b8b02a4SEd Tanous                 os << *fmt;
57161b8b02a4SEd Tanous             break;
57171b8b02a4SEd Tanous         case 'T':
57181b8b02a4SEd Tanous             if (command)
57191b8b02a4SEd Tanous             {
57201b8b02a4SEd Tanous                 if (modified == CharT{})
57211b8b02a4SEd Tanous                 {
57221b8b02a4SEd Tanous                     if (!fds.has_tod)
57231b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
57241b8b02a4SEd Tanous                     os << fds.tod;
57251b8b02a4SEd Tanous                 }
57261b8b02a4SEd Tanous                 else
57271b8b02a4SEd Tanous                 {
57281b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
57291b8b02a4SEd Tanous                     modified = CharT{};
57301b8b02a4SEd Tanous                 }
57311b8b02a4SEd Tanous                 command = nullptr;
57321b8b02a4SEd Tanous             }
57331b8b02a4SEd Tanous             else
57341b8b02a4SEd Tanous                 os << *fmt;
57351b8b02a4SEd Tanous             break;
57361b8b02a4SEd Tanous         case 'u':
57371b8b02a4SEd Tanous             if (command)
57381b8b02a4SEd Tanous             {
57391b8b02a4SEd Tanous                 if (modified == CharT{'E'})
57401b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
57411b8b02a4SEd Tanous                 else
57421b8b02a4SEd Tanous                 {
57431b8b02a4SEd Tanous                     auto wd = extract_weekday(os, fds);
57441b8b02a4SEd Tanous #if !ONLY_C_LOCALE
57451b8b02a4SEd Tanous                     if (modified == CharT{})
57461b8b02a4SEd Tanous #endif
57471b8b02a4SEd Tanous                     {
57481b8b02a4SEd Tanous                         os << (wd != 0 ? wd : 7u);
57491b8b02a4SEd Tanous                     }
57501b8b02a4SEd Tanous #if !ONLY_C_LOCALE
57511b8b02a4SEd Tanous                     else if (modified == CharT{'O'})
57521b8b02a4SEd Tanous                     {
57531b8b02a4SEd Tanous                         const CharT f[] = {'%', modified, *fmt};
57541b8b02a4SEd Tanous                         tm.tm_wday = static_cast<int>(wd);
57551b8b02a4SEd Tanous                         facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
57561b8b02a4SEd Tanous                     }
57571b8b02a4SEd Tanous #endif
57581b8b02a4SEd Tanous                 }
57591b8b02a4SEd Tanous                 modified = CharT{};
57601b8b02a4SEd Tanous                 command = nullptr;
57611b8b02a4SEd Tanous             }
57621b8b02a4SEd Tanous             else
57631b8b02a4SEd Tanous                 os << *fmt;
57641b8b02a4SEd Tanous             break;
57651b8b02a4SEd Tanous         case 'U':
57661b8b02a4SEd Tanous             if (command)
57671b8b02a4SEd Tanous             {
57681b8b02a4SEd Tanous                 if (modified == CharT{'E'})
57691b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
57701b8b02a4SEd Tanous                 else
57711b8b02a4SEd Tanous                 {
57721b8b02a4SEd Tanous                     auto const& ymd = fds.ymd;
57731b8b02a4SEd Tanous                     if (!ymd.ok())
57741b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
57751b8b02a4SEd Tanous                     auto ld = local_days(ymd);
57761b8b02a4SEd Tanous #if !ONLY_C_LOCALE
57771b8b02a4SEd Tanous                     if (modified == CharT{})
57781b8b02a4SEd Tanous #endif
57791b8b02a4SEd Tanous                     {
57801b8b02a4SEd Tanous                         auto st = local_days(Sunday[1]/January/ymd.year());
57811b8b02a4SEd Tanous                         if (ld < st)
57821b8b02a4SEd Tanous                             os << CharT{'0'} << CharT{'0'};
57831b8b02a4SEd Tanous                         else
57841b8b02a4SEd Tanous                         {
57851b8b02a4SEd Tanous                             auto wn = duration_cast<weeks>(ld - st).count() + 1;
57861b8b02a4SEd Tanous                             if (wn < 10)
57871b8b02a4SEd Tanous                                 os << CharT{'0'};
57881b8b02a4SEd Tanous                             os << wn;
57891b8b02a4SEd Tanous                         }
57901b8b02a4SEd Tanous                    }
57911b8b02a4SEd Tanous  #if !ONLY_C_LOCALE
57921b8b02a4SEd Tanous                     else if (modified == CharT{'O'})
57931b8b02a4SEd Tanous                     {
57941b8b02a4SEd Tanous                         const CharT f[] = {'%', modified, *fmt};
57951b8b02a4SEd Tanous                         tm.tm_year = static_cast<int>(ymd.year()) - 1900;
57961b8b02a4SEd Tanous                         tm.tm_wday = static_cast<int>(extract_weekday(os, fds));
57971b8b02a4SEd Tanous                         if (os.fail())
57981b8b02a4SEd Tanous                             return os;
57991b8b02a4SEd Tanous                         tm.tm_yday = static_cast<int>((ld - local_days(ymd.year()/1/1)).count());
58001b8b02a4SEd Tanous                         facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
58011b8b02a4SEd Tanous                     }
58021b8b02a4SEd Tanous #endif
58031b8b02a4SEd Tanous                 }
58041b8b02a4SEd Tanous                 modified = CharT{};
58051b8b02a4SEd Tanous                 command = nullptr;
58061b8b02a4SEd Tanous             }
58071b8b02a4SEd Tanous             else
58081b8b02a4SEd Tanous                 os << *fmt;
58091b8b02a4SEd Tanous             break;
58101b8b02a4SEd Tanous         case 'V':
58111b8b02a4SEd Tanous             if (command)
58121b8b02a4SEd Tanous             {
58131b8b02a4SEd Tanous                 if (modified == CharT{'E'})
58141b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
58151b8b02a4SEd Tanous                 else
58161b8b02a4SEd Tanous                 {
58171b8b02a4SEd Tanous                     if (!fds.ymd.ok())
58181b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
58191b8b02a4SEd Tanous                     auto ld = local_days(fds.ymd);
58201b8b02a4SEd Tanous #if !ONLY_C_LOCALE
58211b8b02a4SEd Tanous                     if (modified == CharT{})
58221b8b02a4SEd Tanous #endif
58231b8b02a4SEd Tanous                     {
58241b8b02a4SEd Tanous                         auto y = year_month_day{ld + days{3}}.year();
58251b8b02a4SEd Tanous                         auto st = local_days((y-years{1})/12/Thursday[last]) +
58261b8b02a4SEd Tanous                                   (Monday-Thursday);
58271b8b02a4SEd Tanous                         if (ld < st)
58281b8b02a4SEd Tanous                         {
58291b8b02a4SEd Tanous                             --y;
58301b8b02a4SEd Tanous                             st = local_days((y - years{1})/12/Thursday[last]) +
58311b8b02a4SEd Tanous                                  (Monday-Thursday);
58321b8b02a4SEd Tanous                         }
58331b8b02a4SEd Tanous                         auto wn = duration_cast<weeks>(ld - st).count() + 1;
58341b8b02a4SEd Tanous                         if (wn < 10)
58351b8b02a4SEd Tanous                             os << CharT{'0'};
58361b8b02a4SEd Tanous                         os << wn;
58371b8b02a4SEd Tanous                     }
58381b8b02a4SEd Tanous #if !ONLY_C_LOCALE
58391b8b02a4SEd Tanous                     else if (modified == CharT{'O'})
58401b8b02a4SEd Tanous                     {
58411b8b02a4SEd Tanous                         const CharT f[] = {'%', modified, *fmt};
58421b8b02a4SEd Tanous                         auto const& ymd = fds.ymd;
58431b8b02a4SEd Tanous                         tm.tm_year = static_cast<int>(ymd.year()) - 1900;
58441b8b02a4SEd Tanous                         tm.tm_wday = static_cast<int>(extract_weekday(os, fds));
58451b8b02a4SEd Tanous                         if (os.fail())
58461b8b02a4SEd Tanous                             return os;
58471b8b02a4SEd Tanous                         tm.tm_yday = static_cast<int>((ld - local_days(ymd.year()/1/1)).count());
58481b8b02a4SEd Tanous                         facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
58491b8b02a4SEd Tanous                     }
58501b8b02a4SEd Tanous #endif
58511b8b02a4SEd Tanous                 }
58521b8b02a4SEd Tanous                 modified = CharT{};
58531b8b02a4SEd Tanous                 command = nullptr;
58541b8b02a4SEd Tanous             }
58551b8b02a4SEd Tanous             else
58561b8b02a4SEd Tanous                 os << *fmt;
58571b8b02a4SEd Tanous             break;
58581b8b02a4SEd Tanous         case 'w':
58591b8b02a4SEd Tanous             if (command)
58601b8b02a4SEd Tanous             {
58611b8b02a4SEd Tanous                 auto wd = extract_weekday(os, fds);
58621b8b02a4SEd Tanous                 if (os.fail())
58631b8b02a4SEd Tanous                     return os;
58641b8b02a4SEd Tanous #if !ONLY_C_LOCALE
58651b8b02a4SEd Tanous                 if (modified == CharT{})
58661b8b02a4SEd Tanous #else
58671b8b02a4SEd Tanous                 if (modified != CharT{'E'})
58681b8b02a4SEd Tanous #endif
58691b8b02a4SEd Tanous                 {
58701b8b02a4SEd Tanous                     os << wd;
58711b8b02a4SEd Tanous                 }
58721b8b02a4SEd Tanous #if !ONLY_C_LOCALE
58731b8b02a4SEd Tanous                 else if (modified == CharT{'O'})
58741b8b02a4SEd Tanous                 {
58751b8b02a4SEd Tanous                     const CharT f[] = {'%', modified, *fmt};
58761b8b02a4SEd Tanous                     tm.tm_wday = static_cast<int>(wd);
58771b8b02a4SEd Tanous                     facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
58781b8b02a4SEd Tanous                 }
58791b8b02a4SEd Tanous #endif
58801b8b02a4SEd Tanous                 else
58811b8b02a4SEd Tanous                 {
58821b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
58831b8b02a4SEd Tanous                 }
58841b8b02a4SEd Tanous                 modified = CharT{};
58851b8b02a4SEd Tanous                 command = nullptr;
58861b8b02a4SEd Tanous             }
58871b8b02a4SEd Tanous             else
58881b8b02a4SEd Tanous                 os << *fmt;
58891b8b02a4SEd Tanous             break;
58901b8b02a4SEd Tanous         case 'W':
58911b8b02a4SEd Tanous             if (command)
58921b8b02a4SEd Tanous             {
58931b8b02a4SEd Tanous                 if (modified == CharT{'E'})
58941b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
58951b8b02a4SEd Tanous                 else
58961b8b02a4SEd Tanous                 {
58971b8b02a4SEd Tanous                     auto const& ymd = fds.ymd;
58981b8b02a4SEd Tanous                     if (!ymd.ok())
58991b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
59001b8b02a4SEd Tanous                     auto ld = local_days(ymd);
59011b8b02a4SEd Tanous #if !ONLY_C_LOCALE
59021b8b02a4SEd Tanous                     if (modified == CharT{})
59031b8b02a4SEd Tanous #endif
59041b8b02a4SEd Tanous                     {
59051b8b02a4SEd Tanous                         auto st = local_days(Monday[1]/January/ymd.year());
59061b8b02a4SEd Tanous                         if (ld < st)
59071b8b02a4SEd Tanous                             os << CharT{'0'} << CharT{'0'};
59081b8b02a4SEd Tanous                         else
59091b8b02a4SEd Tanous                         {
59101b8b02a4SEd Tanous                             auto wn = duration_cast<weeks>(ld - st).count() + 1;
59111b8b02a4SEd Tanous                             if (wn < 10)
59121b8b02a4SEd Tanous                                 os << CharT{'0'};
59131b8b02a4SEd Tanous                             os << wn;
59141b8b02a4SEd Tanous                         }
59151b8b02a4SEd Tanous                     }
59161b8b02a4SEd Tanous #if !ONLY_C_LOCALE
59171b8b02a4SEd Tanous                     else if (modified == CharT{'O'})
59181b8b02a4SEd Tanous                     {
59191b8b02a4SEd Tanous                         const CharT f[] = {'%', modified, *fmt};
59201b8b02a4SEd Tanous                         tm.tm_year = static_cast<int>(ymd.year()) - 1900;
59211b8b02a4SEd Tanous                         tm.tm_wday = static_cast<int>(extract_weekday(os, fds));
59221b8b02a4SEd Tanous                         if (os.fail())
59231b8b02a4SEd Tanous                             return os;
59241b8b02a4SEd Tanous                         tm.tm_yday = static_cast<int>((ld - local_days(ymd.year()/1/1)).count());
59251b8b02a4SEd Tanous                         facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
59261b8b02a4SEd Tanous                     }
59271b8b02a4SEd Tanous #endif
59281b8b02a4SEd Tanous                 }
59291b8b02a4SEd Tanous                 modified = CharT{};
59301b8b02a4SEd Tanous                 command = nullptr;
59311b8b02a4SEd Tanous             }
59321b8b02a4SEd Tanous             else
59331b8b02a4SEd Tanous                 os << *fmt;
59341b8b02a4SEd Tanous             break;
59351b8b02a4SEd Tanous         case 'X':
59361b8b02a4SEd Tanous             if (command)
59371b8b02a4SEd Tanous             {
59381b8b02a4SEd Tanous                 if (modified == CharT{'O'})
59391b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
59401b8b02a4SEd Tanous                 else
59411b8b02a4SEd Tanous                 {
59421b8b02a4SEd Tanous                     if (!fds.has_tod)
59431b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
59441b8b02a4SEd Tanous #if !ONLY_C_LOCALE
59451b8b02a4SEd Tanous                     tm = std::tm{};
59461b8b02a4SEd Tanous                     tm.tm_sec = static_cast<int>(fds.tod.seconds().count());
59471b8b02a4SEd Tanous                     tm.tm_min = static_cast<int>(fds.tod.minutes().count());
59481b8b02a4SEd Tanous                     tm.tm_hour = static_cast<int>(fds.tod.hours().count());
59491b8b02a4SEd Tanous                     CharT f[3] = {'%'};
59501b8b02a4SEd Tanous                     auto fe = std::begin(f) + 1;
59511b8b02a4SEd Tanous                     if (modified == CharT{'E'})
59521b8b02a4SEd Tanous                         *fe++ = modified;
59531b8b02a4SEd Tanous                     *fe++ = *fmt;
59541b8b02a4SEd Tanous                     facet.put(os, os, os.fill(), &tm, std::begin(f), fe);
59551b8b02a4SEd Tanous #else
59561b8b02a4SEd Tanous                     os << fds.tod;
59571b8b02a4SEd Tanous #endif
59581b8b02a4SEd Tanous                 }
59591b8b02a4SEd Tanous                 command = nullptr;
59601b8b02a4SEd Tanous                 modified = CharT{};
59611b8b02a4SEd Tanous             }
59621b8b02a4SEd Tanous             else
59631b8b02a4SEd Tanous                 os << *fmt;
59641b8b02a4SEd Tanous             break;
59651b8b02a4SEd Tanous         case 'y':
59661b8b02a4SEd Tanous             if (command)
59671b8b02a4SEd Tanous             {
59681b8b02a4SEd Tanous                 if (!fds.ymd.year().ok())
59691b8b02a4SEd Tanous                     os.setstate(std::ios::failbit);
59701b8b02a4SEd Tanous                 auto y = static_cast<int>(fds.ymd.year());
59711b8b02a4SEd Tanous #if !ONLY_C_LOCALE
59721b8b02a4SEd Tanous                 if (modified == CharT{})
59731b8b02a4SEd Tanous                 {
59741b8b02a4SEd Tanous #endif
59751b8b02a4SEd Tanous                     y = std::abs(y) % 100;
59761b8b02a4SEd Tanous                     if (y < 10)
59771b8b02a4SEd Tanous                         os << CharT{'0'};
59781b8b02a4SEd Tanous                     os << y;
59791b8b02a4SEd Tanous #if !ONLY_C_LOCALE
59801b8b02a4SEd Tanous                 }
59811b8b02a4SEd Tanous                 else
59821b8b02a4SEd Tanous                 {
59831b8b02a4SEd Tanous                     const CharT f[] = {'%', modified, *fmt};
59841b8b02a4SEd Tanous                     tm.tm_year = y - 1900;
59851b8b02a4SEd Tanous                     facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
59861b8b02a4SEd Tanous                 }
59871b8b02a4SEd Tanous #endif
59881b8b02a4SEd Tanous                 modified = CharT{};
59891b8b02a4SEd Tanous                 command = nullptr;
59901b8b02a4SEd Tanous             }
59911b8b02a4SEd Tanous             else
59921b8b02a4SEd Tanous                 os << *fmt;
59931b8b02a4SEd Tanous             break;
59941b8b02a4SEd Tanous         case 'Y':
59951b8b02a4SEd Tanous             if (command)
59961b8b02a4SEd Tanous             {
59971b8b02a4SEd Tanous                 if (modified == CharT{'O'})
59981b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
59991b8b02a4SEd Tanous                 else
60001b8b02a4SEd Tanous                 {
60011b8b02a4SEd Tanous                     if (!fds.ymd.year().ok())
60021b8b02a4SEd Tanous                         os.setstate(std::ios::failbit);
60031b8b02a4SEd Tanous                     auto y = fds.ymd.year();
60041b8b02a4SEd Tanous #if !ONLY_C_LOCALE
60051b8b02a4SEd Tanous                     if (modified == CharT{})
60061b8b02a4SEd Tanous #endif
60071b8b02a4SEd Tanous                     {
60081b8b02a4SEd Tanous                         save_ostream<CharT, Traits> _(os);
60091b8b02a4SEd Tanous                         os.imbue(std::locale::classic());
60101b8b02a4SEd Tanous                         os << y;
60111b8b02a4SEd Tanous                     }
60121b8b02a4SEd Tanous #if !ONLY_C_LOCALE
60131b8b02a4SEd Tanous                     else if (modified == CharT{'E'})
60141b8b02a4SEd Tanous                     {
60151b8b02a4SEd Tanous                         const CharT f[] = {'%', modified, *fmt};
60161b8b02a4SEd Tanous                         tm.tm_year = static_cast<int>(y) - 1900;
60171b8b02a4SEd Tanous                         facet.put(os, os, os.fill(), &tm, std::begin(f), std::end(f));
60181b8b02a4SEd Tanous                     }
60191b8b02a4SEd Tanous #endif
60201b8b02a4SEd Tanous                 }
60211b8b02a4SEd Tanous                 modified = CharT{};
60221b8b02a4SEd Tanous                 command = nullptr;
60231b8b02a4SEd Tanous             }
60241b8b02a4SEd Tanous             else
60251b8b02a4SEd Tanous                 os << *fmt;
60261b8b02a4SEd Tanous             break;
60271b8b02a4SEd Tanous         case 'z':
60281b8b02a4SEd Tanous             if (command)
60291b8b02a4SEd Tanous             {
60301b8b02a4SEd Tanous                 if (offset_sec == nullptr)
60311b8b02a4SEd Tanous                 {
60321b8b02a4SEd Tanous                     // Can not format %z with unknown offset
60331b8b02a4SEd Tanous                     os.setstate(ios::failbit);
60341b8b02a4SEd Tanous                     return os;
60351b8b02a4SEd Tanous                 }
60361b8b02a4SEd Tanous                 auto m = duration_cast<minutes>(*offset_sec);
60371b8b02a4SEd Tanous                 auto neg = m < minutes{0};
60381b8b02a4SEd Tanous                 m = date::abs(m);
60391b8b02a4SEd Tanous                 auto h = duration_cast<hours>(m);
60401b8b02a4SEd Tanous                 m -= h;
60411b8b02a4SEd Tanous                 if (neg)
60421b8b02a4SEd Tanous                     os << CharT{'-'};
60431b8b02a4SEd Tanous                 else
60441b8b02a4SEd Tanous                     os << CharT{'+'};
60451b8b02a4SEd Tanous                 if (h < hours{10})
60461b8b02a4SEd Tanous                     os << CharT{'0'};
60471b8b02a4SEd Tanous                 os << h.count();
60481b8b02a4SEd Tanous                 if (modified != CharT{})
60491b8b02a4SEd Tanous                     os << CharT{':'};
60501b8b02a4SEd Tanous                 if (m < minutes{10})
60511b8b02a4SEd Tanous                     os << CharT{'0'};
60521b8b02a4SEd Tanous                 os << m.count();
60531b8b02a4SEd Tanous                 command = nullptr;
60541b8b02a4SEd Tanous                 modified = CharT{};
60551b8b02a4SEd Tanous             }
60561b8b02a4SEd Tanous             else
60571b8b02a4SEd Tanous                 os << *fmt;
60581b8b02a4SEd Tanous             break;
60591b8b02a4SEd Tanous         case 'Z':
60601b8b02a4SEd Tanous             if (command)
60611b8b02a4SEd Tanous             {
60621b8b02a4SEd Tanous                 if (modified == CharT{})
60631b8b02a4SEd Tanous                 {
60641b8b02a4SEd Tanous                     if (abbrev == nullptr)
60651b8b02a4SEd Tanous                     {
60661b8b02a4SEd Tanous                         // Can not format %Z with unknown time_zone
60671b8b02a4SEd Tanous                         os.setstate(ios::failbit);
60681b8b02a4SEd Tanous                         return os;
60691b8b02a4SEd Tanous                     }
60701b8b02a4SEd Tanous                     for (auto c : *abbrev)
60711b8b02a4SEd Tanous                         os << CharT(c);
60721b8b02a4SEd Tanous                 }
60731b8b02a4SEd Tanous                 else
60741b8b02a4SEd Tanous                 {
60751b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
60761b8b02a4SEd Tanous                     modified = CharT{};
60771b8b02a4SEd Tanous                 }
60781b8b02a4SEd Tanous                 command = nullptr;
60791b8b02a4SEd Tanous             }
60801b8b02a4SEd Tanous             else
60811b8b02a4SEd Tanous                 os << *fmt;
60821b8b02a4SEd Tanous             break;
60831b8b02a4SEd Tanous         case 'E':
60841b8b02a4SEd Tanous         case 'O':
60851b8b02a4SEd Tanous             if (command)
60861b8b02a4SEd Tanous             {
60871b8b02a4SEd Tanous                 if (modified == CharT{})
60881b8b02a4SEd Tanous                 {
60891b8b02a4SEd Tanous                     modified = *fmt;
60901b8b02a4SEd Tanous                 }
60911b8b02a4SEd Tanous                 else
60921b8b02a4SEd Tanous                 {
60931b8b02a4SEd Tanous                     os << CharT{'%'} << modified << *fmt;
60941b8b02a4SEd Tanous                     command = nullptr;
60951b8b02a4SEd Tanous                     modified = CharT{};
60961b8b02a4SEd Tanous                 }
60971b8b02a4SEd Tanous             }
60981b8b02a4SEd Tanous             else
60991b8b02a4SEd Tanous                 os << *fmt;
61001b8b02a4SEd Tanous             break;
61011b8b02a4SEd Tanous         case '%':
61021b8b02a4SEd Tanous             if (command)
61031b8b02a4SEd Tanous             {
61041b8b02a4SEd Tanous                 if (modified == CharT{})
61051b8b02a4SEd Tanous                 {
61061b8b02a4SEd Tanous                     os << CharT{'%'};
61071b8b02a4SEd Tanous                     command = nullptr;
61081b8b02a4SEd Tanous                 }
61091b8b02a4SEd Tanous                 else
61101b8b02a4SEd Tanous                 {
61111b8b02a4SEd Tanous                     os << CharT{'%'} << modified << CharT{'%'};
61121b8b02a4SEd Tanous                     command = nullptr;
61131b8b02a4SEd Tanous                     modified = CharT{};
61141b8b02a4SEd Tanous                 }
61151b8b02a4SEd Tanous             }
61161b8b02a4SEd Tanous             else
61171b8b02a4SEd Tanous                 command = fmt;
61181b8b02a4SEd Tanous             break;
61191b8b02a4SEd Tanous         default:
61201b8b02a4SEd Tanous             if (command)
61211b8b02a4SEd Tanous             {
61221b8b02a4SEd Tanous                 os << CharT{'%'};
61231b8b02a4SEd Tanous                 command = nullptr;
61241b8b02a4SEd Tanous             }
61251b8b02a4SEd Tanous             if (modified != CharT{})
61261b8b02a4SEd Tanous             {
61271b8b02a4SEd Tanous                 os << modified;
61281b8b02a4SEd Tanous                 modified = CharT{};
61291b8b02a4SEd Tanous             }
61301b8b02a4SEd Tanous             os << *fmt;
61311b8b02a4SEd Tanous             break;
61321b8b02a4SEd Tanous         }
61331b8b02a4SEd Tanous     }
61341b8b02a4SEd Tanous     if (command)
61351b8b02a4SEd Tanous         os << CharT{'%'};
61361b8b02a4SEd Tanous     if (modified != CharT{})
61371b8b02a4SEd Tanous         os << modified;
61381b8b02a4SEd Tanous     return os;
61391b8b02a4SEd Tanous }
61401b8b02a4SEd Tanous 
61411b8b02a4SEd Tanous template <class CharT, class Traits>
61421b8b02a4SEd Tanous inline
61431b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
61441b8b02a4SEd Tanous to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt, const year& y)
61451b8b02a4SEd Tanous {
61461b8b02a4SEd Tanous     using CT = std::chrono::seconds;
61471b8b02a4SEd Tanous     fields<CT> fds{y/0/0};
61481b8b02a4SEd Tanous     return to_stream(os, fmt, fds);
61491b8b02a4SEd Tanous }
61501b8b02a4SEd Tanous 
61511b8b02a4SEd Tanous template <class CharT, class Traits>
61521b8b02a4SEd Tanous inline
61531b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
61541b8b02a4SEd Tanous to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt, const month& m)
61551b8b02a4SEd Tanous {
61561b8b02a4SEd Tanous     using CT = std::chrono::seconds;
61571b8b02a4SEd Tanous     fields<CT> fds{m/0/nanyear};
61581b8b02a4SEd Tanous     return to_stream(os, fmt, fds);
61591b8b02a4SEd Tanous }
61601b8b02a4SEd Tanous 
61611b8b02a4SEd Tanous template <class CharT, class Traits>
61621b8b02a4SEd Tanous inline
61631b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
61641b8b02a4SEd Tanous to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt, const day& d)
61651b8b02a4SEd Tanous {
61661b8b02a4SEd Tanous     using CT = std::chrono::seconds;
61671b8b02a4SEd Tanous     fields<CT> fds{d/0/nanyear};
61681b8b02a4SEd Tanous     return to_stream(os, fmt, fds);
61691b8b02a4SEd Tanous }
61701b8b02a4SEd Tanous 
61711b8b02a4SEd Tanous template <class CharT, class Traits>
61721b8b02a4SEd Tanous inline
61731b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
61741b8b02a4SEd Tanous to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt, const weekday& wd)
61751b8b02a4SEd Tanous {
61761b8b02a4SEd Tanous     using CT = std::chrono::seconds;
61771b8b02a4SEd Tanous     fields<CT> fds{wd};
61781b8b02a4SEd Tanous     return to_stream(os, fmt, fds);
61791b8b02a4SEd Tanous }
61801b8b02a4SEd Tanous 
61811b8b02a4SEd Tanous template <class CharT, class Traits>
61821b8b02a4SEd Tanous inline
61831b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
61841b8b02a4SEd Tanous to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt, const year_month& ym)
61851b8b02a4SEd Tanous {
61861b8b02a4SEd Tanous     using CT = std::chrono::seconds;
61871b8b02a4SEd Tanous     fields<CT> fds{ym/0};
61881b8b02a4SEd Tanous     return to_stream(os, fmt, fds);
61891b8b02a4SEd Tanous }
61901b8b02a4SEd Tanous 
61911b8b02a4SEd Tanous template <class CharT, class Traits>
61921b8b02a4SEd Tanous inline
61931b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
61941b8b02a4SEd Tanous to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt, const month_day& md)
61951b8b02a4SEd Tanous {
61961b8b02a4SEd Tanous     using CT = std::chrono::seconds;
61971b8b02a4SEd Tanous     fields<CT> fds{md/nanyear};
61981b8b02a4SEd Tanous     return to_stream(os, fmt, fds);
61991b8b02a4SEd Tanous }
62001b8b02a4SEd Tanous 
62011b8b02a4SEd Tanous template <class CharT, class Traits>
62021b8b02a4SEd Tanous inline
62031b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
62041b8b02a4SEd Tanous to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
62051b8b02a4SEd Tanous           const year_month_day& ymd)
62061b8b02a4SEd Tanous {
62071b8b02a4SEd Tanous     using CT = std::chrono::seconds;
62081b8b02a4SEd Tanous     fields<CT> fds{ymd};
62091b8b02a4SEd Tanous     return to_stream(os, fmt, fds);
62101b8b02a4SEd Tanous }
62111b8b02a4SEd Tanous 
62121b8b02a4SEd Tanous template <class CharT, class Traits, class Rep, class Period>
62131b8b02a4SEd Tanous inline
62141b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
62151b8b02a4SEd Tanous to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
62161b8b02a4SEd Tanous           const std::chrono::duration<Rep, Period>& d)
62171b8b02a4SEd Tanous {
62181b8b02a4SEd Tanous     using Duration = std::chrono::duration<Rep, Period>;
62191b8b02a4SEd Tanous     using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
62201b8b02a4SEd Tanous     fields<CT> fds{hh_mm_ss<CT>{d}};
62211b8b02a4SEd Tanous     return to_stream(os, fmt, fds);
62221b8b02a4SEd Tanous }
62231b8b02a4SEd Tanous 
62241b8b02a4SEd Tanous template <class CharT, class Traits, class Duration>
62251b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
62261b8b02a4SEd Tanous to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
62271b8b02a4SEd Tanous           const local_time<Duration>& tp, const std::string* abbrev = nullptr,
62281b8b02a4SEd Tanous           const std::chrono::seconds* offset_sec = nullptr)
62291b8b02a4SEd Tanous {
62301b8b02a4SEd Tanous     using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
62311b8b02a4SEd Tanous     auto ld = std::chrono::time_point_cast<days>(tp);
62321b8b02a4SEd Tanous     fields<CT> fds;
62331b8b02a4SEd Tanous     if (ld <= tp)
62341b8b02a4SEd Tanous         fds = fields<CT>{year_month_day{ld}, hh_mm_ss<CT>{tp-local_seconds{ld}}};
62351b8b02a4SEd Tanous     else
62361b8b02a4SEd Tanous         fds = fields<CT>{year_month_day{ld - days{1}},
62371b8b02a4SEd Tanous                          hh_mm_ss<CT>{days{1} - (local_seconds{ld} - tp)}};
62381b8b02a4SEd Tanous     return to_stream(os, fmt, fds, abbrev, offset_sec);
62391b8b02a4SEd Tanous }
62401b8b02a4SEd Tanous 
62411b8b02a4SEd Tanous template <class CharT, class Traits, class Duration>
62421b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
62431b8b02a4SEd Tanous to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
62441b8b02a4SEd Tanous           const sys_time<Duration>& tp)
62451b8b02a4SEd Tanous {
62461b8b02a4SEd Tanous     using std::chrono::seconds;
62471b8b02a4SEd Tanous     using CT = typename std::common_type<Duration, seconds>::type;
62481b8b02a4SEd Tanous     const std::string abbrev("UTC");
62491b8b02a4SEd Tanous     CONSTDATA seconds offset{0};
62501b8b02a4SEd Tanous     auto sd = std::chrono::time_point_cast<days>(tp);
62511b8b02a4SEd Tanous     fields<CT> fds;
62521b8b02a4SEd Tanous     if (sd <= tp)
62531b8b02a4SEd Tanous         fds = fields<CT>{year_month_day{sd}, hh_mm_ss<CT>{tp-sys_seconds{sd}}};
62541b8b02a4SEd Tanous     else
62551b8b02a4SEd Tanous         fds = fields<CT>{year_month_day{sd - days{1}},
62561b8b02a4SEd Tanous                          hh_mm_ss<CT>{days{1} - (sys_seconds{sd} - tp)}};
62571b8b02a4SEd Tanous     return to_stream(os, fmt, fds, &abbrev, &offset);
62581b8b02a4SEd Tanous }
62591b8b02a4SEd Tanous 
62601b8b02a4SEd Tanous // format
62611b8b02a4SEd Tanous 
62621b8b02a4SEd Tanous template <class CharT, class Streamable>
62631b8b02a4SEd Tanous auto
62641b8b02a4SEd Tanous format(const std::locale& loc, const CharT* fmt, const Streamable& tp)
62651b8b02a4SEd Tanous     -> decltype(to_stream(std::declval<std::basic_ostream<CharT>&>(), fmt, tp),
62661b8b02a4SEd Tanous                 std::basic_string<CharT>{})
62671b8b02a4SEd Tanous {
62681b8b02a4SEd Tanous     std::basic_ostringstream<CharT> os;
62691b8b02a4SEd Tanous     os.exceptions(std::ios::failbit | std::ios::badbit);
62701b8b02a4SEd Tanous     os.imbue(loc);
62711b8b02a4SEd Tanous     to_stream(os, fmt, tp);
62721b8b02a4SEd Tanous     return os.str();
62731b8b02a4SEd Tanous }
62741b8b02a4SEd Tanous 
62751b8b02a4SEd Tanous template <class CharT, class Streamable>
62761b8b02a4SEd Tanous auto
62771b8b02a4SEd Tanous format(const CharT* fmt, const Streamable& tp)
62781b8b02a4SEd Tanous     -> decltype(to_stream(std::declval<std::basic_ostream<CharT>&>(), fmt, tp),
62791b8b02a4SEd Tanous                 std::basic_string<CharT>{})
62801b8b02a4SEd Tanous {
62811b8b02a4SEd Tanous     std::basic_ostringstream<CharT> os;
62821b8b02a4SEd Tanous     os.exceptions(std::ios::failbit | std::ios::badbit);
62831b8b02a4SEd Tanous     to_stream(os, fmt, tp);
62841b8b02a4SEd Tanous     return os.str();
62851b8b02a4SEd Tanous }
62861b8b02a4SEd Tanous 
62871b8b02a4SEd Tanous template <class CharT, class Traits, class Alloc, class Streamable>
62881b8b02a4SEd Tanous auto
62891b8b02a4SEd Tanous format(const std::locale& loc, const std::basic_string<CharT, Traits, Alloc>& fmt,
62901b8b02a4SEd Tanous        const Streamable& tp)
62911b8b02a4SEd Tanous     -> decltype(to_stream(std::declval<std::basic_ostream<CharT, Traits>&>(), fmt.c_str(), tp),
62921b8b02a4SEd Tanous                 std::basic_string<CharT, Traits, Alloc>{})
62931b8b02a4SEd Tanous {
62941b8b02a4SEd Tanous     std::basic_ostringstream<CharT, Traits, Alloc> os;
62951b8b02a4SEd Tanous     os.exceptions(std::ios::failbit | std::ios::badbit);
62961b8b02a4SEd Tanous     os.imbue(loc);
62971b8b02a4SEd Tanous     to_stream(os, fmt.c_str(), tp);
62981b8b02a4SEd Tanous     return os.str();
62991b8b02a4SEd Tanous }
63001b8b02a4SEd Tanous 
63011b8b02a4SEd Tanous template <class CharT, class Traits, class Alloc, class Streamable>
63021b8b02a4SEd Tanous auto
63031b8b02a4SEd Tanous format(const std::basic_string<CharT, Traits, Alloc>& fmt, const Streamable& tp)
63041b8b02a4SEd Tanous     -> decltype(to_stream(std::declval<std::basic_ostream<CharT, Traits>&>(), fmt.c_str(), tp),
63051b8b02a4SEd Tanous                 std::basic_string<CharT, Traits, Alloc>{})
63061b8b02a4SEd Tanous {
63071b8b02a4SEd Tanous     std::basic_ostringstream<CharT, Traits, Alloc> os;
63081b8b02a4SEd Tanous     os.exceptions(std::ios::failbit | std::ios::badbit);
63091b8b02a4SEd Tanous     to_stream(os, fmt.c_str(), tp);
63101b8b02a4SEd Tanous     return os.str();
63111b8b02a4SEd Tanous }
63121b8b02a4SEd Tanous 
63131b8b02a4SEd Tanous // parse
63141b8b02a4SEd Tanous 
63151b8b02a4SEd Tanous namespace detail
63161b8b02a4SEd Tanous {
63171b8b02a4SEd Tanous 
63181b8b02a4SEd Tanous template <class CharT, class Traits>
63191b8b02a4SEd Tanous bool
63201b8b02a4SEd Tanous read_char(std::basic_istream<CharT, Traits>& is, CharT fmt, std::ios::iostate& err)
63211b8b02a4SEd Tanous {
63221b8b02a4SEd Tanous     auto ic = is.get();
63231b8b02a4SEd Tanous     if (Traits::eq_int_type(ic, Traits::eof()) ||
63241b8b02a4SEd Tanous        !Traits::eq(Traits::to_char_type(ic), fmt))
63251b8b02a4SEd Tanous     {
63261b8b02a4SEd Tanous         err |= std::ios::failbit;
63271b8b02a4SEd Tanous         is.setstate(std::ios::failbit);
63281b8b02a4SEd Tanous         return false;
63291b8b02a4SEd Tanous     }
63301b8b02a4SEd Tanous     return true;
63311b8b02a4SEd Tanous }
63321b8b02a4SEd Tanous 
63331b8b02a4SEd Tanous template <class CharT, class Traits>
63341b8b02a4SEd Tanous unsigned
63351b8b02a4SEd Tanous read_unsigned(std::basic_istream<CharT, Traits>& is, unsigned m = 1, unsigned M = 10)
63361b8b02a4SEd Tanous {
63371b8b02a4SEd Tanous     unsigned x = 0;
63381b8b02a4SEd Tanous     unsigned count = 0;
63391b8b02a4SEd Tanous     while (true)
63401b8b02a4SEd Tanous     {
63411b8b02a4SEd Tanous         auto ic = is.peek();
63421b8b02a4SEd Tanous         if (Traits::eq_int_type(ic, Traits::eof()))
63431b8b02a4SEd Tanous             break;
63441b8b02a4SEd Tanous         auto c = static_cast<char>(Traits::to_char_type(ic));
63451b8b02a4SEd Tanous         if (!('0' <= c && c <= '9'))
63461b8b02a4SEd Tanous             break;
63471b8b02a4SEd Tanous         (void)is.get();
63481b8b02a4SEd Tanous         ++count;
63491b8b02a4SEd Tanous         x = 10*x + static_cast<unsigned>(c - '0');
63501b8b02a4SEd Tanous         if (count == M)
63511b8b02a4SEd Tanous             break;
63521b8b02a4SEd Tanous     }
63531b8b02a4SEd Tanous     if (count < m)
63541b8b02a4SEd Tanous         is.setstate(std::ios::failbit);
63551b8b02a4SEd Tanous     return x;
63561b8b02a4SEd Tanous }
63571b8b02a4SEd Tanous 
63581b8b02a4SEd Tanous template <class CharT, class Traits>
63591b8b02a4SEd Tanous int
63601b8b02a4SEd Tanous read_signed(std::basic_istream<CharT, Traits>& is, unsigned m = 1, unsigned M = 10)
63611b8b02a4SEd Tanous {
63621b8b02a4SEd Tanous     auto ic = is.peek();
63631b8b02a4SEd Tanous     if (!Traits::eq_int_type(ic, Traits::eof()))
63641b8b02a4SEd Tanous     {
63651b8b02a4SEd Tanous         auto c = static_cast<char>(Traits::to_char_type(ic));
63661b8b02a4SEd Tanous         if (('0' <= c && c <= '9') || c == '-' || c == '+')
63671b8b02a4SEd Tanous         {
63681b8b02a4SEd Tanous             if (c == '-' || c == '+')
63691b8b02a4SEd Tanous                 (void)is.get();
63701b8b02a4SEd Tanous             auto x = static_cast<int>(read_unsigned(is, std::max(m, 1u), M));
63711b8b02a4SEd Tanous             if (!is.fail())
63721b8b02a4SEd Tanous             {
63731b8b02a4SEd Tanous                 if (c == '-')
63741b8b02a4SEd Tanous                     x = -x;
63751b8b02a4SEd Tanous                 return x;
63761b8b02a4SEd Tanous             }
63771b8b02a4SEd Tanous         }
63781b8b02a4SEd Tanous     }
63791b8b02a4SEd Tanous     if (m > 0)
63801b8b02a4SEd Tanous         is.setstate(std::ios::failbit);
63811b8b02a4SEd Tanous     return 0;
63821b8b02a4SEd Tanous }
63831b8b02a4SEd Tanous 
63841b8b02a4SEd Tanous template <class CharT, class Traits>
63851b8b02a4SEd Tanous long double
63861b8b02a4SEd Tanous read_long_double(std::basic_istream<CharT, Traits>& is, unsigned m = 1, unsigned M = 10)
63871b8b02a4SEd Tanous {
63881b8b02a4SEd Tanous     unsigned count = 0;
63891b8b02a4SEd Tanous     unsigned fcount = 0;
63901b8b02a4SEd Tanous     unsigned long long i = 0;
63911b8b02a4SEd Tanous     unsigned long long f = 0;
63921b8b02a4SEd Tanous     bool parsing_fraction = false;
63931b8b02a4SEd Tanous #if ONLY_C_LOCALE
63941b8b02a4SEd Tanous     typename Traits::int_type decimal_point = '.';
63951b8b02a4SEd Tanous #else
63961b8b02a4SEd Tanous     auto decimal_point = Traits::to_int_type(
63971b8b02a4SEd Tanous         std::use_facet<std::numpunct<CharT>>(is.getloc()).decimal_point());
63981b8b02a4SEd Tanous #endif
63991b8b02a4SEd Tanous     while (true)
64001b8b02a4SEd Tanous     {
64011b8b02a4SEd Tanous         auto ic = is.peek();
64021b8b02a4SEd Tanous         if (Traits::eq_int_type(ic, Traits::eof()))
64031b8b02a4SEd Tanous             break;
64041b8b02a4SEd Tanous         if (Traits::eq_int_type(ic, decimal_point))
64051b8b02a4SEd Tanous         {
64061b8b02a4SEd Tanous             decimal_point = Traits::eof();
64071b8b02a4SEd Tanous             parsing_fraction = true;
64081b8b02a4SEd Tanous         }
64091b8b02a4SEd Tanous         else
64101b8b02a4SEd Tanous         {
64111b8b02a4SEd Tanous             auto c = static_cast<char>(Traits::to_char_type(ic));
64121b8b02a4SEd Tanous             if (!('0' <= c && c <= '9'))
64131b8b02a4SEd Tanous                 break;
64141b8b02a4SEd Tanous             if (!parsing_fraction)
64151b8b02a4SEd Tanous             {
64161b8b02a4SEd Tanous                 i = 10*i + static_cast<unsigned>(c - '0');
64171b8b02a4SEd Tanous             }
64181b8b02a4SEd Tanous             else
64191b8b02a4SEd Tanous             {
64201b8b02a4SEd Tanous                 f = 10*f + static_cast<unsigned>(c - '0');
64211b8b02a4SEd Tanous                 ++fcount;
64221b8b02a4SEd Tanous             }
64231b8b02a4SEd Tanous         }
64241b8b02a4SEd Tanous         (void)is.get();
64251b8b02a4SEd Tanous         if (++count == M)
64261b8b02a4SEd Tanous             break;
64271b8b02a4SEd Tanous     }
64281b8b02a4SEd Tanous     if (count < m)
64291b8b02a4SEd Tanous     {
64301b8b02a4SEd Tanous         is.setstate(std::ios::failbit);
64311b8b02a4SEd Tanous         return 0;
64321b8b02a4SEd Tanous     }
64331b8b02a4SEd Tanous     return static_cast<long double>(i) + static_cast<long double>(f)/std::pow(10.L, fcount);
64341b8b02a4SEd Tanous }
64351b8b02a4SEd Tanous 
64361b8b02a4SEd Tanous struct rs
64371b8b02a4SEd Tanous {
64381b8b02a4SEd Tanous     int& i;
64391b8b02a4SEd Tanous     unsigned m;
64401b8b02a4SEd Tanous     unsigned M;
64411b8b02a4SEd Tanous };
64421b8b02a4SEd Tanous 
64431b8b02a4SEd Tanous struct ru
64441b8b02a4SEd Tanous {
64451b8b02a4SEd Tanous     int& i;
64461b8b02a4SEd Tanous     unsigned m;
64471b8b02a4SEd Tanous     unsigned M;
64481b8b02a4SEd Tanous };
64491b8b02a4SEd Tanous 
64501b8b02a4SEd Tanous struct rld
64511b8b02a4SEd Tanous {
64521b8b02a4SEd Tanous     long double& i;
64531b8b02a4SEd Tanous     unsigned m;
64541b8b02a4SEd Tanous     unsigned M;
64551b8b02a4SEd Tanous };
64561b8b02a4SEd Tanous 
64571b8b02a4SEd Tanous template <class CharT, class Traits>
64581b8b02a4SEd Tanous void
64591b8b02a4SEd Tanous read(std::basic_istream<CharT, Traits>&)
64601b8b02a4SEd Tanous {
64611b8b02a4SEd Tanous }
64621b8b02a4SEd Tanous 
64631b8b02a4SEd Tanous template <class CharT, class Traits, class ...Args>
64641b8b02a4SEd Tanous void
64651b8b02a4SEd Tanous read(std::basic_istream<CharT, Traits>& is, CharT a0, Args&& ...args);
64661b8b02a4SEd Tanous 
64671b8b02a4SEd Tanous template <class CharT, class Traits, class ...Args>
64681b8b02a4SEd Tanous void
64691b8b02a4SEd Tanous read(std::basic_istream<CharT, Traits>& is, rs a0, Args&& ...args);
64701b8b02a4SEd Tanous 
64711b8b02a4SEd Tanous template <class CharT, class Traits, class ...Args>
64721b8b02a4SEd Tanous void
64731b8b02a4SEd Tanous read(std::basic_istream<CharT, Traits>& is, ru a0, Args&& ...args);
64741b8b02a4SEd Tanous 
64751b8b02a4SEd Tanous template <class CharT, class Traits, class ...Args>
64761b8b02a4SEd Tanous void
64771b8b02a4SEd Tanous read(std::basic_istream<CharT, Traits>& is, int a0, Args&& ...args);
64781b8b02a4SEd Tanous 
64791b8b02a4SEd Tanous template <class CharT, class Traits, class ...Args>
64801b8b02a4SEd Tanous void
64811b8b02a4SEd Tanous read(std::basic_istream<CharT, Traits>& is, rld a0, Args&& ...args);
64821b8b02a4SEd Tanous 
64831b8b02a4SEd Tanous template <class CharT, class Traits, class ...Args>
64841b8b02a4SEd Tanous void
64851b8b02a4SEd Tanous read(std::basic_istream<CharT, Traits>& is, CharT a0, Args&& ...args)
64861b8b02a4SEd Tanous {
64871b8b02a4SEd Tanous     // No-op if a0 == CharT{}
64881b8b02a4SEd Tanous     if (a0 != CharT{})
64891b8b02a4SEd Tanous     {
64901b8b02a4SEd Tanous         auto ic = is.peek();
64911b8b02a4SEd Tanous         if (Traits::eq_int_type(ic, Traits::eof()))
64921b8b02a4SEd Tanous         {
64931b8b02a4SEd Tanous             is.setstate(std::ios::failbit | std::ios::eofbit);
64941b8b02a4SEd Tanous             return;
64951b8b02a4SEd Tanous         }
64961b8b02a4SEd Tanous         if (!Traits::eq(Traits::to_char_type(ic), a0))
64971b8b02a4SEd Tanous         {
64981b8b02a4SEd Tanous             is.setstate(std::ios::failbit);
64991b8b02a4SEd Tanous             return;
65001b8b02a4SEd Tanous         }
65011b8b02a4SEd Tanous         (void)is.get();
65021b8b02a4SEd Tanous     }
65031b8b02a4SEd Tanous     read(is, std::forward<Args>(args)...);
65041b8b02a4SEd Tanous }
65051b8b02a4SEd Tanous 
65061b8b02a4SEd Tanous template <class CharT, class Traits, class ...Args>
65071b8b02a4SEd Tanous void
65081b8b02a4SEd Tanous read(std::basic_istream<CharT, Traits>& is, rs a0, Args&& ...args)
65091b8b02a4SEd Tanous {
65101b8b02a4SEd Tanous     auto x = read_signed(is, a0.m, a0.M);
65111b8b02a4SEd Tanous     if (is.fail())
65121b8b02a4SEd Tanous         return;
65131b8b02a4SEd Tanous     a0.i = x;
65141b8b02a4SEd Tanous     read(is, std::forward<Args>(args)...);
65151b8b02a4SEd Tanous }
65161b8b02a4SEd Tanous 
65171b8b02a4SEd Tanous template <class CharT, class Traits, class ...Args>
65181b8b02a4SEd Tanous void
65191b8b02a4SEd Tanous read(std::basic_istream<CharT, Traits>& is, ru a0, Args&& ...args)
65201b8b02a4SEd Tanous {
65211b8b02a4SEd Tanous     auto x = read_unsigned(is, a0.m, a0.M);
65221b8b02a4SEd Tanous     if (is.fail())
65231b8b02a4SEd Tanous         return;
65241b8b02a4SEd Tanous     a0.i = static_cast<int>(x);
65251b8b02a4SEd Tanous     read(is, std::forward<Args>(args)...);
65261b8b02a4SEd Tanous }
65271b8b02a4SEd Tanous 
65281b8b02a4SEd Tanous template <class CharT, class Traits, class ...Args>
65291b8b02a4SEd Tanous void
65301b8b02a4SEd Tanous read(std::basic_istream<CharT, Traits>& is, int a0, Args&& ...args)
65311b8b02a4SEd Tanous {
65321b8b02a4SEd Tanous     if (a0 != -1)
65331b8b02a4SEd Tanous     {
65341b8b02a4SEd Tanous         auto u = static_cast<unsigned>(a0);
65351b8b02a4SEd Tanous         CharT buf[std::numeric_limits<unsigned>::digits10+2u] = {};
65361b8b02a4SEd Tanous         auto e = buf;
65371b8b02a4SEd Tanous         do
65381b8b02a4SEd Tanous         {
65391b8b02a4SEd Tanous             *e++ = static_cast<CharT>(CharT(u % 10) + CharT{'0'});
65401b8b02a4SEd Tanous             u /= 10;
65411b8b02a4SEd Tanous         } while (u > 0);
65421b8b02a4SEd Tanous         std::reverse(buf, e);
65431b8b02a4SEd Tanous         for (auto p = buf; p != e && is.rdstate() == std::ios::goodbit; ++p)
65441b8b02a4SEd Tanous             read(is, *p);
65451b8b02a4SEd Tanous     }
65461b8b02a4SEd Tanous     if (is.rdstate() == std::ios::goodbit)
65471b8b02a4SEd Tanous         read(is, std::forward<Args>(args)...);
65481b8b02a4SEd Tanous }
65491b8b02a4SEd Tanous 
65501b8b02a4SEd Tanous template <class CharT, class Traits, class ...Args>
65511b8b02a4SEd Tanous void
65521b8b02a4SEd Tanous read(std::basic_istream<CharT, Traits>& is, rld a0, Args&& ...args)
65531b8b02a4SEd Tanous {
65541b8b02a4SEd Tanous     auto x = read_long_double(is, a0.m, a0.M);
65551b8b02a4SEd Tanous     if (is.fail())
65561b8b02a4SEd Tanous         return;
65571b8b02a4SEd Tanous     a0.i = x;
65581b8b02a4SEd Tanous     read(is, std::forward<Args>(args)...);
65591b8b02a4SEd Tanous }
65601b8b02a4SEd Tanous 
65611b8b02a4SEd Tanous template <class T, class CharT, class Traits>
65621b8b02a4SEd Tanous inline
65631b8b02a4SEd Tanous void
65641b8b02a4SEd Tanous checked_set(T& value, T from, T not_a_value, std::basic_ios<CharT, Traits>& is)
65651b8b02a4SEd Tanous {
65661b8b02a4SEd Tanous     if (!is.fail())
65671b8b02a4SEd Tanous     {
65681b8b02a4SEd Tanous         if (value == not_a_value)
65691b8b02a4SEd Tanous             value = std::move(from);
65701b8b02a4SEd Tanous         else if (value != from)
65711b8b02a4SEd Tanous             is.setstate(std::ios::failbit);
65721b8b02a4SEd Tanous     }
65731b8b02a4SEd Tanous }
65741b8b02a4SEd Tanous 
65751b8b02a4SEd Tanous }  // namespace detail;
65761b8b02a4SEd Tanous 
65771b8b02a4SEd Tanous template <class CharT, class Traits, class Duration, class Alloc = std::allocator<CharT>>
65781b8b02a4SEd Tanous std::basic_istream<CharT, Traits>&
65791b8b02a4SEd Tanous from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
65801b8b02a4SEd Tanous             fields<Duration>& fds, std::basic_string<CharT, Traits, Alloc>* abbrev,
65811b8b02a4SEd Tanous             std::chrono::minutes* offset)
65821b8b02a4SEd Tanous {
65831b8b02a4SEd Tanous     using std::numeric_limits;
65841b8b02a4SEd Tanous     using std::ios;
65851b8b02a4SEd Tanous     using std::chrono::duration;
65861b8b02a4SEd Tanous     using std::chrono::duration_cast;
65871b8b02a4SEd Tanous     using std::chrono::seconds;
65881b8b02a4SEd Tanous     using std::chrono::minutes;
65891b8b02a4SEd Tanous     using std::chrono::hours;
65901b8b02a4SEd Tanous     using detail::round_i;
65911b8b02a4SEd Tanous     typename std::basic_istream<CharT, Traits>::sentry ok{is, true};
65921b8b02a4SEd Tanous     if (ok)
65931b8b02a4SEd Tanous     {
65941b8b02a4SEd Tanous         date::detail::save_istream<CharT, Traits> ss(is);
65951b8b02a4SEd Tanous         is.fill(' ');
65961b8b02a4SEd Tanous         is.flags(std::ios::skipws | std::ios::dec);
65971b8b02a4SEd Tanous         is.width(0);
65981b8b02a4SEd Tanous #if !ONLY_C_LOCALE
65991b8b02a4SEd Tanous         auto& f = std::use_facet<std::time_get<CharT>>(is.getloc());
66001b8b02a4SEd Tanous         std::tm tm{};
66011b8b02a4SEd Tanous #endif
66021b8b02a4SEd Tanous         const CharT* command = nullptr;
66031b8b02a4SEd Tanous         auto modified = CharT{};
66041b8b02a4SEd Tanous         auto width = -1;
66051b8b02a4SEd Tanous 
66061b8b02a4SEd Tanous         CONSTDATA int not_a_year = numeric_limits<short>::min();
66071b8b02a4SEd Tanous         CONSTDATA int not_a_2digit_year = 100;
66081b8b02a4SEd Tanous         CONSTDATA int not_a_century = not_a_year / 100;
66091b8b02a4SEd Tanous         CONSTDATA int not_a_month = 0;
66101b8b02a4SEd Tanous         CONSTDATA int not_a_day = 0;
66111b8b02a4SEd Tanous         CONSTDATA int not_a_hour = numeric_limits<int>::min();
66121b8b02a4SEd Tanous         CONSTDATA int not_a_hour_12_value = 0;
66131b8b02a4SEd Tanous         CONSTDATA int not_a_minute = not_a_hour;
66141b8b02a4SEd Tanous         CONSTDATA Duration not_a_second = Duration::min();
66151b8b02a4SEd Tanous         CONSTDATA int not_a_doy = -1;
66161b8b02a4SEd Tanous         CONSTDATA int not_a_weekday = 8;
66171b8b02a4SEd Tanous         CONSTDATA int not_a_week_num = 100;
66181b8b02a4SEd Tanous         CONSTDATA int not_a_ampm = -1;
66191b8b02a4SEd Tanous         CONSTDATA minutes not_a_offset = minutes::min();
66201b8b02a4SEd Tanous 
66211b8b02a4SEd Tanous         int Y = not_a_year;             // c, F, Y                   *
66221b8b02a4SEd Tanous         int y = not_a_2digit_year;      // D, x, y                   *
66231b8b02a4SEd Tanous         int g = not_a_2digit_year;      // g                         *
66241b8b02a4SEd Tanous         int G = not_a_year;             // G                         *
66251b8b02a4SEd Tanous         int C = not_a_century;          // C                         *
66261b8b02a4SEd Tanous         int m = not_a_month;            // b, B, h, m, c, D, F, x    *
66271b8b02a4SEd Tanous         int d = not_a_day;              // c, d, D, e, F, x          *
66281b8b02a4SEd Tanous         int j = not_a_doy;              // j                         *
66291b8b02a4SEd Tanous         int wd = not_a_weekday;         // a, A, u, w                *
66301b8b02a4SEd Tanous         int H = not_a_hour;             // c, H, R, T, X             *
66311b8b02a4SEd Tanous         int I = not_a_hour_12_value;    // I, r                      *
66321b8b02a4SEd Tanous         int p = not_a_ampm;             // p, r                      *
66331b8b02a4SEd Tanous         int M = not_a_minute;           // c, M, r, R, T, X          *
66341b8b02a4SEd Tanous         Duration s = not_a_second;      // c, r, S, T, X             *
66351b8b02a4SEd Tanous         int U = not_a_week_num;         // U                         *
66361b8b02a4SEd Tanous         int V = not_a_week_num;         // V                         *
66371b8b02a4SEd Tanous         int W = not_a_week_num;         // W                         *
66381b8b02a4SEd Tanous         std::basic_string<CharT, Traits, Alloc> temp_abbrev;  // Z   *
66391b8b02a4SEd Tanous         minutes temp_offset = not_a_offset;  // z                    *
66401b8b02a4SEd Tanous 
66411b8b02a4SEd Tanous         using detail::read;
66421b8b02a4SEd Tanous         using detail::rs;
66431b8b02a4SEd Tanous         using detail::ru;
66441b8b02a4SEd Tanous         using detail::rld;
66451b8b02a4SEd Tanous         using detail::checked_set;
66461b8b02a4SEd Tanous         for (; *fmt != CharT{} && !is.fail(); ++fmt)
66471b8b02a4SEd Tanous         {
66481b8b02a4SEd Tanous             switch (*fmt)
66491b8b02a4SEd Tanous             {
66501b8b02a4SEd Tanous             case 'a':
66511b8b02a4SEd Tanous             case 'A':
66521b8b02a4SEd Tanous             case 'u':
66531b8b02a4SEd Tanous             case 'w':  // wd:  a, A, u, w
66541b8b02a4SEd Tanous                 if (command)
66551b8b02a4SEd Tanous                 {
66561b8b02a4SEd Tanous                     int trial_wd = not_a_weekday;
66571b8b02a4SEd Tanous                     if (*fmt == 'a' || *fmt == 'A')
66581b8b02a4SEd Tanous                     {
66591b8b02a4SEd Tanous                         if (modified == CharT{})
66601b8b02a4SEd Tanous                         {
66611b8b02a4SEd Tanous #if !ONLY_C_LOCALE
66621b8b02a4SEd Tanous                             ios::iostate err = ios::goodbit;
66631b8b02a4SEd Tanous                             f.get(is, nullptr, is, err, &tm, command, fmt+1);
66641b8b02a4SEd Tanous                             is.setstate(err);
66651b8b02a4SEd Tanous                             if (!is.fail())
66661b8b02a4SEd Tanous                                 trial_wd = tm.tm_wday;
66671b8b02a4SEd Tanous #else
66681b8b02a4SEd Tanous                             auto nm = detail::weekday_names();
66691b8b02a4SEd Tanous                             auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
66701b8b02a4SEd Tanous                             if (!is.fail())
66711b8b02a4SEd Tanous                                 trial_wd = i % 7;
66721b8b02a4SEd Tanous #endif
66731b8b02a4SEd Tanous                         }
66741b8b02a4SEd Tanous                         else
66751b8b02a4SEd Tanous                             read(is, CharT{'%'}, width, modified, *fmt);
66761b8b02a4SEd Tanous                     }
66771b8b02a4SEd Tanous                     else  // *fmt == 'u' || *fmt == 'w'
66781b8b02a4SEd Tanous                     {
66791b8b02a4SEd Tanous #if !ONLY_C_LOCALE
66801b8b02a4SEd Tanous                         if (modified == CharT{})
66811b8b02a4SEd Tanous #else
66821b8b02a4SEd Tanous                         if (modified != CharT{'E'})
66831b8b02a4SEd Tanous #endif
66841b8b02a4SEd Tanous                         {
66851b8b02a4SEd Tanous                             read(is, ru{trial_wd, 1, width == -1 ?
66861b8b02a4SEd Tanous                                                       1u : static_cast<unsigned>(width)});
66871b8b02a4SEd Tanous                             if (!is.fail())
66881b8b02a4SEd Tanous                             {
66891b8b02a4SEd Tanous                                 if (*fmt == 'u')
66901b8b02a4SEd Tanous                                 {
66911b8b02a4SEd Tanous                                     if (!(1 <= trial_wd && trial_wd <= 7))
66921b8b02a4SEd Tanous                                     {
66931b8b02a4SEd Tanous                                         trial_wd = not_a_weekday;
66941b8b02a4SEd Tanous                                         is.setstate(ios::failbit);
66951b8b02a4SEd Tanous                                     }
66961b8b02a4SEd Tanous                                     else if (trial_wd == 7)
66971b8b02a4SEd Tanous                                         trial_wd = 0;
66981b8b02a4SEd Tanous                                 }
66991b8b02a4SEd Tanous                                 else  // *fmt == 'w'
67001b8b02a4SEd Tanous                                 {
67011b8b02a4SEd Tanous                                     if (!(0 <= trial_wd && trial_wd <= 6))
67021b8b02a4SEd Tanous                                     {
67031b8b02a4SEd Tanous                                         trial_wd = not_a_weekday;
67041b8b02a4SEd Tanous                                         is.setstate(ios::failbit);
67051b8b02a4SEd Tanous                                     }
67061b8b02a4SEd Tanous                                 }
67071b8b02a4SEd Tanous                             }
67081b8b02a4SEd Tanous                         }
67091b8b02a4SEd Tanous #if !ONLY_C_LOCALE
67101b8b02a4SEd Tanous                         else if (modified == CharT{'O'})
67111b8b02a4SEd Tanous                         {
67121b8b02a4SEd Tanous                             ios::iostate err = ios::goodbit;
67131b8b02a4SEd Tanous                             f.get(is, nullptr, is, err, &tm, command, fmt+1);
67141b8b02a4SEd Tanous                             is.setstate(err);
67151b8b02a4SEd Tanous                             if (!is.fail())
67161b8b02a4SEd Tanous                                 trial_wd = tm.tm_wday;
67171b8b02a4SEd Tanous                         }
67181b8b02a4SEd Tanous #endif
67191b8b02a4SEd Tanous                         else
67201b8b02a4SEd Tanous                             read(is, CharT{'%'}, width, modified, *fmt);
67211b8b02a4SEd Tanous                     }
67221b8b02a4SEd Tanous                     if (trial_wd != not_a_weekday)
67231b8b02a4SEd Tanous                         checked_set(wd, trial_wd, not_a_weekday, is);
67241b8b02a4SEd Tanous                 }
67251b8b02a4SEd Tanous                 else  // !command
67261b8b02a4SEd Tanous                     read(is, *fmt);
67271b8b02a4SEd Tanous                 command = nullptr;
67281b8b02a4SEd Tanous                 width = -1;
67291b8b02a4SEd Tanous                 modified = CharT{};
67301b8b02a4SEd Tanous                 break;
67311b8b02a4SEd Tanous             case 'b':
67321b8b02a4SEd Tanous             case 'B':
67331b8b02a4SEd Tanous             case 'h':
67341b8b02a4SEd Tanous                 if (command)
67351b8b02a4SEd Tanous                 {
67361b8b02a4SEd Tanous                     if (modified == CharT{})
67371b8b02a4SEd Tanous                     {
67381b8b02a4SEd Tanous                         int ttm = not_a_month;
67391b8b02a4SEd Tanous #if !ONLY_C_LOCALE
67401b8b02a4SEd Tanous                         ios::iostate err = ios::goodbit;
67411b8b02a4SEd Tanous                         f.get(is, nullptr, is, err, &tm, command, fmt+1);
67421b8b02a4SEd Tanous                         if ((err & ios::failbit) == 0)
67431b8b02a4SEd Tanous                             ttm = tm.tm_mon + 1;
67441b8b02a4SEd Tanous                         is.setstate(err);
67451b8b02a4SEd Tanous #else
67461b8b02a4SEd Tanous                         auto nm = detail::month_names();
67471b8b02a4SEd Tanous                         auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
67481b8b02a4SEd Tanous                         if (!is.fail())
67491b8b02a4SEd Tanous                             ttm = i % 12 + 1;
67501b8b02a4SEd Tanous #endif
67511b8b02a4SEd Tanous                         checked_set(m, ttm, not_a_month, is);
67521b8b02a4SEd Tanous                     }
67531b8b02a4SEd Tanous                     else
67541b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
67551b8b02a4SEd Tanous                     command = nullptr;
67561b8b02a4SEd Tanous                     width = -1;
67571b8b02a4SEd Tanous                     modified = CharT{};
67581b8b02a4SEd Tanous                 }
67591b8b02a4SEd Tanous                 else
67601b8b02a4SEd Tanous                     read(is, *fmt);
67611b8b02a4SEd Tanous                 break;
67621b8b02a4SEd Tanous             case 'c':
67631b8b02a4SEd Tanous                 if (command)
67641b8b02a4SEd Tanous                 {
67651b8b02a4SEd Tanous                     if (modified != CharT{'O'})
67661b8b02a4SEd Tanous                     {
67671b8b02a4SEd Tanous #if !ONLY_C_LOCALE
67681b8b02a4SEd Tanous                         ios::iostate err = ios::goodbit;
67691b8b02a4SEd Tanous                         f.get(is, nullptr, is, err, &tm, command, fmt+1);
67701b8b02a4SEd Tanous                         if ((err & ios::failbit) == 0)
67711b8b02a4SEd Tanous                         {
67721b8b02a4SEd Tanous                             checked_set(Y, tm.tm_year + 1900, not_a_year, is);
67731b8b02a4SEd Tanous                             checked_set(m, tm.tm_mon + 1, not_a_month, is);
67741b8b02a4SEd Tanous                             checked_set(d, tm.tm_mday, not_a_day, is);
67751b8b02a4SEd Tanous                             checked_set(H, tm.tm_hour, not_a_hour, is);
67761b8b02a4SEd Tanous                             checked_set(M, tm.tm_min, not_a_minute, is);
67771b8b02a4SEd Tanous                             checked_set(s, duration_cast<Duration>(seconds{tm.tm_sec}),
67781b8b02a4SEd Tanous                                         not_a_second, is);
67791b8b02a4SEd Tanous                         }
67801b8b02a4SEd Tanous                         is.setstate(err);
67811b8b02a4SEd Tanous #else
67821b8b02a4SEd Tanous                         // "%a %b %e %T %Y"
67831b8b02a4SEd Tanous                         auto nm = detail::weekday_names();
67841b8b02a4SEd Tanous                         auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
67851b8b02a4SEd Tanous                         checked_set(wd, static_cast<int>(i % 7), not_a_weekday, is);
67861b8b02a4SEd Tanous                         ws(is);
67871b8b02a4SEd Tanous                         nm = detail::month_names();
67881b8b02a4SEd Tanous                         i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
67891b8b02a4SEd Tanous                         checked_set(m, static_cast<int>(i % 12 + 1), not_a_month, is);
67901b8b02a4SEd Tanous                         ws(is);
67911b8b02a4SEd Tanous                         int td = not_a_day;
67921b8b02a4SEd Tanous                         read(is, rs{td, 1, 2});
67931b8b02a4SEd Tanous                         checked_set(d, td, not_a_day, is);
67941b8b02a4SEd Tanous                         ws(is);
67951b8b02a4SEd Tanous                         using dfs = detail::decimal_format_seconds<Duration>;
67961b8b02a4SEd Tanous                         CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
67971b8b02a4SEd Tanous                         int tH;
67981b8b02a4SEd Tanous                         int tM;
67991b8b02a4SEd Tanous                         long double S{};
68001b8b02a4SEd Tanous                         read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2},
68011b8b02a4SEd Tanous                                                CharT{':'}, rld{S, 1, w});
68021b8b02a4SEd Tanous                         checked_set(H, tH, not_a_hour, is);
68031b8b02a4SEd Tanous                         checked_set(M, tM, not_a_minute, is);
68041b8b02a4SEd Tanous                         checked_set(s, round_i<Duration>(duration<long double>{S}),
68051b8b02a4SEd Tanous                                     not_a_second, is);
68061b8b02a4SEd Tanous                         ws(is);
68071b8b02a4SEd Tanous                         int tY = not_a_year;
68081b8b02a4SEd Tanous                         read(is, rs{tY, 1, 4u});
68091b8b02a4SEd Tanous                         checked_set(Y, tY, not_a_year, is);
68101b8b02a4SEd Tanous #endif
68111b8b02a4SEd Tanous                     }
68121b8b02a4SEd Tanous                     else
68131b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
68141b8b02a4SEd Tanous                     command = nullptr;
68151b8b02a4SEd Tanous                     width = -1;
68161b8b02a4SEd Tanous                     modified = CharT{};
68171b8b02a4SEd Tanous                 }
68181b8b02a4SEd Tanous                 else
68191b8b02a4SEd Tanous                     read(is, *fmt);
68201b8b02a4SEd Tanous                 break;
68211b8b02a4SEd Tanous             case 'x':
68221b8b02a4SEd Tanous                 if (command)
68231b8b02a4SEd Tanous                 {
68241b8b02a4SEd Tanous                     if (modified != CharT{'O'})
68251b8b02a4SEd Tanous                     {
68261b8b02a4SEd Tanous #if !ONLY_C_LOCALE
68271b8b02a4SEd Tanous                         ios::iostate err = ios::goodbit;
68281b8b02a4SEd Tanous                         f.get(is, nullptr, is, err, &tm, command, fmt+1);
68291b8b02a4SEd Tanous                         if ((err & ios::failbit) == 0)
68301b8b02a4SEd Tanous                         {
68311b8b02a4SEd Tanous                             checked_set(Y, tm.tm_year + 1900, not_a_year, is);
68321b8b02a4SEd Tanous                             checked_set(m, tm.tm_mon + 1, not_a_month, is);
68331b8b02a4SEd Tanous                             checked_set(d, tm.tm_mday, not_a_day, is);
68341b8b02a4SEd Tanous                         }
68351b8b02a4SEd Tanous                         is.setstate(err);
68361b8b02a4SEd Tanous #else
68371b8b02a4SEd Tanous                         // "%m/%d/%y"
68381b8b02a4SEd Tanous                         int ty = not_a_2digit_year;
68391b8b02a4SEd Tanous                         int tm = not_a_month;
68401b8b02a4SEd Tanous                         int td = not_a_day;
68411b8b02a4SEd Tanous                         read(is, ru{tm, 1, 2}, CharT{'/'}, ru{td, 1, 2}, CharT{'/'},
68421b8b02a4SEd Tanous                                  rs{ty, 1, 2});
68431b8b02a4SEd Tanous                         checked_set(y, ty, not_a_2digit_year, is);
68441b8b02a4SEd Tanous                         checked_set(m, tm, not_a_month, is);
68451b8b02a4SEd Tanous                         checked_set(d, td, not_a_day, is);
68461b8b02a4SEd Tanous #endif
68471b8b02a4SEd Tanous                     }
68481b8b02a4SEd Tanous                     else
68491b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
68501b8b02a4SEd Tanous                     command = nullptr;
68511b8b02a4SEd Tanous                     width = -1;
68521b8b02a4SEd Tanous                     modified = CharT{};
68531b8b02a4SEd Tanous                 }
68541b8b02a4SEd Tanous                 else
68551b8b02a4SEd Tanous                     read(is, *fmt);
68561b8b02a4SEd Tanous                 break;
68571b8b02a4SEd Tanous             case 'X':
68581b8b02a4SEd Tanous                 if (command)
68591b8b02a4SEd Tanous                 {
68601b8b02a4SEd Tanous                     if (modified != CharT{'O'})
68611b8b02a4SEd Tanous                     {
68621b8b02a4SEd Tanous #if !ONLY_C_LOCALE
68631b8b02a4SEd Tanous                         ios::iostate err = ios::goodbit;
68641b8b02a4SEd Tanous                         f.get(is, nullptr, is, err, &tm, command, fmt+1);
68651b8b02a4SEd Tanous                         if ((err & ios::failbit) == 0)
68661b8b02a4SEd Tanous                         {
68671b8b02a4SEd Tanous                             checked_set(H, tm.tm_hour, not_a_hour, is);
68681b8b02a4SEd Tanous                             checked_set(M, tm.tm_min, not_a_minute, is);
68691b8b02a4SEd Tanous                             checked_set(s, duration_cast<Duration>(seconds{tm.tm_sec}),
68701b8b02a4SEd Tanous                                         not_a_second, is);
68711b8b02a4SEd Tanous                         }
68721b8b02a4SEd Tanous                         is.setstate(err);
68731b8b02a4SEd Tanous #else
68741b8b02a4SEd Tanous                         // "%T"
68751b8b02a4SEd Tanous                         using dfs = detail::decimal_format_seconds<Duration>;
68761b8b02a4SEd Tanous                         CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
68771b8b02a4SEd Tanous                         int tH = not_a_hour;
68781b8b02a4SEd Tanous                         int tM = not_a_minute;
68791b8b02a4SEd Tanous                         long double S{};
68801b8b02a4SEd Tanous                         read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2},
68811b8b02a4SEd Tanous                                                CharT{':'}, rld{S, 1, w});
68821b8b02a4SEd Tanous                         checked_set(H, tH, not_a_hour, is);
68831b8b02a4SEd Tanous                         checked_set(M, tM, not_a_minute, is);
68841b8b02a4SEd Tanous                         checked_set(s, round_i<Duration>(duration<long double>{S}),
68851b8b02a4SEd Tanous                                     not_a_second, is);
68861b8b02a4SEd Tanous #endif
68871b8b02a4SEd Tanous                     }
68881b8b02a4SEd Tanous                     else
68891b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
68901b8b02a4SEd Tanous                     command = nullptr;
68911b8b02a4SEd Tanous                     width = -1;
68921b8b02a4SEd Tanous                     modified = CharT{};
68931b8b02a4SEd Tanous                 }
68941b8b02a4SEd Tanous                 else
68951b8b02a4SEd Tanous                     read(is, *fmt);
68961b8b02a4SEd Tanous                 break;
68971b8b02a4SEd Tanous             case 'C':
68981b8b02a4SEd Tanous                 if (command)
68991b8b02a4SEd Tanous                 {
69001b8b02a4SEd Tanous                     int tC = not_a_century;
69011b8b02a4SEd Tanous #if !ONLY_C_LOCALE
69021b8b02a4SEd Tanous                     if (modified == CharT{})
69031b8b02a4SEd Tanous                     {
69041b8b02a4SEd Tanous #endif
69051b8b02a4SEd Tanous                         read(is, rs{tC, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
69061b8b02a4SEd Tanous #if !ONLY_C_LOCALE
69071b8b02a4SEd Tanous                     }
69081b8b02a4SEd Tanous                     else
69091b8b02a4SEd Tanous                     {
69101b8b02a4SEd Tanous                         ios::iostate err = ios::goodbit;
69111b8b02a4SEd Tanous                         f.get(is, nullptr, is, err, &tm, command, fmt+1);
69121b8b02a4SEd Tanous                         if ((err & ios::failbit) == 0)
69131b8b02a4SEd Tanous                         {
69141b8b02a4SEd Tanous                             auto tY = tm.tm_year + 1900;
69151b8b02a4SEd Tanous                             tC = (tY >= 0 ? tY : tY-99) / 100;
69161b8b02a4SEd Tanous                         }
69171b8b02a4SEd Tanous                         is.setstate(err);
69181b8b02a4SEd Tanous                     }
69191b8b02a4SEd Tanous #endif
69201b8b02a4SEd Tanous                     checked_set(C, tC, not_a_century, is);
69211b8b02a4SEd Tanous                     command = nullptr;
69221b8b02a4SEd Tanous                     width = -1;
69231b8b02a4SEd Tanous                     modified = CharT{};
69241b8b02a4SEd Tanous                 }
69251b8b02a4SEd Tanous                 else
69261b8b02a4SEd Tanous                     read(is, *fmt);
69271b8b02a4SEd Tanous                 break;
69281b8b02a4SEd Tanous             case 'D':
69291b8b02a4SEd Tanous                 if (command)
69301b8b02a4SEd Tanous                 {
69311b8b02a4SEd Tanous                     if (modified == CharT{})
69321b8b02a4SEd Tanous                     {
69331b8b02a4SEd Tanous                         int tn = not_a_month;
69341b8b02a4SEd Tanous                         int td = not_a_day;
69351b8b02a4SEd Tanous                         int ty = not_a_2digit_year;
69361b8b02a4SEd Tanous                         read(is, ru{tn, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'},
69371b8b02a4SEd Tanous                                  ru{td, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'},
69381b8b02a4SEd Tanous                                  rs{ty, 1, 2});
69391b8b02a4SEd Tanous                         checked_set(y, ty, not_a_2digit_year, is);
69401b8b02a4SEd Tanous                         checked_set(m, tn, not_a_month, is);
69411b8b02a4SEd Tanous                         checked_set(d, td, not_a_day, is);
69421b8b02a4SEd Tanous                     }
69431b8b02a4SEd Tanous                     else
69441b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
69451b8b02a4SEd Tanous                     command = nullptr;
69461b8b02a4SEd Tanous                     width = -1;
69471b8b02a4SEd Tanous                     modified = CharT{};
69481b8b02a4SEd Tanous                 }
69491b8b02a4SEd Tanous                 else
69501b8b02a4SEd Tanous                     read(is, *fmt);
69511b8b02a4SEd Tanous                 break;
69521b8b02a4SEd Tanous             case 'F':
69531b8b02a4SEd Tanous                 if (command)
69541b8b02a4SEd Tanous                 {
69551b8b02a4SEd Tanous                     if (modified == CharT{})
69561b8b02a4SEd Tanous                     {
69571b8b02a4SEd Tanous                         int tY = not_a_year;
69581b8b02a4SEd Tanous                         int tn = not_a_month;
69591b8b02a4SEd Tanous                         int td = not_a_day;
69601b8b02a4SEd Tanous                         read(is, rs{tY, 1, width == -1 ? 4u : static_cast<unsigned>(width)},
69611b8b02a4SEd Tanous                                  CharT{'-'}, ru{tn, 1, 2}, CharT{'-'}, ru{td, 1, 2});
69621b8b02a4SEd Tanous                         checked_set(Y, tY, not_a_year, is);
69631b8b02a4SEd Tanous                         checked_set(m, tn, not_a_month, is);
69641b8b02a4SEd Tanous                         checked_set(d, td, not_a_day, is);
69651b8b02a4SEd Tanous                     }
69661b8b02a4SEd Tanous                     else
69671b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
69681b8b02a4SEd Tanous                     command = nullptr;
69691b8b02a4SEd Tanous                     width = -1;
69701b8b02a4SEd Tanous                     modified = CharT{};
69711b8b02a4SEd Tanous                 }
69721b8b02a4SEd Tanous                 else
69731b8b02a4SEd Tanous                     read(is, *fmt);
69741b8b02a4SEd Tanous                 break;
69751b8b02a4SEd Tanous             case 'd':
69761b8b02a4SEd Tanous             case 'e':
69771b8b02a4SEd Tanous                 if (command)
69781b8b02a4SEd Tanous                 {
69791b8b02a4SEd Tanous #if !ONLY_C_LOCALE
69801b8b02a4SEd Tanous                     if (modified == CharT{})
69811b8b02a4SEd Tanous #else
69821b8b02a4SEd Tanous                     if (modified != CharT{'E'})
69831b8b02a4SEd Tanous #endif
69841b8b02a4SEd Tanous                     {
69851b8b02a4SEd Tanous                         int td = not_a_day;
69861b8b02a4SEd Tanous                         read(is, rs{td, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
69871b8b02a4SEd Tanous                         checked_set(d, td, not_a_day, is);
69881b8b02a4SEd Tanous                     }
69891b8b02a4SEd Tanous #if !ONLY_C_LOCALE
69901b8b02a4SEd Tanous                     else if (modified == CharT{'O'})
69911b8b02a4SEd Tanous                     {
69921b8b02a4SEd Tanous                         ios::iostate err = ios::goodbit;
69931b8b02a4SEd Tanous                         f.get(is, nullptr, is, err, &tm, command, fmt+1);
69941b8b02a4SEd Tanous                         command = nullptr;
69951b8b02a4SEd Tanous                         width = -1;
69961b8b02a4SEd Tanous                         modified = CharT{};
69971b8b02a4SEd Tanous                         if ((err & ios::failbit) == 0)
69981b8b02a4SEd Tanous                             checked_set(d, tm.tm_mday, not_a_day, is);
69991b8b02a4SEd Tanous                         is.setstate(err);
70001b8b02a4SEd Tanous                     }
70011b8b02a4SEd Tanous #endif
70021b8b02a4SEd Tanous                     else
70031b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
70041b8b02a4SEd Tanous                     command = nullptr;
70051b8b02a4SEd Tanous                     width = -1;
70061b8b02a4SEd Tanous                     modified = CharT{};
70071b8b02a4SEd Tanous                 }
70081b8b02a4SEd Tanous                 else
70091b8b02a4SEd Tanous                     read(is, *fmt);
70101b8b02a4SEd Tanous                 break;
70111b8b02a4SEd Tanous             case 'H':
70121b8b02a4SEd Tanous                 if (command)
70131b8b02a4SEd Tanous                 {
70141b8b02a4SEd Tanous #if !ONLY_C_LOCALE
70151b8b02a4SEd Tanous                     if (modified == CharT{})
70161b8b02a4SEd Tanous #else
70171b8b02a4SEd Tanous                     if (modified != CharT{'E'})
70181b8b02a4SEd Tanous #endif
70191b8b02a4SEd Tanous                     {
70201b8b02a4SEd Tanous                         int tH = not_a_hour;
70211b8b02a4SEd Tanous                         read(is, ru{tH, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
70221b8b02a4SEd Tanous                         checked_set(H, tH, not_a_hour, is);
70231b8b02a4SEd Tanous                     }
70241b8b02a4SEd Tanous #if !ONLY_C_LOCALE
70251b8b02a4SEd Tanous                     else if (modified == CharT{'O'})
70261b8b02a4SEd Tanous                     {
70271b8b02a4SEd Tanous                         ios::iostate err = ios::goodbit;
70281b8b02a4SEd Tanous                         f.get(is, nullptr, is, err, &tm, command, fmt+1);
70291b8b02a4SEd Tanous                         if ((err & ios::failbit) == 0)
70301b8b02a4SEd Tanous                             checked_set(H, tm.tm_hour, not_a_hour, is);
70311b8b02a4SEd Tanous                         is.setstate(err);
70321b8b02a4SEd Tanous                     }
70331b8b02a4SEd Tanous #endif
70341b8b02a4SEd Tanous                     else
70351b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
70361b8b02a4SEd Tanous                     command = nullptr;
70371b8b02a4SEd Tanous                     width = -1;
70381b8b02a4SEd Tanous                     modified = CharT{};
70391b8b02a4SEd Tanous                 }
70401b8b02a4SEd Tanous                 else
70411b8b02a4SEd Tanous                     read(is, *fmt);
70421b8b02a4SEd Tanous                 break;
70431b8b02a4SEd Tanous             case 'I':
70441b8b02a4SEd Tanous                 if (command)
70451b8b02a4SEd Tanous                 {
70461b8b02a4SEd Tanous                     if (modified == CharT{})
70471b8b02a4SEd Tanous                     {
70481b8b02a4SEd Tanous                         int tI = not_a_hour_12_value;
70491b8b02a4SEd Tanous                         // reads in an hour into I, but most be in [1, 12]
70501b8b02a4SEd Tanous                         read(is, rs{tI, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
70511b8b02a4SEd Tanous                         if (!(1 <= tI && tI <= 12))
70521b8b02a4SEd Tanous                             is.setstate(ios::failbit);
70531b8b02a4SEd Tanous                         checked_set(I, tI, not_a_hour_12_value, is);
70541b8b02a4SEd Tanous                     }
70551b8b02a4SEd Tanous                     else
70561b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
70571b8b02a4SEd Tanous                     command = nullptr;
70581b8b02a4SEd Tanous                     width = -1;
70591b8b02a4SEd Tanous                     modified = CharT{};
70601b8b02a4SEd Tanous                 }
70611b8b02a4SEd Tanous                 else
70621b8b02a4SEd Tanous                     read(is, *fmt);
70631b8b02a4SEd Tanous                break;
70641b8b02a4SEd Tanous             case 'j':
70651b8b02a4SEd Tanous                 if (command)
70661b8b02a4SEd Tanous                 {
70671b8b02a4SEd Tanous                     if (modified == CharT{})
70681b8b02a4SEd Tanous                     {
70691b8b02a4SEd Tanous                         int tj = not_a_doy;
70701b8b02a4SEd Tanous                         read(is, ru{tj, 1, width == -1 ? 3u : static_cast<unsigned>(width)});
70711b8b02a4SEd Tanous                         checked_set(j, tj, not_a_doy, is);
70721b8b02a4SEd Tanous                     }
70731b8b02a4SEd Tanous                     else
70741b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
70751b8b02a4SEd Tanous                     command = nullptr;
70761b8b02a4SEd Tanous                     width = -1;
70771b8b02a4SEd Tanous                     modified = CharT{};
70781b8b02a4SEd Tanous                 }
70791b8b02a4SEd Tanous                 else
70801b8b02a4SEd Tanous                     read(is, *fmt);
70811b8b02a4SEd Tanous                 break;
70821b8b02a4SEd Tanous             case 'M':
70831b8b02a4SEd Tanous                 if (command)
70841b8b02a4SEd Tanous                 {
70851b8b02a4SEd Tanous #if !ONLY_C_LOCALE
70861b8b02a4SEd Tanous                     if (modified == CharT{})
70871b8b02a4SEd Tanous #else
70881b8b02a4SEd Tanous                     if (modified != CharT{'E'})
70891b8b02a4SEd Tanous #endif
70901b8b02a4SEd Tanous                     {
70911b8b02a4SEd Tanous                         int tM = not_a_minute;
70921b8b02a4SEd Tanous                         read(is, ru{tM, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
70931b8b02a4SEd Tanous                         checked_set(M, tM, not_a_minute, is);
70941b8b02a4SEd Tanous                     }
70951b8b02a4SEd Tanous #if !ONLY_C_LOCALE
70961b8b02a4SEd Tanous                     else if (modified == CharT{'O'})
70971b8b02a4SEd Tanous                     {
70981b8b02a4SEd Tanous                         ios::iostate err = ios::goodbit;
70991b8b02a4SEd Tanous                         f.get(is, nullptr, is, err, &tm, command, fmt+1);
71001b8b02a4SEd Tanous                         if ((err & ios::failbit) == 0)
71011b8b02a4SEd Tanous                             checked_set(M, tm.tm_min, not_a_minute, is);
71021b8b02a4SEd Tanous                         is.setstate(err);
71031b8b02a4SEd Tanous                     }
71041b8b02a4SEd Tanous #endif
71051b8b02a4SEd Tanous                     else
71061b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
71071b8b02a4SEd Tanous                     command = nullptr;
71081b8b02a4SEd Tanous                     width = -1;
71091b8b02a4SEd Tanous                     modified = CharT{};
71101b8b02a4SEd Tanous                 }
71111b8b02a4SEd Tanous                 else
71121b8b02a4SEd Tanous                     read(is, *fmt);
71131b8b02a4SEd Tanous                 break;
71141b8b02a4SEd Tanous             case 'm':
71151b8b02a4SEd Tanous                 if (command)
71161b8b02a4SEd Tanous                 {
71171b8b02a4SEd Tanous #if !ONLY_C_LOCALE
71181b8b02a4SEd Tanous                     if (modified == CharT{})
71191b8b02a4SEd Tanous #else
71201b8b02a4SEd Tanous                     if (modified != CharT{'E'})
71211b8b02a4SEd Tanous #endif
71221b8b02a4SEd Tanous                     {
71231b8b02a4SEd Tanous                         int tn = not_a_month;
71241b8b02a4SEd Tanous                         read(is, rs{tn, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
71251b8b02a4SEd Tanous                         checked_set(m, tn, not_a_month, is);
71261b8b02a4SEd Tanous                     }
71271b8b02a4SEd Tanous #if !ONLY_C_LOCALE
71281b8b02a4SEd Tanous                     else if (modified == CharT{'O'})
71291b8b02a4SEd Tanous                     {
71301b8b02a4SEd Tanous                         ios::iostate err = ios::goodbit;
71311b8b02a4SEd Tanous                         f.get(is, nullptr, is, err, &tm, command, fmt+1);
71321b8b02a4SEd Tanous                         if ((err & ios::failbit) == 0)
71331b8b02a4SEd Tanous                             checked_set(m, tm.tm_mon + 1, not_a_month, is);
71341b8b02a4SEd Tanous                         is.setstate(err);
71351b8b02a4SEd Tanous                     }
71361b8b02a4SEd Tanous #endif
71371b8b02a4SEd Tanous                     else
71381b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
71391b8b02a4SEd Tanous                     command = nullptr;
71401b8b02a4SEd Tanous                     width = -1;
71411b8b02a4SEd Tanous                     modified = CharT{};
71421b8b02a4SEd Tanous                 }
71431b8b02a4SEd Tanous                 else
71441b8b02a4SEd Tanous                     read(is, *fmt);
71451b8b02a4SEd Tanous                 break;
71461b8b02a4SEd Tanous             case 'n':
71471b8b02a4SEd Tanous             case 't':
71481b8b02a4SEd Tanous                 if (command)
71491b8b02a4SEd Tanous                 {
71501b8b02a4SEd Tanous                     if (modified == CharT{})
71511b8b02a4SEd Tanous                     {
71521b8b02a4SEd Tanous                         // %n matches a single white space character
71531b8b02a4SEd Tanous                         // %t matches 0 or 1 white space characters
71541b8b02a4SEd Tanous                         auto ic = is.peek();
71551b8b02a4SEd Tanous                         if (Traits::eq_int_type(ic, Traits::eof()))
71561b8b02a4SEd Tanous                         {
71571b8b02a4SEd Tanous                             ios::iostate err = ios::eofbit;
71581b8b02a4SEd Tanous                             if (*fmt == 'n')
71591b8b02a4SEd Tanous                                 err |= ios::failbit;
71601b8b02a4SEd Tanous                             is.setstate(err);
71611b8b02a4SEd Tanous                             break;
71621b8b02a4SEd Tanous                         }
71631b8b02a4SEd Tanous                         if (isspace(ic))
71641b8b02a4SEd Tanous                         {
71651b8b02a4SEd Tanous                             (void)is.get();
71661b8b02a4SEd Tanous                         }
71671b8b02a4SEd Tanous                         else if (*fmt == 'n')
71681b8b02a4SEd Tanous                             is.setstate(ios::failbit);
71691b8b02a4SEd Tanous                     }
71701b8b02a4SEd Tanous                     else
71711b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
71721b8b02a4SEd Tanous                     command = nullptr;
71731b8b02a4SEd Tanous                     width = -1;
71741b8b02a4SEd Tanous                     modified = CharT{};
71751b8b02a4SEd Tanous                 }
71761b8b02a4SEd Tanous                 else
71771b8b02a4SEd Tanous                     read(is, *fmt);
71781b8b02a4SEd Tanous                 break;
71791b8b02a4SEd Tanous             case 'p':
71801b8b02a4SEd Tanous                 if (command)
71811b8b02a4SEd Tanous                 {
71821b8b02a4SEd Tanous                     if (modified == CharT{})
71831b8b02a4SEd Tanous                     {
71841b8b02a4SEd Tanous                         int tp = not_a_ampm;
71851b8b02a4SEd Tanous #if !ONLY_C_LOCALE
71861b8b02a4SEd Tanous                         tm = std::tm{};
71871b8b02a4SEd Tanous                         tm.tm_hour = 1;
71881b8b02a4SEd Tanous                         ios::iostate err = ios::goodbit;
71891b8b02a4SEd Tanous                         f.get(is, nullptr, is, err, &tm, command, fmt+1);
71901b8b02a4SEd Tanous                         is.setstate(err);
71911b8b02a4SEd Tanous                         if (tm.tm_hour == 1)
71921b8b02a4SEd Tanous                             tp = 0;
71931b8b02a4SEd Tanous                         else if (tm.tm_hour == 13)
71941b8b02a4SEd Tanous                             tp = 1;
71951b8b02a4SEd Tanous                         else
71961b8b02a4SEd Tanous                             is.setstate(err);
71971b8b02a4SEd Tanous #else
71981b8b02a4SEd Tanous                         auto nm = detail::ampm_names();
71991b8b02a4SEd Tanous                         auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
72001b8b02a4SEd Tanous                         tp = static_cast<decltype(tp)>(i);
72011b8b02a4SEd Tanous #endif
72021b8b02a4SEd Tanous                         checked_set(p, tp, not_a_ampm, is);
72031b8b02a4SEd Tanous                     }
72041b8b02a4SEd Tanous                     else
72051b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
72061b8b02a4SEd Tanous                     command = nullptr;
72071b8b02a4SEd Tanous                     width = -1;
72081b8b02a4SEd Tanous                     modified = CharT{};
72091b8b02a4SEd Tanous                 }
72101b8b02a4SEd Tanous                 else
72111b8b02a4SEd Tanous                     read(is, *fmt);
72121b8b02a4SEd Tanous 
72131b8b02a4SEd Tanous                break;
72141b8b02a4SEd Tanous             case 'r':
72151b8b02a4SEd Tanous                 if (command)
72161b8b02a4SEd Tanous                 {
72171b8b02a4SEd Tanous                     if (modified == CharT{})
72181b8b02a4SEd Tanous                     {
72191b8b02a4SEd Tanous #if !ONLY_C_LOCALE
72201b8b02a4SEd Tanous                         ios::iostate err = ios::goodbit;
72211b8b02a4SEd Tanous                         f.get(is, nullptr, is, err, &tm, command, fmt+1);
72221b8b02a4SEd Tanous                         if ((err & ios::failbit) == 0)
72231b8b02a4SEd Tanous                         {
72241b8b02a4SEd Tanous                             checked_set(H, tm.tm_hour, not_a_hour, is);
72251b8b02a4SEd Tanous                             checked_set(M, tm.tm_min, not_a_hour, is);
72261b8b02a4SEd Tanous                             checked_set(s, duration_cast<Duration>(seconds{tm.tm_sec}),
72271b8b02a4SEd Tanous                                         not_a_second, is);
72281b8b02a4SEd Tanous                         }
72291b8b02a4SEd Tanous                         is.setstate(err);
72301b8b02a4SEd Tanous #else
72311b8b02a4SEd Tanous                         // "%I:%M:%S %p"
72321b8b02a4SEd Tanous                         using dfs = detail::decimal_format_seconds<Duration>;
72331b8b02a4SEd Tanous                         CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
72341b8b02a4SEd Tanous                         long double S{};
72351b8b02a4SEd Tanous                         int tI = not_a_hour_12_value;
72361b8b02a4SEd Tanous                         int tM = not_a_minute;
72371b8b02a4SEd Tanous                         read(is, ru{tI, 1, 2}, CharT{':'}, ru{tM, 1, 2},
72381b8b02a4SEd Tanous                                                CharT{':'}, rld{S, 1, w});
72391b8b02a4SEd Tanous                         checked_set(I, tI, not_a_hour_12_value, is);
72401b8b02a4SEd Tanous                         checked_set(M, tM, not_a_minute, is);
72411b8b02a4SEd Tanous                         checked_set(s, round_i<Duration>(duration<long double>{S}),
72421b8b02a4SEd Tanous                                     not_a_second, is);
72431b8b02a4SEd Tanous                         ws(is);
72441b8b02a4SEd Tanous                         auto nm = detail::ampm_names();
72451b8b02a4SEd Tanous                         auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
72461b8b02a4SEd Tanous                         checked_set(p, static_cast<int>(i), not_a_ampm, is);
72471b8b02a4SEd Tanous #endif
72481b8b02a4SEd Tanous                     }
72491b8b02a4SEd Tanous                     else
72501b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
72511b8b02a4SEd Tanous                     command = nullptr;
72521b8b02a4SEd Tanous                     width = -1;
72531b8b02a4SEd Tanous                     modified = CharT{};
72541b8b02a4SEd Tanous                 }
72551b8b02a4SEd Tanous                 else
72561b8b02a4SEd Tanous                     read(is, *fmt);
72571b8b02a4SEd Tanous                 break;
72581b8b02a4SEd Tanous             case 'R':
72591b8b02a4SEd Tanous                 if (command)
72601b8b02a4SEd Tanous                 {
72611b8b02a4SEd Tanous                     if (modified == CharT{})
72621b8b02a4SEd Tanous                     {
72631b8b02a4SEd Tanous                         int tH = not_a_hour;
72641b8b02a4SEd Tanous                         int tM = not_a_minute;
72651b8b02a4SEd Tanous                         read(is, ru{tH, 1, 2}, CharT{'\0'}, CharT{':'}, CharT{'\0'},
72661b8b02a4SEd Tanous                                  ru{tM, 1, 2}, CharT{'\0'});
72671b8b02a4SEd Tanous                         checked_set(H, tH, not_a_hour, is);
72681b8b02a4SEd Tanous                         checked_set(M, tM, not_a_minute, is);
72691b8b02a4SEd Tanous                     }
72701b8b02a4SEd Tanous                     else
72711b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
72721b8b02a4SEd Tanous                     command = nullptr;
72731b8b02a4SEd Tanous                     width = -1;
72741b8b02a4SEd Tanous                     modified = CharT{};
72751b8b02a4SEd Tanous                 }
72761b8b02a4SEd Tanous                 else
72771b8b02a4SEd Tanous                     read(is, *fmt);
72781b8b02a4SEd Tanous                 break;
72791b8b02a4SEd Tanous             case 'S':
72801b8b02a4SEd Tanous                 if (command)
72811b8b02a4SEd Tanous                 {
72821b8b02a4SEd Tanous  #if !ONLY_C_LOCALE
72831b8b02a4SEd Tanous                    if (modified == CharT{})
72841b8b02a4SEd Tanous #else
72851b8b02a4SEd Tanous                    if (modified != CharT{'E'})
72861b8b02a4SEd Tanous #endif
72871b8b02a4SEd Tanous                     {
72881b8b02a4SEd Tanous                         using dfs = detail::decimal_format_seconds<Duration>;
72891b8b02a4SEd Tanous                         CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
72901b8b02a4SEd Tanous                         long double S{};
72911b8b02a4SEd Tanous                         read(is, rld{S, 1, width == -1 ? w : static_cast<unsigned>(width)});
72921b8b02a4SEd Tanous                         checked_set(s, round_i<Duration>(duration<long double>{S}),
72931b8b02a4SEd Tanous                                     not_a_second, is);
72941b8b02a4SEd Tanous                     }
72951b8b02a4SEd Tanous #if !ONLY_C_LOCALE
72961b8b02a4SEd Tanous                     else if (modified == CharT{'O'})
72971b8b02a4SEd Tanous                     {
72981b8b02a4SEd Tanous                         ios::iostate err = ios::goodbit;
72991b8b02a4SEd Tanous                         f.get(is, nullptr, is, err, &tm, command, fmt+1);
73001b8b02a4SEd Tanous                         if ((err & ios::failbit) == 0)
73011b8b02a4SEd Tanous                             checked_set(s, duration_cast<Duration>(seconds{tm.tm_sec}),
73021b8b02a4SEd Tanous                                         not_a_second, is);
73031b8b02a4SEd Tanous                         is.setstate(err);
73041b8b02a4SEd Tanous                     }
73051b8b02a4SEd Tanous #endif
73061b8b02a4SEd Tanous                     else
73071b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
73081b8b02a4SEd Tanous                     command = nullptr;
73091b8b02a4SEd Tanous                     width = -1;
73101b8b02a4SEd Tanous                     modified = CharT{};
73111b8b02a4SEd Tanous                 }
73121b8b02a4SEd Tanous                 else
73131b8b02a4SEd Tanous                     read(is, *fmt);
73141b8b02a4SEd Tanous                 break;
73151b8b02a4SEd Tanous             case 'T':
73161b8b02a4SEd Tanous                 if (command)
73171b8b02a4SEd Tanous                 {
73181b8b02a4SEd Tanous                     if (modified == CharT{})
73191b8b02a4SEd Tanous                     {
73201b8b02a4SEd Tanous                         using dfs = detail::decimal_format_seconds<Duration>;
73211b8b02a4SEd Tanous                         CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
73221b8b02a4SEd Tanous                         int tH = not_a_hour;
73231b8b02a4SEd Tanous                         int tM = not_a_minute;
73241b8b02a4SEd Tanous                         long double S{};
73251b8b02a4SEd Tanous                         read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2},
73261b8b02a4SEd Tanous                                                CharT{':'}, rld{S, 1, w});
73271b8b02a4SEd Tanous                         checked_set(H, tH, not_a_hour, is);
73281b8b02a4SEd Tanous                         checked_set(M, tM, not_a_minute, is);
73291b8b02a4SEd Tanous                         checked_set(s, round_i<Duration>(duration<long double>{S}),
73301b8b02a4SEd Tanous                                     not_a_second, is);
73311b8b02a4SEd Tanous                     }
73321b8b02a4SEd Tanous                     else
73331b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
73341b8b02a4SEd Tanous                     command = nullptr;
73351b8b02a4SEd Tanous                     width = -1;
73361b8b02a4SEd Tanous                     modified = CharT{};
73371b8b02a4SEd Tanous                 }
73381b8b02a4SEd Tanous                 else
73391b8b02a4SEd Tanous                     read(is, *fmt);
73401b8b02a4SEd Tanous                 break;
73411b8b02a4SEd Tanous             case 'Y':
73421b8b02a4SEd Tanous                 if (command)
73431b8b02a4SEd Tanous                 {
73441b8b02a4SEd Tanous #if !ONLY_C_LOCALE
73451b8b02a4SEd Tanous                     if (modified == CharT{})
73461b8b02a4SEd Tanous #else
73471b8b02a4SEd Tanous                     if (modified != CharT{'O'})
73481b8b02a4SEd Tanous #endif
73491b8b02a4SEd Tanous                     {
73501b8b02a4SEd Tanous                         int tY = not_a_year;
73511b8b02a4SEd Tanous                         read(is, rs{tY, 1, width == -1 ? 4u : static_cast<unsigned>(width)});
73521b8b02a4SEd Tanous                         checked_set(Y, tY, not_a_year, is);
73531b8b02a4SEd Tanous                     }
73541b8b02a4SEd Tanous #if !ONLY_C_LOCALE
73551b8b02a4SEd Tanous                     else if (modified == CharT{'E'})
73561b8b02a4SEd Tanous                     {
73571b8b02a4SEd Tanous                         ios::iostate err = ios::goodbit;
73581b8b02a4SEd Tanous                         f.get(is, nullptr, is, err, &tm, command, fmt+1);
73591b8b02a4SEd Tanous                         if ((err & ios::failbit) == 0)
73601b8b02a4SEd Tanous                             checked_set(Y, tm.tm_year + 1900, not_a_year, is);
73611b8b02a4SEd Tanous                         is.setstate(err);
73621b8b02a4SEd Tanous                     }
73631b8b02a4SEd Tanous #endif
73641b8b02a4SEd Tanous                     else
73651b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
73661b8b02a4SEd Tanous                     command = nullptr;
73671b8b02a4SEd Tanous                     width = -1;
73681b8b02a4SEd Tanous                     modified = CharT{};
73691b8b02a4SEd Tanous                 }
73701b8b02a4SEd Tanous                 else
73711b8b02a4SEd Tanous                     read(is, *fmt);
73721b8b02a4SEd Tanous                 break;
73731b8b02a4SEd Tanous             case 'y':
73741b8b02a4SEd Tanous                 if (command)
73751b8b02a4SEd Tanous                 {
73761b8b02a4SEd Tanous #if !ONLY_C_LOCALE
73771b8b02a4SEd Tanous                     if (modified == CharT{})
73781b8b02a4SEd Tanous #endif
73791b8b02a4SEd Tanous                     {
73801b8b02a4SEd Tanous                         int ty = not_a_2digit_year;
73811b8b02a4SEd Tanous                         read(is, ru{ty, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
73821b8b02a4SEd Tanous                         checked_set(y, ty, not_a_2digit_year, is);
73831b8b02a4SEd Tanous                     }
73841b8b02a4SEd Tanous #if !ONLY_C_LOCALE
73851b8b02a4SEd Tanous                     else
73861b8b02a4SEd Tanous                     {
73871b8b02a4SEd Tanous                         ios::iostate err = ios::goodbit;
73881b8b02a4SEd Tanous                         f.get(is, nullptr, is, err, &tm, command, fmt+1);
73891b8b02a4SEd Tanous                         if ((err & ios::failbit) == 0)
73901b8b02a4SEd Tanous                             checked_set(Y, tm.tm_year + 1900, not_a_year, is);
73911b8b02a4SEd Tanous                         is.setstate(err);
73921b8b02a4SEd Tanous                     }
73931b8b02a4SEd Tanous #endif
73941b8b02a4SEd Tanous                     command = nullptr;
73951b8b02a4SEd Tanous                     width = -1;
73961b8b02a4SEd Tanous                     modified = CharT{};
73971b8b02a4SEd Tanous                 }
73981b8b02a4SEd Tanous                 else
73991b8b02a4SEd Tanous                     read(is, *fmt);
74001b8b02a4SEd Tanous                 break;
74011b8b02a4SEd Tanous             case 'g':
74021b8b02a4SEd Tanous                 if (command)
74031b8b02a4SEd Tanous                 {
74041b8b02a4SEd Tanous                     if (modified == CharT{})
74051b8b02a4SEd Tanous                     {
74061b8b02a4SEd Tanous                         int tg = not_a_2digit_year;
74071b8b02a4SEd Tanous                         read(is, ru{tg, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
74081b8b02a4SEd Tanous                         checked_set(g, tg, not_a_2digit_year, is);
74091b8b02a4SEd Tanous                     }
74101b8b02a4SEd Tanous                     else
74111b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
74121b8b02a4SEd Tanous                     command = nullptr;
74131b8b02a4SEd Tanous                     width = -1;
74141b8b02a4SEd Tanous                     modified = CharT{};
74151b8b02a4SEd Tanous                 }
74161b8b02a4SEd Tanous                 else
74171b8b02a4SEd Tanous                     read(is, *fmt);
74181b8b02a4SEd Tanous                 break;
74191b8b02a4SEd Tanous             case 'G':
74201b8b02a4SEd Tanous                 if (command)
74211b8b02a4SEd Tanous                 {
74221b8b02a4SEd Tanous                     if (modified == CharT{})
74231b8b02a4SEd Tanous                     {
74241b8b02a4SEd Tanous                         int tG = not_a_year;
74251b8b02a4SEd Tanous                         read(is, rs{tG, 1, width == -1 ? 4u : static_cast<unsigned>(width)});
74261b8b02a4SEd Tanous                         checked_set(G, tG, not_a_year, is);
74271b8b02a4SEd Tanous                     }
74281b8b02a4SEd Tanous                     else
74291b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
74301b8b02a4SEd Tanous                     command = nullptr;
74311b8b02a4SEd Tanous                     width = -1;
74321b8b02a4SEd Tanous                     modified = CharT{};
74331b8b02a4SEd Tanous                 }
74341b8b02a4SEd Tanous                 else
74351b8b02a4SEd Tanous                     read(is, *fmt);
74361b8b02a4SEd Tanous                 break;
74371b8b02a4SEd Tanous             case 'U':
74381b8b02a4SEd Tanous                 if (command)
74391b8b02a4SEd Tanous                 {
74401b8b02a4SEd Tanous                     if (modified == CharT{})
74411b8b02a4SEd Tanous                     {
74421b8b02a4SEd Tanous                         int tU = not_a_week_num;
74431b8b02a4SEd Tanous                         read(is, ru{tU, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
74441b8b02a4SEd Tanous                         checked_set(U, tU, not_a_week_num, is);
74451b8b02a4SEd Tanous                     }
74461b8b02a4SEd Tanous                     else
74471b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
74481b8b02a4SEd Tanous                     command = nullptr;
74491b8b02a4SEd Tanous                     width = -1;
74501b8b02a4SEd Tanous                     modified = CharT{};
74511b8b02a4SEd Tanous                 }
74521b8b02a4SEd Tanous                 else
74531b8b02a4SEd Tanous                     read(is, *fmt);
74541b8b02a4SEd Tanous                 break;
74551b8b02a4SEd Tanous             case 'V':
74561b8b02a4SEd Tanous                 if (command)
74571b8b02a4SEd Tanous                 {
74581b8b02a4SEd Tanous                     if (modified == CharT{})
74591b8b02a4SEd Tanous                     {
74601b8b02a4SEd Tanous                         int tV = not_a_week_num;
74611b8b02a4SEd Tanous                         read(is, ru{tV, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
74621b8b02a4SEd Tanous                         checked_set(V, tV, not_a_week_num, is);
74631b8b02a4SEd Tanous                     }
74641b8b02a4SEd Tanous                     else
74651b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
74661b8b02a4SEd Tanous                     command = nullptr;
74671b8b02a4SEd Tanous                     width = -1;
74681b8b02a4SEd Tanous                     modified = CharT{};
74691b8b02a4SEd Tanous                 }
74701b8b02a4SEd Tanous                 else
74711b8b02a4SEd Tanous                     read(is, *fmt);
74721b8b02a4SEd Tanous                 break;
74731b8b02a4SEd Tanous             case 'W':
74741b8b02a4SEd Tanous                 if (command)
74751b8b02a4SEd Tanous                 {
74761b8b02a4SEd Tanous                     if (modified == CharT{})
74771b8b02a4SEd Tanous                     {
74781b8b02a4SEd Tanous                         int tW = not_a_week_num;
74791b8b02a4SEd Tanous                         read(is, ru{tW, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
74801b8b02a4SEd Tanous                         checked_set(W, tW, not_a_week_num, is);
74811b8b02a4SEd Tanous                     }
74821b8b02a4SEd Tanous                     else
74831b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
74841b8b02a4SEd Tanous                     command = nullptr;
74851b8b02a4SEd Tanous                     width = -1;
74861b8b02a4SEd Tanous                     modified = CharT{};
74871b8b02a4SEd Tanous                 }
74881b8b02a4SEd Tanous                 else
74891b8b02a4SEd Tanous                     read(is, *fmt);
74901b8b02a4SEd Tanous                 break;
74911b8b02a4SEd Tanous             case 'E':
74921b8b02a4SEd Tanous             case 'O':
74931b8b02a4SEd Tanous                 if (command)
74941b8b02a4SEd Tanous                 {
74951b8b02a4SEd Tanous                     if (modified == CharT{})
74961b8b02a4SEd Tanous                     {
74971b8b02a4SEd Tanous                         modified = *fmt;
74981b8b02a4SEd Tanous                     }
74991b8b02a4SEd Tanous                     else
75001b8b02a4SEd Tanous                     {
75011b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
75021b8b02a4SEd Tanous                         command = nullptr;
75031b8b02a4SEd Tanous                         width = -1;
75041b8b02a4SEd Tanous                         modified = CharT{};
75051b8b02a4SEd Tanous                     }
75061b8b02a4SEd Tanous                 }
75071b8b02a4SEd Tanous                 else
75081b8b02a4SEd Tanous                     read(is, *fmt);
75091b8b02a4SEd Tanous                 break;
75101b8b02a4SEd Tanous             case '%':
75111b8b02a4SEd Tanous                 if (command)
75121b8b02a4SEd Tanous                 {
75131b8b02a4SEd Tanous                     if (modified == CharT{})
75141b8b02a4SEd Tanous                         read(is, *fmt);
75151b8b02a4SEd Tanous                     else
75161b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
75171b8b02a4SEd Tanous                     command = nullptr;
75181b8b02a4SEd Tanous                     width = -1;
75191b8b02a4SEd Tanous                     modified = CharT{};
75201b8b02a4SEd Tanous                 }
75211b8b02a4SEd Tanous                 else
75221b8b02a4SEd Tanous                     command = fmt;
75231b8b02a4SEd Tanous                 break;
75241b8b02a4SEd Tanous             case 'z':
75251b8b02a4SEd Tanous                 if (command)
75261b8b02a4SEd Tanous                 {
75271b8b02a4SEd Tanous                     int tH, tM;
75281b8b02a4SEd Tanous                     minutes toff = not_a_offset;
75291b8b02a4SEd Tanous                     bool neg = false;
75301b8b02a4SEd Tanous                     auto ic = is.peek();
75311b8b02a4SEd Tanous                     if (!Traits::eq_int_type(ic, Traits::eof()))
75321b8b02a4SEd Tanous                     {
75331b8b02a4SEd Tanous                         auto c = static_cast<char>(Traits::to_char_type(ic));
75341b8b02a4SEd Tanous                         if (c == '-')
75351b8b02a4SEd Tanous                             neg = true;
75361b8b02a4SEd Tanous                     }
75371b8b02a4SEd Tanous                     if (modified == CharT{})
75381b8b02a4SEd Tanous                     {
75391b8b02a4SEd Tanous                         read(is, rs{tH, 2, 2});
75401b8b02a4SEd Tanous                         if (!is.fail())
75411b8b02a4SEd Tanous                             toff = hours{std::abs(tH)};
75421b8b02a4SEd Tanous                         if (is.good())
75431b8b02a4SEd Tanous                         {
75441b8b02a4SEd Tanous                             ic = is.peek();
75451b8b02a4SEd Tanous                             if (!Traits::eq_int_type(ic, Traits::eof()))
75461b8b02a4SEd Tanous                             {
75471b8b02a4SEd Tanous                                 auto c = static_cast<char>(Traits::to_char_type(ic));
75481b8b02a4SEd Tanous                                 if ('0' <= c && c <= '9')
75491b8b02a4SEd Tanous                                 {
75501b8b02a4SEd Tanous                                     read(is, ru{tM, 2, 2});
75511b8b02a4SEd Tanous                                     if (!is.fail())
75521b8b02a4SEd Tanous                                         toff += minutes{tM};
75531b8b02a4SEd Tanous                                 }
75541b8b02a4SEd Tanous                             }
75551b8b02a4SEd Tanous                         }
75561b8b02a4SEd Tanous                     }
75571b8b02a4SEd Tanous                     else
75581b8b02a4SEd Tanous                     {
75591b8b02a4SEd Tanous                         read(is, rs{tH, 1, 2});
75601b8b02a4SEd Tanous                         if (!is.fail())
75611b8b02a4SEd Tanous                             toff = hours{std::abs(tH)};
75621b8b02a4SEd Tanous                         if (is.good())
75631b8b02a4SEd Tanous                         {
75641b8b02a4SEd Tanous                             ic = is.peek();
75651b8b02a4SEd Tanous                             if (!Traits::eq_int_type(ic, Traits::eof()))
75661b8b02a4SEd Tanous                             {
75671b8b02a4SEd Tanous                                 auto c = static_cast<char>(Traits::to_char_type(ic));
75681b8b02a4SEd Tanous                                 if (c == ':')
75691b8b02a4SEd Tanous                                 {
75701b8b02a4SEd Tanous                                     (void)is.get();
75711b8b02a4SEd Tanous                                     read(is, ru{tM, 2, 2});
75721b8b02a4SEd Tanous                                     if (!is.fail())
75731b8b02a4SEd Tanous                                         toff += minutes{tM};
75741b8b02a4SEd Tanous                                 }
75751b8b02a4SEd Tanous                             }
75761b8b02a4SEd Tanous                         }
75771b8b02a4SEd Tanous                     }
75781b8b02a4SEd Tanous                     if (neg)
75791b8b02a4SEd Tanous                         toff = -toff;
75801b8b02a4SEd Tanous                     checked_set(temp_offset, toff, not_a_offset, is);
75811b8b02a4SEd Tanous                     command = nullptr;
75821b8b02a4SEd Tanous                     width = -1;
75831b8b02a4SEd Tanous                     modified = CharT{};
75841b8b02a4SEd Tanous                 }
75851b8b02a4SEd Tanous                 else
75861b8b02a4SEd Tanous                     read(is, *fmt);
75871b8b02a4SEd Tanous                 break;
75881b8b02a4SEd Tanous             case 'Z':
75891b8b02a4SEd Tanous                 if (command)
75901b8b02a4SEd Tanous                 {
75911b8b02a4SEd Tanous                     if (modified == CharT{})
75921b8b02a4SEd Tanous                     {
75931b8b02a4SEd Tanous                         std::basic_string<CharT, Traits, Alloc> buf;
75941b8b02a4SEd Tanous                         while (is.rdstate() == std::ios::goodbit)
75951b8b02a4SEd Tanous                         {
75961b8b02a4SEd Tanous                             auto i = is.rdbuf()->sgetc();
75971b8b02a4SEd Tanous                             if (Traits::eq_int_type(i, Traits::eof()))
75981b8b02a4SEd Tanous                             {
75991b8b02a4SEd Tanous                                 is.setstate(ios::eofbit);
76001b8b02a4SEd Tanous                                 break;
76011b8b02a4SEd Tanous                             }
76021b8b02a4SEd Tanous                             auto wc = Traits::to_char_type(i);
76031b8b02a4SEd Tanous                             auto c = static_cast<char>(wc);
76041b8b02a4SEd Tanous                             // is c a valid time zone name or abbreviation character?
76051b8b02a4SEd Tanous                             if (!(CharT{1} < wc && wc < CharT{127}) || !(isalnum(c) ||
76061b8b02a4SEd Tanous                                     c == '_' || c == '/' || c == '-' || c == '+'))
76071b8b02a4SEd Tanous                                 break;
76081b8b02a4SEd Tanous                             buf.push_back(c);
76091b8b02a4SEd Tanous                             is.rdbuf()->sbumpc();
76101b8b02a4SEd Tanous                         }
76111b8b02a4SEd Tanous                         if (buf.empty())
76121b8b02a4SEd Tanous                             is.setstate(ios::failbit);
76131b8b02a4SEd Tanous                         checked_set(temp_abbrev, buf, {}, is);
76141b8b02a4SEd Tanous                     }
76151b8b02a4SEd Tanous                     else
76161b8b02a4SEd Tanous                         read(is, CharT{'%'}, width, modified, *fmt);
76171b8b02a4SEd Tanous                     command = nullptr;
76181b8b02a4SEd Tanous                     width = -1;
76191b8b02a4SEd Tanous                     modified = CharT{};
76201b8b02a4SEd Tanous                 }
76211b8b02a4SEd Tanous                 else
76221b8b02a4SEd Tanous                     read(is, *fmt);
76231b8b02a4SEd Tanous                 break;
76241b8b02a4SEd Tanous             default:
76251b8b02a4SEd Tanous                 if (command)
76261b8b02a4SEd Tanous                 {
76271b8b02a4SEd Tanous                     if (width == -1 && modified == CharT{} && '0' <= *fmt && *fmt <= '9')
76281b8b02a4SEd Tanous                     {
76291b8b02a4SEd Tanous                         width = static_cast<char>(*fmt) - '0';
76301b8b02a4SEd Tanous                         while ('0' <= fmt[1] && fmt[1] <= '9')
76311b8b02a4SEd Tanous                             width = 10*width + static_cast<char>(*++fmt) - '0';
76321b8b02a4SEd Tanous                     }
76331b8b02a4SEd Tanous                     else
76341b8b02a4SEd Tanous                     {
76351b8b02a4SEd Tanous                         if (modified == CharT{})
76361b8b02a4SEd Tanous                             read(is, CharT{'%'}, width, *fmt);
76371b8b02a4SEd Tanous                         else
76381b8b02a4SEd Tanous                             read(is, CharT{'%'}, width, modified, *fmt);
76391b8b02a4SEd Tanous                         command = nullptr;
76401b8b02a4SEd Tanous                         width = -1;
76411b8b02a4SEd Tanous                         modified = CharT{};
76421b8b02a4SEd Tanous                     }
76431b8b02a4SEd Tanous                 }
76441b8b02a4SEd Tanous                 else  // !command
76451b8b02a4SEd Tanous                 {
76461b8b02a4SEd Tanous                     if (isspace(static_cast<unsigned char>(*fmt)))
76471b8b02a4SEd Tanous                     {
76481b8b02a4SEd Tanous                         // space matches 0 or more white space characters
76491b8b02a4SEd Tanous                         if (is.good())
76501b8b02a4SEd Tanous                            ws(is);
76511b8b02a4SEd Tanous                     }
76521b8b02a4SEd Tanous                     else
76531b8b02a4SEd Tanous                         read(is, *fmt);
76541b8b02a4SEd Tanous                 }
76551b8b02a4SEd Tanous                 break;
76561b8b02a4SEd Tanous             }
76571b8b02a4SEd Tanous         }
76581b8b02a4SEd Tanous         // is.fail() || *fmt == CharT{}
76591b8b02a4SEd Tanous         if (is.rdstate() == ios::goodbit && command)
76601b8b02a4SEd Tanous         {
76611b8b02a4SEd Tanous             if (modified == CharT{})
76621b8b02a4SEd Tanous                 read(is, CharT{'%'}, width);
76631b8b02a4SEd Tanous             else
76641b8b02a4SEd Tanous                 read(is, CharT{'%'}, width, modified);
76651b8b02a4SEd Tanous         }
76661b8b02a4SEd Tanous         if (!is.fail())
76671b8b02a4SEd Tanous         {
76681b8b02a4SEd Tanous             if (y != not_a_2digit_year)
76691b8b02a4SEd Tanous             {
76701b8b02a4SEd Tanous                 // Convert y and an optional C to Y
76711b8b02a4SEd Tanous                 if (!(0 <= y && y <= 99))
76721b8b02a4SEd Tanous                     goto broken;
76731b8b02a4SEd Tanous                 if (C == not_a_century)
76741b8b02a4SEd Tanous                 {
76751b8b02a4SEd Tanous                     if (Y == not_a_year)
76761b8b02a4SEd Tanous                     {
76771b8b02a4SEd Tanous                         if (y >= 69)
76781b8b02a4SEd Tanous                             C = 19;
76791b8b02a4SEd Tanous                         else
76801b8b02a4SEd Tanous                             C = 20;
76811b8b02a4SEd Tanous                     }
76821b8b02a4SEd Tanous                     else
76831b8b02a4SEd Tanous                     {
76841b8b02a4SEd Tanous                         C = (Y >= 0 ? Y : Y-100) / 100;
76851b8b02a4SEd Tanous                     }
76861b8b02a4SEd Tanous                 }
76871b8b02a4SEd Tanous                 int tY;
76881b8b02a4SEd Tanous                 if (C >= 0)
76891b8b02a4SEd Tanous                     tY = 100*C + y;
76901b8b02a4SEd Tanous                 else
76911b8b02a4SEd Tanous                     tY = 100*(C+1) - (y == 0 ? 100 : y);
76921b8b02a4SEd Tanous                 if (Y != not_a_year && Y != tY)
76931b8b02a4SEd Tanous                     goto broken;
76941b8b02a4SEd Tanous                 Y = tY;
76951b8b02a4SEd Tanous             }
76961b8b02a4SEd Tanous             if (g != not_a_2digit_year)
76971b8b02a4SEd Tanous             {
76981b8b02a4SEd Tanous                 // Convert g and an optional C to G
76991b8b02a4SEd Tanous                 if (!(0 <= g && g <= 99))
77001b8b02a4SEd Tanous                     goto broken;
77011b8b02a4SEd Tanous                 if (C == not_a_century)
77021b8b02a4SEd Tanous                 {
77031b8b02a4SEd Tanous                     if (G == not_a_year)
77041b8b02a4SEd Tanous                     {
77051b8b02a4SEd Tanous                         if (g >= 69)
77061b8b02a4SEd Tanous                             C = 19;
77071b8b02a4SEd Tanous                         else
77081b8b02a4SEd Tanous                             C = 20;
77091b8b02a4SEd Tanous                     }
77101b8b02a4SEd Tanous                     else
77111b8b02a4SEd Tanous                     {
77121b8b02a4SEd Tanous                         C = (G >= 0 ? G : G-100) / 100;
77131b8b02a4SEd Tanous                     }
77141b8b02a4SEd Tanous                 }
77151b8b02a4SEd Tanous                 int tG;
77161b8b02a4SEd Tanous                 if (C >= 0)
77171b8b02a4SEd Tanous                     tG = 100*C + g;
77181b8b02a4SEd Tanous                 else
77191b8b02a4SEd Tanous                     tG = 100*(C+1) - (g == 0 ? 100 : g);
77201b8b02a4SEd Tanous                 if (G != not_a_year && G != tG)
77211b8b02a4SEd Tanous                     goto broken;
77221b8b02a4SEd Tanous                 G = tG;
77231b8b02a4SEd Tanous             }
77241b8b02a4SEd Tanous             if (Y < static_cast<int>(year::min()) || Y > static_cast<int>(year::max()))
77251b8b02a4SEd Tanous                 Y = not_a_year;
77261b8b02a4SEd Tanous             bool computed = false;
77271b8b02a4SEd Tanous             if (G != not_a_year && V != not_a_week_num && wd != not_a_weekday)
77281b8b02a4SEd Tanous             {
77291b8b02a4SEd Tanous                 year_month_day ymd_trial = sys_days(year{G-1}/December/Thursday[last]) +
77301b8b02a4SEd Tanous                                            (Monday-Thursday) + weeks{V-1} +
77311b8b02a4SEd Tanous                                            (weekday{static_cast<unsigned>(wd)}-Monday);
77321b8b02a4SEd Tanous                 if (Y == not_a_year)
77331b8b02a4SEd Tanous                     Y = static_cast<int>(ymd_trial.year());
77341b8b02a4SEd Tanous                 else if (year{Y} != ymd_trial.year())
77351b8b02a4SEd Tanous                     goto broken;
77361b8b02a4SEd Tanous                 if (m == not_a_month)
77371b8b02a4SEd Tanous                     m = static_cast<int>(static_cast<unsigned>(ymd_trial.month()));
77381b8b02a4SEd Tanous                 else if (month(static_cast<unsigned>(m)) != ymd_trial.month())
77391b8b02a4SEd Tanous                     goto broken;
77401b8b02a4SEd Tanous                 if (d == not_a_day)
77411b8b02a4SEd Tanous                     d = static_cast<int>(static_cast<unsigned>(ymd_trial.day()));
77421b8b02a4SEd Tanous                 else if (day(static_cast<unsigned>(d)) != ymd_trial.day())
77431b8b02a4SEd Tanous                     goto broken;
77441b8b02a4SEd Tanous                 computed = true;
77451b8b02a4SEd Tanous             }
77461b8b02a4SEd Tanous             if (Y != not_a_year && U != not_a_week_num && wd != not_a_weekday)
77471b8b02a4SEd Tanous             {
77481b8b02a4SEd Tanous                 year_month_day ymd_trial = sys_days(year{Y}/January/Sunday[1]) +
77491b8b02a4SEd Tanous                                            weeks{U-1} +
77501b8b02a4SEd Tanous                                            (weekday{static_cast<unsigned>(wd)} - Sunday);
77511b8b02a4SEd Tanous                 if (Y == not_a_year)
77521b8b02a4SEd Tanous                     Y = static_cast<int>(ymd_trial.year());
77531b8b02a4SEd Tanous                 else if (year{Y} != ymd_trial.year())
77541b8b02a4SEd Tanous                     goto broken;
77551b8b02a4SEd Tanous                 if (m == not_a_month)
77561b8b02a4SEd Tanous                     m = static_cast<int>(static_cast<unsigned>(ymd_trial.month()));
77571b8b02a4SEd Tanous                 else if (month(static_cast<unsigned>(m)) != ymd_trial.month())
77581b8b02a4SEd Tanous                     goto broken;
77591b8b02a4SEd Tanous                 if (d == not_a_day)
77601b8b02a4SEd Tanous                     d = static_cast<int>(static_cast<unsigned>(ymd_trial.day()));
77611b8b02a4SEd Tanous                 else if (day(static_cast<unsigned>(d)) != ymd_trial.day())
77621b8b02a4SEd Tanous                     goto broken;
77631b8b02a4SEd Tanous                 computed = true;
77641b8b02a4SEd Tanous             }
77651b8b02a4SEd Tanous             if (Y != not_a_year && W != not_a_week_num && wd != not_a_weekday)
77661b8b02a4SEd Tanous             {
77671b8b02a4SEd Tanous                 year_month_day ymd_trial = sys_days(year{Y}/January/Monday[1]) +
77681b8b02a4SEd Tanous                                            weeks{W-1} +
77691b8b02a4SEd Tanous                                            (weekday{static_cast<unsigned>(wd)} - Monday);
77701b8b02a4SEd Tanous                 if (Y == not_a_year)
77711b8b02a4SEd Tanous                     Y = static_cast<int>(ymd_trial.year());
77721b8b02a4SEd Tanous                 else if (year{Y} != ymd_trial.year())
77731b8b02a4SEd Tanous                     goto broken;
77741b8b02a4SEd Tanous                 if (m == not_a_month)
77751b8b02a4SEd Tanous                     m = static_cast<int>(static_cast<unsigned>(ymd_trial.month()));
77761b8b02a4SEd Tanous                 else if (month(static_cast<unsigned>(m)) != ymd_trial.month())
77771b8b02a4SEd Tanous                     goto broken;
77781b8b02a4SEd Tanous                 if (d == not_a_day)
77791b8b02a4SEd Tanous                     d = static_cast<int>(static_cast<unsigned>(ymd_trial.day()));
77801b8b02a4SEd Tanous                 else if (day(static_cast<unsigned>(d)) != ymd_trial.day())
77811b8b02a4SEd Tanous                     goto broken;
77821b8b02a4SEd Tanous                 computed = true;
77831b8b02a4SEd Tanous             }
77841b8b02a4SEd Tanous             if (j != not_a_doy && Y != not_a_year)
77851b8b02a4SEd Tanous             {
77861b8b02a4SEd Tanous                 auto ymd_trial = year_month_day{local_days(year{Y}/1/1) + days{j-1}};
77871b8b02a4SEd Tanous                 if (m == not_a_month)
77881b8b02a4SEd Tanous                     m = static_cast<int>(static_cast<unsigned>(ymd_trial.month()));
77891b8b02a4SEd Tanous                 else if (month(static_cast<unsigned>(m)) != ymd_trial.month())
77901b8b02a4SEd Tanous                     goto broken;
77911b8b02a4SEd Tanous                 if (d == not_a_day)
77921b8b02a4SEd Tanous                     d = static_cast<int>(static_cast<unsigned>(ymd_trial.day()));
77931b8b02a4SEd Tanous                 else if (day(static_cast<unsigned>(d)) != ymd_trial.day())
77941b8b02a4SEd Tanous                     goto broken;
77951b8b02a4SEd Tanous                 j = not_a_doy;
77961b8b02a4SEd Tanous             }
77971b8b02a4SEd Tanous             auto ymd = year{Y}/m/d;
77981b8b02a4SEd Tanous             if (ymd.ok())
77991b8b02a4SEd Tanous             {
78001b8b02a4SEd Tanous                 if (wd == not_a_weekday)
78011b8b02a4SEd Tanous                     wd = static_cast<int>((weekday(sys_days(ymd)) - Sunday).count());
78021b8b02a4SEd Tanous                 else if (wd != static_cast<int>((weekday(sys_days(ymd)) - Sunday).count()))
78031b8b02a4SEd Tanous                     goto broken;
78041b8b02a4SEd Tanous                 if (!computed)
78051b8b02a4SEd Tanous                 {
78061b8b02a4SEd Tanous                     if (G != not_a_year || V != not_a_week_num)
78071b8b02a4SEd Tanous                     {
78081b8b02a4SEd Tanous                         sys_days sd = ymd;
78091b8b02a4SEd Tanous                         auto G_trial = year_month_day{sd + days{3}}.year();
78101b8b02a4SEd Tanous                         auto start = sys_days((G_trial - years{1})/December/Thursday[last]) +
78111b8b02a4SEd Tanous                                      (Monday - Thursday);
78121b8b02a4SEd Tanous                         if (sd < start)
78131b8b02a4SEd Tanous                         {
78141b8b02a4SEd Tanous                             --G_trial;
78151b8b02a4SEd Tanous                             if (V != not_a_week_num)
78161b8b02a4SEd Tanous                                 start = sys_days((G_trial - years{1})/December/Thursday[last])
78171b8b02a4SEd Tanous                                         + (Monday - Thursday);
78181b8b02a4SEd Tanous                         }
78191b8b02a4SEd Tanous                         if (G != not_a_year && G != static_cast<int>(G_trial))
78201b8b02a4SEd Tanous                             goto broken;
78211b8b02a4SEd Tanous                         if (V != not_a_week_num)
78221b8b02a4SEd Tanous                         {
78231b8b02a4SEd Tanous                             auto V_trial = duration_cast<weeks>(sd - start).count() + 1;
78241b8b02a4SEd Tanous                             if (V != V_trial)
78251b8b02a4SEd Tanous                                 goto broken;
78261b8b02a4SEd Tanous                         }
78271b8b02a4SEd Tanous                     }
78281b8b02a4SEd Tanous                     if (U != not_a_week_num)
78291b8b02a4SEd Tanous                     {
78301b8b02a4SEd Tanous                         auto start = sys_days(Sunday[1]/January/ymd.year());
78311b8b02a4SEd Tanous                         auto U_trial = floor<weeks>(sys_days(ymd) - start).count() + 1;
78321b8b02a4SEd Tanous                         if (U != U_trial)
78331b8b02a4SEd Tanous                             goto broken;
78341b8b02a4SEd Tanous                     }
78351b8b02a4SEd Tanous                     if (W != not_a_week_num)
78361b8b02a4SEd Tanous                     {
78371b8b02a4SEd Tanous                         auto start = sys_days(Monday[1]/January/ymd.year());
78381b8b02a4SEd Tanous                         auto W_trial = floor<weeks>(sys_days(ymd) - start).count() + 1;
78391b8b02a4SEd Tanous                         if (W != W_trial)
78401b8b02a4SEd Tanous                             goto broken;
78411b8b02a4SEd Tanous                     }
78421b8b02a4SEd Tanous                 }
78431b8b02a4SEd Tanous             }
78441b8b02a4SEd Tanous             fds.ymd = ymd;
78451b8b02a4SEd Tanous             if (I != not_a_hour_12_value)
78461b8b02a4SEd Tanous             {
78471b8b02a4SEd Tanous                 if (!(1 <= I && I <= 12))
78481b8b02a4SEd Tanous                     goto broken;
78491b8b02a4SEd Tanous                 if (p != not_a_ampm)
78501b8b02a4SEd Tanous                 {
78511b8b02a4SEd Tanous                     // p is in [0, 1] == [AM, PM]
78521b8b02a4SEd Tanous                     // Store trial H in I
78531b8b02a4SEd Tanous                     if (I == 12)
78541b8b02a4SEd Tanous                         --p;
78551b8b02a4SEd Tanous                     I += p*12;
78561b8b02a4SEd Tanous                     // Either set H from I or make sure H and I are consistent
78571b8b02a4SEd Tanous                     if (H == not_a_hour)
78581b8b02a4SEd Tanous                         H = I;
78591b8b02a4SEd Tanous                     else if (I != H)
78601b8b02a4SEd Tanous                         goto broken;
78611b8b02a4SEd Tanous                 }
78621b8b02a4SEd Tanous                 else  // p == not_a_ampm
78631b8b02a4SEd Tanous                 {
78641b8b02a4SEd Tanous                     // if H, make sure H and I could be consistent
78651b8b02a4SEd Tanous                     if (H != not_a_hour)
78661b8b02a4SEd Tanous                     {
78671b8b02a4SEd Tanous                         if (I == 12)
78681b8b02a4SEd Tanous                         {
78691b8b02a4SEd Tanous                             if (H != 0 && H != 12)
78701b8b02a4SEd Tanous                                 goto broken;
78711b8b02a4SEd Tanous                         }
78721b8b02a4SEd Tanous                         else if (!(I == H || I == H+12))
78731b8b02a4SEd Tanous                         {
78741b8b02a4SEd Tanous                             goto broken;
78751b8b02a4SEd Tanous                         }
78761b8b02a4SEd Tanous                     }
78771b8b02a4SEd Tanous                     else  // I is ambiguous, AM or PM?
78781b8b02a4SEd Tanous                         goto broken;
78791b8b02a4SEd Tanous                 }
78801b8b02a4SEd Tanous             }
78811b8b02a4SEd Tanous             if (H != not_a_hour)
78821b8b02a4SEd Tanous             {
78831b8b02a4SEd Tanous                 fds.has_tod = true;
78841b8b02a4SEd Tanous                 fds.tod = hh_mm_ss<Duration>{hours{H}};
78851b8b02a4SEd Tanous             }
78861b8b02a4SEd Tanous             if (M != not_a_minute)
78871b8b02a4SEd Tanous             {
78881b8b02a4SEd Tanous                 fds.has_tod = true;
78891b8b02a4SEd Tanous                 fds.tod.m_ = minutes{M};
78901b8b02a4SEd Tanous             }
78911b8b02a4SEd Tanous             if (s != not_a_second)
78921b8b02a4SEd Tanous             {
78931b8b02a4SEd Tanous                 fds.has_tod = true;
78941b8b02a4SEd Tanous                 fds.tod.s_ = detail::decimal_format_seconds<Duration>{s};
78951b8b02a4SEd Tanous             }
78961b8b02a4SEd Tanous             if (j != not_a_doy)
78971b8b02a4SEd Tanous             {
78981b8b02a4SEd Tanous                 fds.has_tod = true;
78991b8b02a4SEd Tanous                 fds.tod.h_ += hours{days{j}};
79001b8b02a4SEd Tanous             }
79011b8b02a4SEd Tanous             if (wd != not_a_weekday)
79021b8b02a4SEd Tanous                 fds.wd = weekday{static_cast<unsigned>(wd)};
79031b8b02a4SEd Tanous             if (abbrev != nullptr)
79041b8b02a4SEd Tanous                 *abbrev = std::move(temp_abbrev);
79051b8b02a4SEd Tanous             if (offset != nullptr && temp_offset != not_a_offset)
79061b8b02a4SEd Tanous               *offset = temp_offset;
79071b8b02a4SEd Tanous         }
79081b8b02a4SEd Tanous        return is;
79091b8b02a4SEd Tanous     }
79101b8b02a4SEd Tanous broken:
79111b8b02a4SEd Tanous     is.setstate(ios::failbit);
79121b8b02a4SEd Tanous     return is;
79131b8b02a4SEd Tanous }
79141b8b02a4SEd Tanous 
79151b8b02a4SEd Tanous template <class CharT, class Traits, class Alloc = std::allocator<CharT>>
79161b8b02a4SEd Tanous std::basic_istream<CharT, Traits>&
79171b8b02a4SEd Tanous from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, year& y,
79181b8b02a4SEd Tanous             std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
79191b8b02a4SEd Tanous             std::chrono::minutes* offset = nullptr)
79201b8b02a4SEd Tanous {
79211b8b02a4SEd Tanous     using CT = std::chrono::seconds;
79221b8b02a4SEd Tanous     fields<CT> fds{};
79231b8b02a4SEd Tanous     date::from_stream(is, fmt, fds, abbrev, offset);
79241b8b02a4SEd Tanous     if (!fds.ymd.year().ok())
79251b8b02a4SEd Tanous         is.setstate(std::ios::failbit);
79261b8b02a4SEd Tanous     if (!is.fail())
79271b8b02a4SEd Tanous         y = fds.ymd.year();
79281b8b02a4SEd Tanous     return is;
79291b8b02a4SEd Tanous }
79301b8b02a4SEd Tanous 
79311b8b02a4SEd Tanous template <class CharT, class Traits, class Alloc = std::allocator<CharT>>
79321b8b02a4SEd Tanous std::basic_istream<CharT, Traits>&
79331b8b02a4SEd Tanous from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, month& m,
79341b8b02a4SEd Tanous             std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
79351b8b02a4SEd Tanous             std::chrono::minutes* offset = nullptr)
79361b8b02a4SEd Tanous {
79371b8b02a4SEd Tanous     using CT = std::chrono::seconds;
79381b8b02a4SEd Tanous     fields<CT> fds{};
79391b8b02a4SEd Tanous     date::from_stream(is, fmt, fds, abbrev, offset);
79401b8b02a4SEd Tanous     if (!fds.ymd.month().ok())
79411b8b02a4SEd Tanous         is.setstate(std::ios::failbit);
79421b8b02a4SEd Tanous     if (!is.fail())
79431b8b02a4SEd Tanous         m = fds.ymd.month();
79441b8b02a4SEd Tanous     return is;
79451b8b02a4SEd Tanous }
79461b8b02a4SEd Tanous 
79471b8b02a4SEd Tanous template <class CharT, class Traits, class Alloc = std::allocator<CharT>>
79481b8b02a4SEd Tanous std::basic_istream<CharT, Traits>&
79491b8b02a4SEd Tanous from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, day& d,
79501b8b02a4SEd Tanous             std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
79511b8b02a4SEd Tanous             std::chrono::minutes* offset = nullptr)
79521b8b02a4SEd Tanous {
79531b8b02a4SEd Tanous     using CT = std::chrono::seconds;
79541b8b02a4SEd Tanous     fields<CT> fds{};
79551b8b02a4SEd Tanous     date::from_stream(is, fmt, fds, abbrev, offset);
79561b8b02a4SEd Tanous     if (!fds.ymd.day().ok())
79571b8b02a4SEd Tanous         is.setstate(std::ios::failbit);
79581b8b02a4SEd Tanous     if (!is.fail())
79591b8b02a4SEd Tanous         d = fds.ymd.day();
79601b8b02a4SEd Tanous     return is;
79611b8b02a4SEd Tanous }
79621b8b02a4SEd Tanous 
79631b8b02a4SEd Tanous template <class CharT, class Traits, class Alloc = std::allocator<CharT>>
79641b8b02a4SEd Tanous std::basic_istream<CharT, Traits>&
79651b8b02a4SEd Tanous from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, weekday& wd,
79661b8b02a4SEd Tanous             std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
79671b8b02a4SEd Tanous             std::chrono::minutes* offset = nullptr)
79681b8b02a4SEd Tanous {
79691b8b02a4SEd Tanous     using CT = std::chrono::seconds;
79701b8b02a4SEd Tanous     fields<CT> fds{};
79711b8b02a4SEd Tanous     date::from_stream(is, fmt, fds, abbrev, offset);
79721b8b02a4SEd Tanous     if (!fds.wd.ok())
79731b8b02a4SEd Tanous         is.setstate(std::ios::failbit);
79741b8b02a4SEd Tanous     if (!is.fail())
79751b8b02a4SEd Tanous         wd = fds.wd;
79761b8b02a4SEd Tanous     return is;
79771b8b02a4SEd Tanous }
79781b8b02a4SEd Tanous 
79791b8b02a4SEd Tanous template <class CharT, class Traits, class Alloc = std::allocator<CharT>>
79801b8b02a4SEd Tanous std::basic_istream<CharT, Traits>&
79811b8b02a4SEd Tanous from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, year_month& ym,
79821b8b02a4SEd Tanous             std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
79831b8b02a4SEd Tanous             std::chrono::minutes* offset = nullptr)
79841b8b02a4SEd Tanous {
79851b8b02a4SEd Tanous     using CT = std::chrono::seconds;
79861b8b02a4SEd Tanous     fields<CT> fds{};
79871b8b02a4SEd Tanous     date::from_stream(is, fmt, fds, abbrev, offset);
79881b8b02a4SEd Tanous     if (!fds.ymd.month().ok())
79891b8b02a4SEd Tanous         is.setstate(std::ios::failbit);
79901b8b02a4SEd Tanous     if (!is.fail())
79911b8b02a4SEd Tanous         ym = fds.ymd.year()/fds.ymd.month();
79921b8b02a4SEd Tanous     return is;
79931b8b02a4SEd Tanous }
79941b8b02a4SEd Tanous 
79951b8b02a4SEd Tanous template <class CharT, class Traits, class Alloc = std::allocator<CharT>>
79961b8b02a4SEd Tanous std::basic_istream<CharT, Traits>&
79971b8b02a4SEd Tanous from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt, month_day& md,
79981b8b02a4SEd Tanous             std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
79991b8b02a4SEd Tanous             std::chrono::minutes* offset = nullptr)
80001b8b02a4SEd Tanous {
80011b8b02a4SEd Tanous     using CT = std::chrono::seconds;
80021b8b02a4SEd Tanous     fields<CT> fds{};
80031b8b02a4SEd Tanous     date::from_stream(is, fmt, fds, abbrev, offset);
80041b8b02a4SEd Tanous     if (!fds.ymd.month().ok() || !fds.ymd.day().ok())
80051b8b02a4SEd Tanous         is.setstate(std::ios::failbit);
80061b8b02a4SEd Tanous     if (!is.fail())
80071b8b02a4SEd Tanous         md = fds.ymd.month()/fds.ymd.day();
80081b8b02a4SEd Tanous     return is;
80091b8b02a4SEd Tanous }
80101b8b02a4SEd Tanous 
80111b8b02a4SEd Tanous template <class CharT, class Traits, class Alloc = std::allocator<CharT>>
80121b8b02a4SEd Tanous std::basic_istream<CharT, Traits>&
80131b8b02a4SEd Tanous from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
80141b8b02a4SEd Tanous             year_month_day& ymd, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
80151b8b02a4SEd Tanous             std::chrono::minutes* offset = nullptr)
80161b8b02a4SEd Tanous {
80171b8b02a4SEd Tanous     using CT = std::chrono::seconds;
80181b8b02a4SEd Tanous     fields<CT> fds{};
80191b8b02a4SEd Tanous     date::from_stream(is, fmt, fds, abbrev, offset);
80201b8b02a4SEd Tanous     if (!fds.ymd.ok())
80211b8b02a4SEd Tanous         is.setstate(std::ios::failbit);
80221b8b02a4SEd Tanous     if (!is.fail())
80231b8b02a4SEd Tanous         ymd = fds.ymd;
80241b8b02a4SEd Tanous     return is;
80251b8b02a4SEd Tanous }
80261b8b02a4SEd Tanous 
80271b8b02a4SEd Tanous template <class Duration, class CharT, class Traits, class Alloc = std::allocator<CharT>>
80281b8b02a4SEd Tanous std::basic_istream<CharT, Traits>&
80291b8b02a4SEd Tanous from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
80301b8b02a4SEd Tanous             sys_time<Duration>& tp, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
80311b8b02a4SEd Tanous             std::chrono::minutes* offset = nullptr)
80321b8b02a4SEd Tanous {
80331b8b02a4SEd Tanous     using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
80341b8b02a4SEd Tanous     using detail::round_i;
80351b8b02a4SEd Tanous     std::chrono::minutes offset_local{};
80361b8b02a4SEd Tanous     auto offptr = offset ? offset : &offset_local;
80371b8b02a4SEd Tanous     fields<CT> fds{};
80381b8b02a4SEd Tanous     fds.has_tod = true;
80391b8b02a4SEd Tanous     date::from_stream(is, fmt, fds, abbrev, offptr);
80401b8b02a4SEd Tanous     if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
80411b8b02a4SEd Tanous         is.setstate(std::ios::failbit);
80421b8b02a4SEd Tanous     if (!is.fail())
80431b8b02a4SEd Tanous         tp = round_i<Duration>(sys_days(fds.ymd) - *offptr + fds.tod.to_duration());
80441b8b02a4SEd Tanous     return is;
80451b8b02a4SEd Tanous }
80461b8b02a4SEd Tanous 
80471b8b02a4SEd Tanous template <class Duration, class CharT, class Traits, class Alloc = std::allocator<CharT>>
80481b8b02a4SEd Tanous std::basic_istream<CharT, Traits>&
80491b8b02a4SEd Tanous from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
80501b8b02a4SEd Tanous             local_time<Duration>& tp, std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
80511b8b02a4SEd Tanous             std::chrono::minutes* offset = nullptr)
80521b8b02a4SEd Tanous {
80531b8b02a4SEd Tanous     using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
80541b8b02a4SEd Tanous     using detail::round_i;
80551b8b02a4SEd Tanous     fields<CT> fds{};
80561b8b02a4SEd Tanous     fds.has_tod = true;
80571b8b02a4SEd Tanous     date::from_stream(is, fmt, fds, abbrev, offset);
80581b8b02a4SEd Tanous     if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
80591b8b02a4SEd Tanous         is.setstate(std::ios::failbit);
80601b8b02a4SEd Tanous     if (!is.fail())
80611b8b02a4SEd Tanous         tp = round_i<Duration>(local_seconds{local_days(fds.ymd)} + fds.tod.to_duration());
80621b8b02a4SEd Tanous     return is;
80631b8b02a4SEd Tanous }
80641b8b02a4SEd Tanous 
80651b8b02a4SEd Tanous template <class Rep, class Period, class CharT, class Traits, class Alloc = std::allocator<CharT>>
80661b8b02a4SEd Tanous std::basic_istream<CharT, Traits>&
80671b8b02a4SEd Tanous from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
80681b8b02a4SEd Tanous             std::chrono::duration<Rep, Period>& d,
80691b8b02a4SEd Tanous             std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
80701b8b02a4SEd Tanous             std::chrono::minutes* offset = nullptr)
80711b8b02a4SEd Tanous {
80721b8b02a4SEd Tanous     using Duration = std::chrono::duration<Rep, Period>;
80731b8b02a4SEd Tanous     using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
80741b8b02a4SEd Tanous     using detail::round_i;
80751b8b02a4SEd Tanous     fields<CT> fds{};
80761b8b02a4SEd Tanous     date::from_stream(is, fmt, fds, abbrev, offset);
80771b8b02a4SEd Tanous     if (!fds.has_tod)
80781b8b02a4SEd Tanous         is.setstate(std::ios::failbit);
80791b8b02a4SEd Tanous     if (!is.fail())
80801b8b02a4SEd Tanous         d = round_i<Duration>(fds.tod.to_duration());
80811b8b02a4SEd Tanous     return is;
80821b8b02a4SEd Tanous }
80831b8b02a4SEd Tanous 
80841b8b02a4SEd Tanous template <class Parsable, class CharT, class Traits = std::char_traits<CharT>,
80851b8b02a4SEd Tanous           class Alloc = std::allocator<CharT>>
80861b8b02a4SEd Tanous struct parse_manip
80871b8b02a4SEd Tanous {
80881b8b02a4SEd Tanous     const std::basic_string<CharT, Traits, Alloc> format_;
80891b8b02a4SEd Tanous     Parsable&                                     tp_;
80901b8b02a4SEd Tanous     std::basic_string<CharT, Traits, Alloc>*      abbrev_;
80911b8b02a4SEd Tanous     std::chrono::minutes*                         offset_;
80921b8b02a4SEd Tanous 
80931b8b02a4SEd Tanous public:
80941b8b02a4SEd Tanous     parse_manip(std::basic_string<CharT, Traits, Alloc> format, Parsable& tp,
80951b8b02a4SEd Tanous                 std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
80961b8b02a4SEd Tanous                 std::chrono::minutes* offset = nullptr)
80971b8b02a4SEd Tanous         : format_(std::move(format))
80981b8b02a4SEd Tanous         , tp_(tp)
80991b8b02a4SEd Tanous         , abbrev_(abbrev)
81001b8b02a4SEd Tanous         , offset_(offset)
81011b8b02a4SEd Tanous         {}
81021b8b02a4SEd Tanous 
81031b8b02a4SEd Tanous #if HAS_STRING_VIEW
81041b8b02a4SEd Tanous     parse_manip(const CharT* format, Parsable& tp,
81051b8b02a4SEd Tanous                 std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
81061b8b02a4SEd Tanous                 std::chrono::minutes* offset = nullptr)
81071b8b02a4SEd Tanous         : format_(format)
81081b8b02a4SEd Tanous         , tp_(tp)
81091b8b02a4SEd Tanous         , abbrev_(abbrev)
81101b8b02a4SEd Tanous         , offset_(offset)
81111b8b02a4SEd Tanous         {}
81121b8b02a4SEd Tanous 
81131b8b02a4SEd Tanous     parse_manip(std::basic_string_view<CharT, Traits> format, Parsable& tp,
81141b8b02a4SEd Tanous                 std::basic_string<CharT, Traits, Alloc>* abbrev = nullptr,
81151b8b02a4SEd Tanous                 std::chrono::minutes* offset = nullptr)
81161b8b02a4SEd Tanous         : format_(format)
81171b8b02a4SEd Tanous         , tp_(tp)
81181b8b02a4SEd Tanous         , abbrev_(abbrev)
81191b8b02a4SEd Tanous         , offset_(offset)
81201b8b02a4SEd Tanous         {}
81211b8b02a4SEd Tanous #endif  // HAS_STRING_VIEW
81221b8b02a4SEd Tanous };
81231b8b02a4SEd Tanous 
81241b8b02a4SEd Tanous template <class Parsable, class CharT, class Traits, class Alloc>
81251b8b02a4SEd Tanous std::basic_istream<CharT, Traits>&
81261b8b02a4SEd Tanous operator>>(std::basic_istream<CharT, Traits>& is,
81271b8b02a4SEd Tanous            const parse_manip<Parsable, CharT, Traits, Alloc>& x)
81281b8b02a4SEd Tanous {
81291b8b02a4SEd Tanous     return date::from_stream(is, x.format_.c_str(), x.tp_, x.abbrev_, x.offset_);
81301b8b02a4SEd Tanous }
81311b8b02a4SEd Tanous 
81321b8b02a4SEd Tanous template <class Parsable, class CharT, class Traits, class Alloc>
81331b8b02a4SEd Tanous inline
81341b8b02a4SEd Tanous auto
81351b8b02a4SEd Tanous parse(const std::basic_string<CharT, Traits, Alloc>& format, Parsable& tp)
81361b8b02a4SEd Tanous     -> decltype(date::from_stream(std::declval<std::basic_istream<CharT, Traits>&>(),
81371b8b02a4SEd Tanous                             format.c_str(), tp),
81381b8b02a4SEd Tanous                 parse_manip<Parsable, CharT, Traits, Alloc>{format, tp})
81391b8b02a4SEd Tanous {
81401b8b02a4SEd Tanous     return {format, tp};
81411b8b02a4SEd Tanous }
81421b8b02a4SEd Tanous 
81431b8b02a4SEd Tanous template <class Parsable, class CharT, class Traits, class Alloc>
81441b8b02a4SEd Tanous inline
81451b8b02a4SEd Tanous auto
81461b8b02a4SEd Tanous parse(const std::basic_string<CharT, Traits, Alloc>& format, Parsable& tp,
81471b8b02a4SEd Tanous       std::basic_string<CharT, Traits, Alloc>& abbrev)
81481b8b02a4SEd Tanous     -> decltype(date::from_stream(std::declval<std::basic_istream<CharT, Traits>&>(),
81491b8b02a4SEd Tanous                             format.c_str(), tp, &abbrev),
81501b8b02a4SEd Tanous                 parse_manip<Parsable, CharT, Traits, Alloc>{format, tp, &abbrev})
81511b8b02a4SEd Tanous {
81521b8b02a4SEd Tanous     return {format, tp, &abbrev};
81531b8b02a4SEd Tanous }
81541b8b02a4SEd Tanous 
81551b8b02a4SEd Tanous template <class Parsable, class CharT, class Traits, class Alloc>
81561b8b02a4SEd Tanous inline
81571b8b02a4SEd Tanous auto
81581b8b02a4SEd Tanous parse(const std::basic_string<CharT, Traits, Alloc>& format, Parsable& tp,
81591b8b02a4SEd Tanous       std::chrono::minutes& offset)
81601b8b02a4SEd Tanous     -> decltype(date::from_stream(std::declval<std::basic_istream<CharT, Traits>&>(),
81611b8b02a4SEd Tanous                             format.c_str(), tp,
81621b8b02a4SEd Tanous                             std::declval<std::basic_string<CharT, Traits, Alloc>*>(),
81631b8b02a4SEd Tanous                             &offset),
81641b8b02a4SEd Tanous                 parse_manip<Parsable, CharT, Traits, Alloc>{format, tp, nullptr, &offset})
81651b8b02a4SEd Tanous {
81661b8b02a4SEd Tanous     return {format, tp, nullptr, &offset};
81671b8b02a4SEd Tanous }
81681b8b02a4SEd Tanous 
81691b8b02a4SEd Tanous template <class Parsable, class CharT, class Traits, class Alloc>
81701b8b02a4SEd Tanous inline
81711b8b02a4SEd Tanous auto
81721b8b02a4SEd Tanous parse(const std::basic_string<CharT, Traits, Alloc>& format, Parsable& tp,
81731b8b02a4SEd Tanous       std::basic_string<CharT, Traits, Alloc>& abbrev, std::chrono::minutes& offset)
81741b8b02a4SEd Tanous     -> decltype(date::from_stream(std::declval<std::basic_istream<CharT, Traits>&>(),
81751b8b02a4SEd Tanous                             format.c_str(), tp, &abbrev, &offset),
81761b8b02a4SEd Tanous                 parse_manip<Parsable, CharT, Traits, Alloc>{format, tp, &abbrev, &offset})
81771b8b02a4SEd Tanous {
81781b8b02a4SEd Tanous     return {format, tp, &abbrev, &offset};
81791b8b02a4SEd Tanous }
81801b8b02a4SEd Tanous 
81811b8b02a4SEd Tanous // const CharT* formats
81821b8b02a4SEd Tanous 
81831b8b02a4SEd Tanous template <class Parsable, class CharT>
81841b8b02a4SEd Tanous inline
81851b8b02a4SEd Tanous auto
81861b8b02a4SEd Tanous parse(const CharT* format, Parsable& tp)
81871b8b02a4SEd Tanous     -> decltype(date::from_stream(std::declval<std::basic_istream<CharT>&>(), format, tp),
81881b8b02a4SEd Tanous                 parse_manip<Parsable, CharT>{format, tp})
81891b8b02a4SEd Tanous {
81901b8b02a4SEd Tanous     return {format, tp};
81911b8b02a4SEd Tanous }
81921b8b02a4SEd Tanous 
81931b8b02a4SEd Tanous template <class Parsable, class CharT, class Traits, class Alloc>
81941b8b02a4SEd Tanous inline
81951b8b02a4SEd Tanous auto
81961b8b02a4SEd Tanous parse(const CharT* format, Parsable& tp, std::basic_string<CharT, Traits, Alloc>& abbrev)
81971b8b02a4SEd Tanous     -> decltype(date::from_stream(std::declval<std::basic_istream<CharT, Traits>&>(), format,
81981b8b02a4SEd Tanous                             tp, &abbrev),
81991b8b02a4SEd Tanous                 parse_manip<Parsable, CharT, Traits, Alloc>{format, tp, &abbrev})
82001b8b02a4SEd Tanous {
82011b8b02a4SEd Tanous     return {format, tp, &abbrev};
82021b8b02a4SEd Tanous }
82031b8b02a4SEd Tanous 
82041b8b02a4SEd Tanous template <class Parsable, class CharT>
82051b8b02a4SEd Tanous inline
82061b8b02a4SEd Tanous auto
82071b8b02a4SEd Tanous parse(const CharT* format, Parsable& tp, std::chrono::minutes& offset)
82081b8b02a4SEd Tanous     -> decltype(date::from_stream(std::declval<std::basic_istream<CharT>&>(), format,
82091b8b02a4SEd Tanous                             tp, std::declval<std::basic_string<CharT>*>(), &offset),
82101b8b02a4SEd Tanous                 parse_manip<Parsable, CharT>{format, tp, nullptr, &offset})
82111b8b02a4SEd Tanous {
82121b8b02a4SEd Tanous     return {format, tp, nullptr, &offset};
82131b8b02a4SEd Tanous }
82141b8b02a4SEd Tanous 
82151b8b02a4SEd Tanous template <class Parsable, class CharT, class Traits, class Alloc>
82161b8b02a4SEd Tanous inline
82171b8b02a4SEd Tanous auto
82181b8b02a4SEd Tanous parse(const CharT* format, Parsable& tp,
82191b8b02a4SEd Tanous       std::basic_string<CharT, Traits, Alloc>& abbrev, std::chrono::minutes& offset)
82201b8b02a4SEd Tanous     -> decltype(date::from_stream(std::declval<std::basic_istream<CharT, Traits>&>(), format,
82211b8b02a4SEd Tanous                             tp, &abbrev, &offset),
82221b8b02a4SEd Tanous                 parse_manip<Parsable, CharT, Traits, Alloc>{format, tp, &abbrev, &offset})
82231b8b02a4SEd Tanous {
82241b8b02a4SEd Tanous     return {format, tp, &abbrev, &offset};
82251b8b02a4SEd Tanous }
82261b8b02a4SEd Tanous 
82271b8b02a4SEd Tanous // duration streaming
82281b8b02a4SEd Tanous 
82291b8b02a4SEd Tanous template <class CharT, class Traits, class Rep, class Period>
82301b8b02a4SEd Tanous inline
82311b8b02a4SEd Tanous std::basic_ostream<CharT, Traits>&
82321b8b02a4SEd Tanous operator<<(std::basic_ostream<CharT, Traits>& os,
82331b8b02a4SEd Tanous            const std::chrono::duration<Rep, Period>& d)
82341b8b02a4SEd Tanous {
82351b8b02a4SEd Tanous     return os << detail::make_string<CharT, Traits>::from(d.count()) +
82361b8b02a4SEd Tanous                  detail::get_units<CharT>(typename Period::type{});
82371b8b02a4SEd Tanous }
82381b8b02a4SEd Tanous 
82391b8b02a4SEd Tanous }  // namespace date
82401b8b02a4SEd Tanous 
82411b8b02a4SEd Tanous #ifdef _MSC_VER
82421b8b02a4SEd Tanous #   pragma warning(pop)
82431b8b02a4SEd Tanous #endif
82441b8b02a4SEd Tanous 
82451b8b02a4SEd Tanous #ifdef __GNUC__
82461b8b02a4SEd Tanous # pragma GCC diagnostic pop
82471b8b02a4SEd Tanous #endif
82481b8b02a4SEd Tanous 
82491b8b02a4SEd Tanous // NOLINTEND
82501b8b02a4SEd Tanous // clang-format off
8251