libstdc++: Add more C++20 additions to <chrono>
authorPatrick Palka <ppalka@redhat.com>
Tue, 25 Aug 2020 14:23:59 +0000 (10:23 -0400)
committerPatrick Palka <ppalka@redhat.com>
Tue, 25 Aug 2020 14:23:59 +0000 (10:23 -0400)
This patch adds the C++20 calendar types and their methods as defined in
[time.cal] (modulo the parsing/printing support).  This patch also
implements [time.hms] and [time.12], and a few more bits of
[time.clock].  The remaining C++20 additions to <chrono> from P0355 and
P1466 depend on [time.zone] and <format>, so they will come later, as
will more optimized versions of some of the algorithms added here.

The non-member operator overloads for the calendar types are defined as
namespace-scope functions in the standard, but here we instead define
these operator overloads as hidden friends.  This simplifies the
implementation somewhat and lets us reap the benefits of hidden friends
for these overloads.

The bulk of this work is based on a patch from Ed Smith-Rowland, which can
be found at the Git branch users/redi/heads/calendar.

Co-authored-by: Ed Smith-Rowland <3dw4rd@verizon.net>
Co-authored-by: Jonathan Wakely <jwakely@redhat.com>
libstdc++-v3/ChangeLog:

* include/std/chrono (time_point::operator++)
(time_point::operator--): Define.
(utc_clock, tai_clock, gps_clock): Forward declare.
(utc_time, utc_seconds, tai_time, tai_seconds, gps_time)
(gps_seconds): Define.
(is_clock<utc_clock>, is_clock<tai_clock>, is_clock<gps_clock>)
(is_clock_v<utc_clock>, is_clock_v<tai_clock>)
(is_clock_v<gps_clock>): Define these specializations.
(leap_second_info): Define.
(day, month, year, weekday, weekday_indexed)
(weekday_last, month_day, month_day_last, month_weekday)
(month_weekday_last, year_month, year_month_day)
(year_month_day_last, year_month_weekday, year_month_weekday_last):
Declare and later define.
(last_spec, last, __detail::__days_per_month)
(__detail::__days_per_month, __detail::__last_day): Define.
(January, February, March, April, May, June, July, August)
(September, October, November, December, Sunday, Monday, Tuesday)
(Wednesday, Thursday, Friday, Saturday): Define.
(weekday::operator[]): Define out-of-line.
(year_month_day::_S_from_days, year_month_day::M_days_since_epoch):
Likewise.
(year_month_day::year_month_day, year_month_day::ok): Likewise.
(__detail::__pow10, hh_mm_ss): Define.
(literals::chrono_literals::operator""d)
(literals::chrono_literals::operator""y): Define.
(is_am, is_pm, make12, make24): Define.
* testsuite/20_util/time_point/4.cc: New test.
* testsuite/std/time/day/1.cc: New test.
* testsuite/std/time/hh_mm_ss/1.cc: New test.
* testsuite/std/time/is_am/1.cc: New test.
* testsuite/std/time/is_pm/1.cc: New test.
* testsuite/std/time/make12/1.cc: New test.
* testsuite/std/time/make24/1.cc: New test.
* testsuite/std/time/month/1.cc: New test.
* testsuite/std/time/month_day/1.cc: New test.
* testsuite/std/time/month_day_last/1.cc: New test.
* testsuite/std/time/month_weekday/1.cc: New test.
* testsuite/std/time/month_weekday_last/1.cc: New test.
* testsuite/std/time/weekday/1.cc: New test.
* testsuite/std/time/weekday_indexed/1.cc: New test.
* testsuite/std/time/weekday_last/1.cc: New test.
* testsuite/std/time/year/1.cc: New test.
* testsuite/std/time/year_month/1.cc: New test.
* testsuite/std/time/year_month_day/1.cc: New test.
* testsuite/std/time/year_month_day_last/1.cc: New test.
* testsuite/std/time/year_month_weekday/1.cc: New test.
* testsuite/std/time/year_month_weekday_last/1.cc: New test.

22 files changed:
libstdc++-v3/include/std/chrono
libstdc++-v3/testsuite/20_util/time_point/4.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/day/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/hh_mm_ss/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/is_am/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/is_pm/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/make12/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/make24/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/month/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/month_day/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/month_day_last/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/month_weekday/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/month_weekday_last/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/weekday/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/weekday_indexed/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/weekday_last/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/year/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/year_month/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/year_month_day/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/year_month_day_last/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/year_month_weekday/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/std/time/year_month_weekday_last/1.cc [new file with mode: 0644]

index 6d78f32ac783005725e466ec035a58d9271a55f3..bf0d7e7af76638ee8fdfd84c21398d443174d262 100644 (file)
@@ -788,6 +788,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        time_since_epoch() const
        { return __d; }
 
+#if __cplusplus > 201703L
+       constexpr time_point&
+       operator++()
+       {
+         ++__d;
+         return *this;
+       }
+
+       constexpr time_point
+       operator++(int)
+       { return time_point{__d++}; }
+
+       constexpr time_point&
+       operator--()
+       {
+         --__d;
+         return *this;
+       }
+
+       constexpr time_point
+       operator--(int)
+       { return time_point{__d--}; }
+#endif
+
        // arithmetic
        _GLIBCXX17_CONSTEXPR time_point&
        operator+=(const duration& __dur)
@@ -1075,130 +1099,2013 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using local_time = time_point<local_t, _Duration>;
     using local_seconds = local_time<seconds>;
     using local_days = local_time<days>;
-#endif // C++20
 
-    // @}
-  } // namespace chrono
+    class utc_clock;
+    class tai_clock;
+    class gps_clock;
 
-#if __cplusplus > 201103L
+    template<typename _Duration>
+      using utc_time = time_point<utc_clock, _Duration>;
+    using utc_seconds = utc_time<seconds>;
 
-#define __cpp_lib_chrono_udls 201304
+    template<typename _Duration>
+      using tai_time = time_point<tai_clock, _Duration>;
+    using tai_seconds = tai_time<seconds>;
 
-  inline namespace literals
-  {
-  /** ISO C++ 2014  namespace for suffixes for duration literals.
-   *
-   * These suffixes can be used to create `chrono::duration` values with
-   * tick periods of hours, minutes, seconds, milliseconds, microseconds
-   * or nanoseconds. For example, `std::chrono::seconds(5)` can be written
-   * as `5s` after making the suffix visible in the current scope.
-   * The suffixes can be made visible by a using-directive or
-   * using-declaration such as:
-   *  - `using namespace std::chrono_literals;`
-   *  - `using namespace std::literals;`
-   *  - `using namespace std::chrono;`
-   *  - `using namespace std;`
-   *  - `using std::chrono_literals::operator""s;`
-   *
-   * The result of these suffixes on an integer literal is one of the
-   * standard typedefs such as `std::chrono::hours`.
-   * The result on a floating-point literal is a duration type with the
-   * specified tick period and an unspecified floating-point representation,
-   * for example `1.5e2ms` might be equivalent to
-   * `chrono::duration<long double, chrono::milli>(1.5e2)`.
-   *
-   * @ingroup chrono
-   */
-  inline namespace chrono_literals
-  {
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wliteral-suffix"
-    /// @cond undocumented
-    template<typename _Dur, char... _Digits>
-      constexpr _Dur __check_overflow()
+    template<typename _Duration>
+      using gps_time = time_point<gps_clock, _Duration>;
+    using gps_seconds = gps_time<seconds>;
+
+    template<> struct is_clock<utc_clock> : true_type { };
+    template<> struct is_clock<tai_clock> : true_type { };
+    template<> struct is_clock<gps_clock> : true_type { };
+
+    template<> inline constexpr bool is_clock_v<utc_clock> = true;
+    template<> inline constexpr bool is_clock_v<tai_clock> = true;
+    template<> inline constexpr bool is_clock_v<gps_clock> = true;
+
+    struct leap_second_info
+    {
+      bool is_leap_second;
+      seconds elapsed;
+    };
+
+    // CALENDRICAL TYPES
+
+    // CLASS DECLARATIONS
+    class day;
+    class month;
+    class year;
+    class weekday;
+    class weekday_indexed;
+    class weekday_last;
+    class month_day;
+    class month_day_last;
+    class month_weekday;
+    class month_weekday_last;
+    class year_month;
+    class year_month_day;
+    class year_month_day_last;
+    class year_month_weekday;
+    class year_month_weekday_last;
+
+    struct last_spec
+    {
+      explicit last_spec() = default;
+
+      friend constexpr month_day_last
+      operator/(int __m, last_spec) noexcept;
+
+      friend constexpr month_day_last
+      operator/(last_spec, int __m) noexcept;
+    };
+
+    inline constexpr last_spec last{};
+
+    namespace __detail
+    {
+      // Compute the remainder of the Euclidean division of __n divided by __d.
+      // Euclidean division truncates toward negative infinity and always
+      // produces a remainder in the range of [0,__d-1] (whereas standard
+      // division truncates toward zero and yields a nonpositive remainder
+      // for negative __n).
+      constexpr unsigned
+      __modulo(long long __n, unsigned __d)
       {
-       using _Val = __parse_int::_Parse_int<_Digits...>;
-       constexpr typename _Dur::rep __repval = _Val::value;
-       static_assert(__repval >= 0 && __repval == _Val::value,
-                     "literal value cannot be represented by duration type");
-       return _Dur(__repval);
+       if (__n >= 0)
+         return __n % __d;
+       else
+         return (__d + (__n % __d)) % __d;
       }
-    /// @endcond
 
-    /// Literal suffix for durations representing non-integer hours
-    constexpr chrono::duration<long double, ratio<3600,1>>
-    operator""h(long double __hours)
-    { return chrono::duration<long double, ratio<3600,1>>{__hours}; }
+      inline constexpr unsigned __days_per_month[12]
+       = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
 
-    /// Literal suffix for durations of type `std::chrono::hours`
-    template <char... _Digits>
-      constexpr chrono::hours
-      operator""h()
-      { return __check_overflow<chrono::hours, _Digits...>(); }
+      inline constexpr unsigned __last_day[12]
+       = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+    }
 
-    /// Literal suffix for durations representing non-integer minutes
-    constexpr chrono::duration<long double, ratio<60,1>>
-    operator""min(long double __mins)
-    { return chrono::duration<long double, ratio<60,1>>{__mins}; }
+    // DAY
 
-    /// Literal suffix for durations of type `std::chrono::minutes`
-    template <char... _Digits>
-      constexpr chrono::minutes
-      operator""min()
-      { return __check_overflow<chrono::minutes, _Digits...>(); }
+    class day
+    {
+    private:
+      unsigned char _M_d;
 
-    /// Literal suffix for durations representing non-integer seconds
-    constexpr chrono::duration<long double>
-    operator""s(long double __secs)
-    { return chrono::duration<long double>{__secs}; }
+    public:
+      day() = default;
 
-    /// Literal suffix for durations of type `std::chrono::seconds`
-    template <char... _Digits>
-      constexpr chrono::seconds
-      operator""s()
-      { return __check_overflow<chrono::seconds, _Digits...>(); }
+      explicit constexpr
+      day(unsigned __d) noexcept
+      : _M_d(__d)
+      { }
 
-    /// Literal suffix for durations representing non-integer milliseconds
-    constexpr chrono::duration<long double, milli>
-    operator""ms(long double __msecs)
-    { return chrono::duration<long double, milli>{__msecs}; }
+      constexpr day&
+      operator++() noexcept
+      {
+       ++_M_d;
+       return *this;
+      }
 
-    /// Literal suffix for durations of type `std::chrono::milliseconds`
-    template <char... _Digits>
-      constexpr chrono::milliseconds
-      operator""ms()
-      { return __check_overflow<chrono::milliseconds, _Digits...>(); }
+      constexpr day
+      operator++(int) noexcept
+      {
+       auto __ret = *this;
+       ++(*this);
+       return __ret;
+      }
 
-    /// Literal suffix for durations representing non-integer microseconds
-    constexpr chrono::duration<long double, micro>
-    operator""us(long double __usecs)
-    { return chrono::duration<long double, micro>{__usecs}; }
+      constexpr day&
+      operator--() noexcept
+      {
+       --_M_d;
+       return *this;
+      }
 
-    /// Literal suffix for durations of type `std::chrono::microseconds`
-    template <char... _Digits>
-      constexpr chrono::microseconds
-      operator""us()
-      { return __check_overflow<chrono::microseconds, _Digits...>(); }
+      constexpr day
+      operator--(int) noexcept
+      {
+       auto __ret = *this;
+       --(*this);
+       return __ret;
+      }
 
-    /// Literal suffix for durations representing non-integer nanoseconds
-    constexpr chrono::duration<long double, nano>
-    operator""ns(long double __nsecs)
-    { return chrono::duration<long double, nano>{__nsecs}; }
+      constexpr day&
+      operator+=(const days& __d) noexcept
+      {
+       *this = *this + __d;
+       return *this;
+      }
 
-    /// Literal suffix for durations of type `std::chrono::nanoseconds`
-    template <char... _Digits>
-      constexpr chrono::nanoseconds
-      operator""ns()
-      { return __check_overflow<chrono::nanoseconds, _Digits...>(); }
+      constexpr day&
+      operator-=(const days& __d) noexcept
+      {
+       *this = *this - __d;
+       return *this;
+      }
 
-#pragma GCC diagnostic pop
-  } // inline namespace chrono_literals
-  } // inline namespace literals
+      constexpr explicit
+      operator unsigned() const noexcept
+      { return _M_d; }
 
-  namespace chrono
-  {
-    using namespace literals::chrono_literals;
-  } // namespace chrono
+      constexpr bool
+      ok() const noexcept
+      { return 1 <= _M_d && _M_d <= 31; }
+
+      friend constexpr bool
+      operator==(const day& __x, const day& __y) noexcept
+      { return unsigned{__x} == unsigned{__y}; }
+
+      friend constexpr strong_ordering
+      operator<=>(const day& __x, const day& __y) noexcept
+      { return unsigned{__x} <=> unsigned{__y}; }
+
+      friend constexpr day
+      operator+(const day& __x, const days& __y) noexcept
+      { return day(unsigned{__x} + __y.count()); }
+
+      friend constexpr day
+      operator+(const days& __x, const day& __y) noexcept
+      { return __y + __x; }
+
+      friend constexpr day
+      operator-(const day& __x, const days& __y) noexcept
+      { return __x + -__y; }
+
+      friend constexpr days
+      operator-(const day& __x, const day& __y) noexcept
+      { return days{int(unsigned{__x}) - int(unsigned{__y})}; }
+
+      friend constexpr month_day
+      operator/(const month& __m, const day& __d) noexcept;
+
+      friend constexpr month_day
+      operator/(int __m, const day& __d) noexcept;
+
+      friend constexpr month_day
+      operator/(const day& __d, const month& __m) noexcept;
+
+      friend constexpr month_day
+      operator/(const day& __d, int __m) noexcept;
+
+      friend constexpr year_month_day
+      operator/(const year_month& __ym, const day& __d) noexcept;
+
+      // TODO: Implement operator<<, to_stream, from_stream.
+    };
+
+    // MONTH
+
+    class month
+    {
+    private:
+      unsigned char _M_m;
+
+    public:
+      month() = default;
+
+      explicit constexpr
+      month(unsigned __m) noexcept
+      : _M_m(__m)
+      { }
+
+      constexpr month&
+      operator++() noexcept
+      {
+       *this += months{1};
+       return *this;
+      }
+
+      constexpr month
+      operator++(int) noexcept
+      {
+       auto __ret = *this;
+       ++(*this);
+       return __ret;
+      }
+
+      constexpr month&
+      operator--() noexcept
+      {
+       *this -= months{1};
+       return *this;
+      }
+
+      constexpr month
+      operator--(int) noexcept
+      {
+       auto __ret = *this;
+       --(*this);
+       return __ret;
+      }
+
+      constexpr month&
+      operator+=(const months& __m) noexcept
+      {
+       *this = *this + __m;
+       return *this;
+      }
+
+      constexpr month&
+      operator-=(const months& __m) noexcept
+      {
+       *this = *this - __m;
+       return *this;
+      }
+
+      explicit constexpr
+      operator unsigned() const noexcept
+      { return _M_m; }
+
+      constexpr bool
+      ok() const noexcept
+      { return 1 <= _M_m && _M_m <= 12; }
+
+      friend constexpr bool
+      operator==(const month& __x, const month& __y) noexcept
+      { return unsigned{__x} == unsigned{__y}; }
+
+      friend constexpr strong_ordering
+      operator<=>(const month& __x, const month& __y) noexcept
+      { return unsigned{__x} <=> unsigned{__y}; }
+
+      friend constexpr month
+      operator+(const month& __x, const months& __y) noexcept
+      {
+       auto __n = static_cast<long long>(unsigned{__x}) + (__y.count() - 1);
+       return month{__detail::__modulo(__n, 12) + 1};
+      }
+
+      friend constexpr month
+      operator+(const months& __x,  const month& __y) noexcept
+      { return __y + __x; }
+
+      friend constexpr month
+      operator-(const month& __x, const months& __y) noexcept
+      { return __x + -__y; }
+
+      friend constexpr months
+      operator-(const month& __x,  const month& __y) noexcept
+      {
+       const auto __dm = int(unsigned(__x)) - int(unsigned(__y));
+       return months{__dm < 0 ? 12 + __dm : __dm};
+      }
+
+      friend constexpr year_month
+      operator/(const year& __y, const month& __m) noexcept;
+
+      friend constexpr month_day
+      operator/(const month& __m, int __d) noexcept;
+
+      friend constexpr month_day_last
+      operator/(const month& __m, last_spec) noexcept;
+
+      friend constexpr month_day_last
+      operator/(last_spec, const month& __m) noexcept;
+
+      friend constexpr month_weekday
+      operator/(const month& __m, const weekday_indexed& __wdi) noexcept;
+
+      friend constexpr month_weekday
+      operator/(const weekday_indexed& __wdi, const month& __m) noexcept;
+
+      friend constexpr month_weekday_last
+      operator/(const month& __m, const weekday_last& __wdl) noexcept;
+
+      friend constexpr month_weekday_last
+      operator/(const weekday_last& __wdl, const month& __m) noexcept;
+
+      // TODO: Implement operator<<, to_stream, from_stream.
+    };
+
+    inline constexpr month January{1};
+    inline constexpr month February{2};
+    inline constexpr month March{3};
+    inline constexpr month April{4};
+    inline constexpr month May{5};
+    inline constexpr month June{6};
+    inline constexpr month July{7};
+    inline constexpr month August{8};
+    inline constexpr month September{9};
+    inline constexpr month October{10};
+    inline constexpr month November{11};
+    inline constexpr month December{12};
+
+    // YEAR
+
+    class year
+    {
+    private:
+      short _M_y;
+
+    public:
+      year() = default;
+
+      explicit constexpr
+      year(int __y) noexcept
+      : _M_y{static_cast<short>(__y)}
+      { }
+
+      static constexpr year
+      min() noexcept
+      { return year{-32767}; }
+
+      static constexpr year
+      max() noexcept
+      { return year{32767}; }
+
+      constexpr year&
+      operator++() noexcept
+      {
+       ++_M_y;
+       return *this;
+      }
+
+      constexpr year
+      operator++(int) noexcept
+      {
+       auto __ret = *this;
+       ++(*this);
+       return __ret;
+      }
+
+      constexpr year&
+      operator--() noexcept
+      {
+       --_M_y;
+       return *this;
+      }
+
+      constexpr year
+      operator--(int) noexcept
+      {
+       auto __ret = *this;
+       --(*this);
+       return __ret;
+      }
+
+      constexpr year&
+      operator+=(const years& __y) noexcept
+      {
+       *this = *this + __y;
+       return *this;
+      }
+
+      constexpr year&
+      operator-=(const years& __y) noexcept
+      {
+       *this = *this - __y;
+       return *this;
+      }
+
+      constexpr year
+      operator+() const noexcept
+      { return *this; }
+
+      constexpr year
+      operator-() const noexcept
+      { return year{-_M_y}; }
+
+      constexpr bool
+      is_leap() const noexcept
+      { return _M_y % 4 == 0 && (_M_y % 100 != 0 || _M_y % 400 == 0); }
+
+      explicit constexpr
+      operator int() const noexcept
+      { return _M_y; }
+
+      constexpr bool
+      ok() const noexcept
+      { return min()._M_y <= _M_y && _M_y <= max()._M_y; }
+
+      friend constexpr bool
+      operator==(const year& __x, const year& __y) noexcept
+      { return int{__x} == int{__y}; }
+
+      friend constexpr strong_ordering
+      operator<=>(const year& __x, const year& __y) noexcept
+      { return int{__x} <=> int{__y}; }
+
+      friend constexpr year
+      operator+(const year& __x, const years& __y) noexcept
+      { return year{int{__x} + __y.count()}; }
+
+      friend constexpr year
+      operator+(const years& __x, const year& __y) noexcept
+      { return __y + __x; }
+
+      friend constexpr year
+      operator-(const year& __x, const years& __y) noexcept
+      { return __x + -__y; }
+
+      friend constexpr years
+      operator-(const year& __x, const year& __y) noexcept
+      { return years{int{__x} - int{__y}}; }
+
+      friend constexpr year_month
+      operator/(const year& __y, int __m) noexcept;
+
+      friend constexpr year_month_day
+      operator/(const year& __y, const month_day& __md) noexcept;
+
+      friend constexpr year_month_day
+      operator/(const month_day& __md, const year& __y) noexcept;
+
+      friend constexpr year_month_day_last
+      operator/(const year& __y, const month_day_last& __mdl) noexcept;
+
+      friend constexpr year_month_day_last
+      operator/(const month_day_last& __mdl, const year& __y) noexcept;
+
+      friend constexpr year_month_weekday
+      operator/(const year& __y, const month_weekday& __mwd) noexcept;
+
+      friend constexpr year_month_weekday
+      operator/(const month_weekday& __mwd, const year& __y) noexcept;
+
+      friend constexpr year_month_weekday_last
+      operator/(const year& __y, const month_weekday_last& __mwdl) noexcept;
+
+      friend constexpr year_month_weekday_last
+      operator/(const month_weekday_last& __mwdl, const year& __y) noexcept;
+
+      // TODO: Implement operator<<, to_stream, from_stream.
+    };
+
+    // WEEKDAY
+
+    class weekday
+    {
+    private:
+      unsigned char _M_wd;
+
+      static constexpr weekday
+      _S_from_days(const days& __d)
+      {
+       auto __n = __d.count();
+       return weekday(__n >= -4 ? (__n + 4) % 7 : (__n + 5) % 7 + 6);
+      }
+
+    public:
+      weekday() = default;
+
+      explicit constexpr
+      weekday(unsigned __wd) noexcept
+      : _M_wd(__wd == 7 ? 0 : __wd) // __wd % 7 ?
+      { }
+
+      constexpr
+      weekday(const sys_days& __dp) noexcept
+      : weekday{_S_from_days(__dp.time_since_epoch())}
+      { }
+
+      explicit constexpr
+      weekday(const local_days& __dp) noexcept
+      : weekday{sys_days{__dp.time_since_epoch()}}
+      { }
+
+      constexpr weekday&
+      operator++() noexcept
+      {
+       *this += days{1};
+       return *this;
+      }
+
+      constexpr weekday
+      operator++(int) noexcept
+      {
+       auto __ret = *this;
+       ++(*this);
+       return __ret;
+      }
+
+      constexpr weekday&
+      operator--() noexcept
+      {
+       *this -= days{1};
+       return *this;
+      }
+
+      constexpr weekday
+      operator--(int) noexcept
+      {
+       auto __ret = *this;
+       --(*this);
+       return __ret;
+      }
+
+      constexpr weekday&
+      operator+=(const days& __d) noexcept
+      {
+       *this = *this + __d;
+       return *this;
+      }
+
+      constexpr weekday&
+      operator-=(const days& __d) noexcept
+      {
+       *this = *this - __d;
+       return *this;
+      }
+
+      constexpr unsigned
+      c_encoding() const noexcept
+      { return _M_wd; }
+
+      constexpr unsigned
+      iso_encoding() const noexcept
+      { return _M_wd == 0u ? 7u : _M_wd; }
+
+      constexpr bool
+      ok() const noexcept
+      { return _M_wd <= 6; }
+
+      constexpr weekday_indexed
+      operator[](unsigned __index) const noexcept;
+
+      constexpr weekday_last
+      operator[](last_spec) const noexcept;
+
+      friend constexpr bool
+      operator==(const weekday& __x, const weekday& __y) noexcept
+      { return __x._M_wd == __y._M_wd; }
+
+      friend constexpr weekday
+      operator+(const weekday& __x, const days& __y) noexcept
+      {
+       auto __n = static_cast<long long>(__x._M_wd) + __y.count();
+       return weekday{__detail::__modulo(__n, 7)};
+      }
+
+      friend constexpr weekday
+      operator+(const days& __x, const weekday& __y) noexcept
+      { return __y + __x; }
+
+      friend constexpr weekday
+      operator-(const weekday& __x, const days& __y) noexcept
+      { return __x + -__y; }
+
+      friend constexpr days
+      operator-(const weekday& __x, const weekday& __y) noexcept
+      {
+       auto __n = static_cast<long long>(__x._M_wd) - __y._M_wd;
+       return days{__detail::__modulo(__n, 7)};
+      }
+
+      // TODO: operator<<, from_stream.
+    };
+
+    inline constexpr weekday Sunday{0};
+    inline constexpr weekday Monday{1};
+    inline constexpr weekday Tuesday{2};
+    inline constexpr weekday Wednesday{3};
+    inline constexpr weekday Thursday{4};
+    inline constexpr weekday Friday{5};
+    inline constexpr weekday Saturday{6};
+
+    // WEEKDAY_INDEXED
+
+    class weekday_indexed
+    {
+    private:
+      chrono::weekday _M_wd;
+      unsigned char _M_index;
+
+    public:
+      weekday_indexed() = default;
+
+      constexpr
+      weekday_indexed(const chrono::weekday& __wd, unsigned __index) noexcept
+      : _M_wd(__wd), _M_index(__index)
+      { }
+
+      constexpr chrono::weekday
+      weekday() const noexcept
+      { return _M_wd; }
+
+      constexpr unsigned
+      index() const noexcept
+      { return _M_index; };
+
+      constexpr bool
+      ok() const noexcept
+      { return _M_wd.ok() && 1 <= _M_index && _M_index <= 5; }
+
+      friend constexpr bool
+      operator==(const weekday_indexed& __x, const weekday_indexed& __y) noexcept
+      { return __x.weekday() == __y.weekday() && __x.index() == __y.index(); }
+
+      friend constexpr month_weekday
+      operator/(const month& __m, const weekday_indexed& __wdi) noexcept;
+
+      friend constexpr month_weekday
+      operator/(int __m, const weekday_indexed& __wdi) noexcept;
+
+      friend constexpr month_weekday
+      operator/(const weekday_indexed& __wdi, const month& __m) noexcept;
+
+      friend constexpr month_weekday
+      operator/(const weekday_indexed& __wdi, int __m) noexcept;
+
+      friend constexpr year_month_weekday
+      operator/(const year_month& __ym, const weekday_indexed& __wdi) noexcept;
+
+      // TODO: Implement operator<<.
+    };
+
+    constexpr weekday_indexed
+    weekday::operator[](unsigned __index) const noexcept
+    { return {*this, __index}; }
+
+    // WEEKDAY_LAST
+
+    class weekday_last
+    {
+    private:
+      chrono::weekday _M_wd;
+
+    public:
+      explicit constexpr
+      weekday_last(const chrono::weekday& __wd) noexcept
+      : _M_wd{__wd}
+      { }
+
+      constexpr chrono::weekday
+      weekday() const noexcept
+      { return _M_wd; }
+
+      constexpr bool
+      ok() const noexcept
+      { return _M_wd.ok(); }
+
+      friend constexpr bool
+      operator==(const weekday_last& __x, const weekday_last& __y) noexcept
+      { return __x.weekday() == __y.weekday(); }
+
+      friend constexpr month_weekday_last
+      operator/(int __m, const weekday_last& __wdl) noexcept;
+
+      friend constexpr month_weekday_last
+      operator/(const weekday_last& __wdl, int __m) noexcept;
+
+      friend constexpr year_month_weekday_last
+      operator/(const year_month& __ym, const weekday_last& __wdl) noexcept;
+
+      // TODO: Implement operator<<.
+    };
+
+    constexpr weekday_last
+    weekday::operator[](last_spec) const noexcept
+    { return weekday_last{*this}; }
+
+    // MONTH_DAY
+
+    class month_day
+    {
+    private:
+      chrono::month _M_m;
+      chrono::day _M_d;
+
+    public:
+      month_day() = default;
+
+      constexpr
+      month_day(const chrono::month& __m, const chrono::day& __d) noexcept
+      : _M_m{__m}, _M_d{__d}
+      { }
+
+      constexpr chrono::month
+      month() const noexcept
+      { return _M_m; }
+
+      constexpr chrono::day
+      day() const noexcept
+      { return _M_d; }
+
+      constexpr bool
+      ok() const noexcept
+      {
+       return _M_m.ok()
+         && 1u <= unsigned(_M_d)
+         && unsigned(_M_d) <= __detail::__days_per_month[unsigned(_M_m) - 1];
+      }
+
+      friend constexpr bool
+      operator==(const month_day& __x, const month_day& __y) noexcept
+      { return __x.month() == __y.month() && __x.day() == __y.day(); }
+
+      friend constexpr strong_ordering
+      operator<=>(const month_day& __x, const month_day& __y) noexcept
+       = default;
+
+      friend constexpr month_day
+      operator/(const chrono::month& __m, const chrono::day& __d) noexcept
+      { return {__m, __d}; }
+
+      friend constexpr month_day
+      operator/(const chrono::month& __m, int __d) noexcept
+      { return {__m, chrono::day(unsigned(__d))}; }
+
+      friend constexpr month_day
+      operator/(int __m, const chrono::day& __d) noexcept
+      { return {chrono::month(unsigned(__m)), __d}; }
+
+      friend constexpr month_day
+      operator/(const chrono::day& __d, const chrono::month& __m) noexcept
+      { return {__m, __d}; }
+
+      friend constexpr month_day
+      operator/(const chrono::day& __d, int __m) noexcept
+      { return {chrono::month(unsigned(__m)), __d}; }
+
+      friend constexpr year_month_day
+      operator/(int __y, const month_day& __md) noexcept;
+
+      friend constexpr year_month_day
+      operator/(const month_day& __md, int __y) noexcept;
+
+      // TODO: Implement operator<<, from_stream.
+    };
+
+    // MONTH_DAY_LAST
+
+    class month_day_last
+    {
+    private:
+      chrono::month _M_m;
+
+    public:
+      explicit constexpr
+      month_day_last(const chrono::month& __m) noexcept
+      : _M_m{__m}
+      { }
+
+      constexpr chrono::month
+      month() const noexcept
+      { return _M_m; }
+
+      constexpr bool
+      ok() const noexcept
+      { return _M_m.ok(); }
+
+      friend constexpr bool
+      operator==(const month_day_last& __x, const month_day_last& __y) noexcept
+      { return __x.month() == __y.month(); }
+
+      friend constexpr strong_ordering
+      operator<=>(const month_day_last& __x, const month_day_last& __y) noexcept
+       = default;
+
+      friend constexpr month_day_last
+      operator/(const chrono::month& __m, last_spec) noexcept
+      { return month_day_last{__m}; }
+
+      friend constexpr month_day_last
+      operator/(int __m, last_spec) noexcept
+      { return chrono::month(unsigned(__m)) / last; }
+
+      friend constexpr month_day_last
+      operator/(last_spec, const chrono::month& __m) noexcept
+      { return __m / last; }
+
+      friend constexpr month_day_last
+      operator/(last_spec, int __m) noexcept
+      { return __m / last; }
+
+      friend constexpr year_month_day_last
+      operator/(int __y, const month_day_last& __mdl) noexcept;
+
+      friend constexpr year_month_day_last
+      operator/(const month_day_last& __mdl, int __y) noexcept;
+
+      // TODO: Implement operator<<.
+    };
+
+    // MONTH_WEEKDAY
+
+    class month_weekday
+    {
+    private:
+      chrono::month _M_m;
+      chrono::weekday_indexed _M_wdi;
+
+    public:
+      constexpr
+      month_weekday(const chrono::month& __m,
+                   const chrono::weekday_indexed& __wdi) noexcept
+      : _M_m{__m}, _M_wdi{__wdi}
+      { }
+
+      constexpr chrono::month
+      month() const noexcept
+      { return _M_m; }
+
+      constexpr chrono::weekday_indexed
+      weekday_indexed() const noexcept
+      { return _M_wdi; }
+
+      constexpr bool
+      ok() const noexcept
+      { return _M_m.ok() && _M_wdi.ok(); }
+
+      friend constexpr bool
+      operator==(const month_weekday& __x, const month_weekday& __y) noexcept
+      {
+       return __x.month() == __y.month()
+         && __x.weekday_indexed() == __y.weekday_indexed();
+      }
+
+      friend constexpr month_weekday
+      operator/(const chrono::month& __m,
+               const chrono::weekday_indexed& __wdi) noexcept
+      { return {__m, __wdi}; }
+
+      friend constexpr month_weekday
+      operator/(int __m, const chrono::weekday_indexed& __wdi) noexcept
+      { return chrono::month(unsigned(__m)) / __wdi; }
+
+      friend constexpr month_weekday
+      operator/(const chrono::weekday_indexed& __wdi,
+               const chrono::month& __m) noexcept
+      { return __m / __wdi; }
+
+      friend constexpr month_weekday
+      operator/(const chrono::weekday_indexed& __wdi, int __m) noexcept
+      { return __m / __wdi; }
+
+      friend constexpr year_month_weekday
+      operator/(int __y, const month_weekday& __mwd) noexcept;
+
+      friend constexpr year_month_weekday
+      operator/(const month_weekday& __mwd, int __y) noexcept;
+
+      // TODO: Implement operator<<.
+    };
+
+    // MONTH_WEEKDAY_LAST
+
+    class month_weekday_last
+    {
+    private:
+      chrono::month _M_m;
+      chrono::weekday_last _M_wdl;
+
+    public:
+      constexpr
+      month_weekday_last(const chrono::month& __m,
+                        const chrono::weekday_last& __wdl) noexcept
+      :_M_m{__m}, _M_wdl{__wdl}
+      { }
+
+      constexpr chrono::month
+      month() const noexcept
+      { return _M_m; }
+
+      constexpr chrono::weekday_last
+      weekday_last() const noexcept
+      { return _M_wdl; }
+
+      constexpr bool
+      ok() const noexcept
+      { return _M_m.ok() && _M_wdl.ok(); }
+
+      friend constexpr bool
+      operator==(const month_weekday_last& __x,
+                const month_weekday_last& __y) noexcept
+      {
+       return __x.month() == __y.month()
+         && __x.weekday_last() == __y.weekday_last();
+      }
+
+      friend constexpr month_weekday_last
+      operator/(const chrono::month& __m,
+               const chrono::weekday_last& __wdl) noexcept
+      { return {__m, __wdl}; }
+
+      friend constexpr month_weekday_last
+      operator/(int __m, const chrono::weekday_last& __wdl) noexcept
+      { return chrono::month(unsigned(__m)) / __wdl; }
+
+      friend constexpr month_weekday_last
+      operator/(const chrono::weekday_last& __wdl,
+               const chrono::month& __m) noexcept
+      { return __m / __wdl; }
+
+      friend constexpr month_weekday_last
+      operator/(const chrono::weekday_last& __wdl, int __m) noexcept
+      { return chrono::month(unsigned(__m)) / __wdl; }
+
+      friend constexpr year_month_weekday_last
+      operator/(int __y, const month_weekday_last& __mwdl) noexcept;
+
+      friend constexpr year_month_weekday_last
+      operator/(const month_weekday_last& __mwdl, int __y) noexcept;
+
+      // TODO: Implement operator<<.
+    };
+
+    // YEAR_MONTH
+
+    class year_month
+    {
+    private:
+      chrono::year _M_y;
+      chrono::month _M_m;
+
+    public:
+      year_month() = default;
+
+      constexpr
+      year_month(const chrono::year& __y, const chrono::month& __m) noexcept
+      : _M_y{__y}, _M_m{__m}
+      { }
+
+      constexpr chrono::year
+      year() const noexcept
+      { return _M_y; }
+
+      constexpr chrono::month
+      month() const noexcept
+      { return _M_m; }
+
+      constexpr year_month&
+      operator+=(const months& __dm) noexcept
+      {
+       *this = *this + __dm;
+       return *this;
+      }
+
+      constexpr year_month&
+      operator-=(const months& __dm) noexcept
+      {
+       *this = *this - __dm;
+       return *this;
+      }
+
+      constexpr year_month&
+      operator+=(const years& __dy)  noexcept
+      {
+       *this = *this + __dy;
+       return *this;
+      }
+
+      constexpr year_month&
+      operator-=(const years& __dy)  noexcept
+      {
+       *this = *this - __dy;
+       return *this;
+      }
+
+      constexpr bool
+      ok() const noexcept
+      { return _M_y.ok() && _M_m.ok(); }
+
+      friend constexpr bool
+      operator==(const year_month& __x, const year_month& __y) noexcept
+      { return __x.year() == __y.year() && __x.month() == __y.month(); }
+
+      friend constexpr strong_ordering
+      operator<=>(const year_month& __x, const year_month& __y) noexcept
+       = default;
+
+      friend constexpr year_month
+      operator+(const year_month& __ym, const months& __dm) noexcept
+      {
+       // TODO: Optimize?
+       auto __m = __ym.month() + __dm;
+       auto __i = unsigned{__ym.month()} - 1 + __dm.count();
+       auto __y = (__i < 0
+                   ? __ym.year() + years{(__i - 11) / 12}
+                   : __ym.year() + years{__i / 12});
+       return __y / __m;
+      }
+
+      friend constexpr year_month
+      operator+(const months& __dm, const year_month& __ym) noexcept
+      { return __ym + __dm; }
+
+      friend constexpr year_month
+      operator-(const year_month& __ym, const months& __dm) noexcept
+      { return __ym + -__dm; }
+
+      friend constexpr months
+      operator-(const year_month& __x, const year_month& __y) noexcept
+      {
+       return (__x.year() - __y.year()
+               + months{static_cast<int>(unsigned{__x.month()})
+                        - static_cast<int>(unsigned{__y.month()})});
+      }
+
+      friend constexpr year_month
+      operator+(const year_month& __ym, const years& __dy) noexcept
+      { return (__ym.year() + __dy) / __ym.month(); }
+
+      friend constexpr year_month
+      operator+(const years& __dy, const year_month& __ym) noexcept
+      { return __ym + __dy; }
+
+      friend constexpr year_month
+      operator-(const year_month& __ym, const years& __dy) noexcept
+      { return __ym + -__dy; }
+
+      friend constexpr year_month
+      operator/(const chrono::year& __y, const chrono::month& __m) noexcept
+      { return {__y, __m}; }
+
+      friend constexpr year_month
+      operator/(const chrono::year& __y, int __m) noexcept
+      { return {__y, chrono::month(unsigned(__m))}; }
+
+      friend constexpr year_month_day
+      operator/(const year_month& __ym, int __d) noexcept;
+
+      friend constexpr year_month_day_last
+      operator/(const year_month& __ym, last_spec) noexcept;
+
+      // TODO: Implement operator<<, from_stream.
+    };
+
+    // YEAR_MONTH_DAY
+
+    class year_month_day
+    {
+    private:
+      chrono::year _M_y;
+      chrono::month _M_m;
+      chrono::day _M_d;
+
+      static constexpr year_month_day _S_from_days(const days& __dp) noexcept;
+
+      constexpr days _M_days_since_epoch() const noexcept;
+
+    public:
+      year_month_day() = default;
+
+      constexpr
+      year_month_day(const chrono::year& __y, const chrono::month& __m,
+                    const chrono::day& __d) noexcept
+      : _M_y{__y}, _M_m{__m}, _M_d{__d}
+      { }
+
+      constexpr
+      year_month_day(const year_month_day_last& __ymdl) noexcept;
+
+      constexpr
+      year_month_day(const sys_days& __dp) noexcept
+      : year_month_day(_S_from_days(__dp.time_since_epoch()))
+      { }
+
+      explicit constexpr
+      year_month_day(const local_days& __dp) noexcept
+      : year_month_day(sys_days{__dp.time_since_epoch()})
+      { }
+
+      constexpr year_month_day&
+      operator+=(const months& __m) noexcept
+      {
+       *this = *this + __m;
+       return *this;
+      }
+
+      constexpr year_month_day&
+      operator-=(const months& __m) noexcept
+      {
+       *this = *this - __m;
+       return *this;
+      }
+
+      constexpr year_month_day&
+      operator+=(const years& __y) noexcept
+      {
+       *this = *this + __y;
+       return *this;
+      }
+
+      constexpr year_month_day&
+      operator-=(const years& __y) noexcept
+      {
+       *this = *this - __y;
+       return *this;
+      }
+
+      constexpr chrono::year
+      year() const noexcept
+      { return _M_y; }
+
+      constexpr chrono::month
+      month() const noexcept
+      { return _M_m; }
+
+      constexpr chrono::day
+      day() const noexcept
+      { return _M_d; }
+
+      constexpr
+      operator sys_days() const noexcept
+      { return sys_days{_M_days_since_epoch()}; }
+
+      explicit constexpr
+      operator local_days() const noexcept
+      { return local_days{sys_days{*this}.time_since_epoch()}; }
+
+      constexpr bool ok() const noexcept;
+
+      friend constexpr bool
+      operator==(const year_month_day& __x, const year_month_day& __y) noexcept
+      {
+       return __x.year() == __y.year()
+         && __x.month() == __y.month()
+         && __x.day() == __y.day();
+      }
+
+      friend constexpr strong_ordering
+      operator<=>(const year_month_day& __x, const year_month_day& __y) noexcept
+       = default;
+
+      friend constexpr year_month_day
+      operator+(const year_month_day& __ymd, const months& __dm) noexcept
+      { return (__ymd.year() / __ymd.month() + __dm) / __ymd.day(); }
+
+      friend constexpr year_month_day
+      operator+(const months& __dm, const year_month_day& __ymd) noexcept
+      { return __ymd + __dm; }
+
+      friend constexpr year_month_day
+      operator+(const year_month_day& __ymd, const years& __dy) noexcept
+      { return (__ymd.year() + __dy) / __ymd.month() / __ymd.day(); }
+
+      friend constexpr year_month_day
+      operator+(const years& __dy, const year_month_day& __ymd) noexcept
+      { return __ymd + __dy; }
+
+      friend constexpr year_month_day
+      operator-(const year_month_day& __ymd, const months& __dm) noexcept
+      { return __ymd + -__dm; }
+
+      friend constexpr year_month_day
+      operator-(const year_month_day& __ymd, const years& __dy) noexcept
+      { return __ymd + -__dy; }
+
+      friend constexpr year_month_day
+      operator/(const year_month& __ym, const chrono::day& __d) noexcept
+      { return {__ym.year(), __ym.month(), __d}; }
+
+      friend constexpr year_month_day
+      operator/(const year_month& __ym, int __d) noexcept
+      { return __ym / chrono::day{unsigned(__d)}; }
+
+      friend constexpr year_month_day
+      operator/(const chrono::year& __y, const month_day& __md) noexcept
+      { return __y / __md.month() / __md.day(); }
+
+      friend constexpr year_month_day
+      operator/(int __y, const month_day& __md) noexcept
+      { return chrono::year{__y} / __md; }
+
+      friend constexpr year_month_day
+      operator/(const month_day& __md, const chrono::year& __y) noexcept
+      { return __y / __md; }
+
+      friend constexpr year_month_day
+      operator/(const month_day& __md, int __y) noexcept
+      { return chrono::year(__y) / __md; }
+
+      // TODO: Implement operator<<, from_stream.
+    };
+
+    // Construct from days since 1970/01/01. Magic.
+    constexpr year_month_day
+    year_month_day::_S_from_days(const days& __dp) noexcept
+    {
+      const auto __z = __dp.count() + 719468;
+      const auto __era = (__z >= 0 ? __z : __z - 146096) / 146097;
+      const auto __doe = static_cast<unsigned>(__z - __era * 146097);
+      const auto __yoe
+       = (__doe - __doe / 1460 + __doe / 36524 - __doe / 146096) / 365;
+      const auto __y = static_cast<days::rep>(__yoe) + __era * 400;
+      const auto __doy = __doe - (365 * __yoe + __yoe / 4 - __yoe / 100);
+      const auto __mp = (5 * __doy + 2) / 153;
+      const auto __d = __doy - (153 * __mp + 2) / 5 + 1;
+      const auto __m = __mp < 10 ? __mp + 3 : __mp - 9;
+      return year_month_day{chrono::year(__y + (__m <= 2)),
+                           chrono::month(__m), chrono::day(__d)};
+    }
+
+    // Days since 1970/01/01. Magic.
+    constexpr days
+    year_month_day::_M_days_since_epoch() const noexcept
+    {
+      const auto __y = static_cast<int>(_M_y) - (_M_m <= February);
+      const auto __m = static_cast<unsigned>(_M_m);
+      const auto __d = static_cast<unsigned>(_M_d);
+      const auto __era = (__y >= 0 ? __y : __y - 399) / 400;
+      // Year of "era" [0, 399].
+      const auto __yoe = static_cast<unsigned>(__y - __era * 400);
+      // Day of year [0, 365].
+      const auto __doy = (153 * (__m > 2 ? __m - 3 : __m + 9) + 2) / 5 + __d - 1;
+      // Day of "era" [0, 146096].
+      const auto __doe = __yoe * 365 + __yoe / 4 - __yoe / 100 + __doy;
+      const auto __days = __era * 146097 + static_cast<int>(__doe) - 719468;
+      return days{__days};
+    }
+
+    // YEAR_MONTH_DAY_LAST
+
+    class year_month_day_last
+    {
+    private:
+      chrono::year _M_y;
+      chrono::month_day_last _M_mdl;
+
+    public:
+      constexpr
+      year_month_day_last(const chrono::year& __y,
+                         const chrono::month_day_last& __mdl) noexcept
+      : _M_y{__y}, _M_mdl{__mdl}
+      { }
+
+      constexpr year_month_day_last&
+      operator+=(const months& __m) noexcept
+      {
+       *this = *this + __m;
+       return *this;
+      }
+
+      constexpr year_month_day_last&
+      operator-=(const months& __m) noexcept
+      {
+       *this = *this - __m;
+       return *this;
+      }
+
+      constexpr year_month_day_last&
+      operator+=(const years& __y)  noexcept
+      {
+       *this = *this + __y;
+       return *this;
+      }
+
+      constexpr year_month_day_last&
+      operator-=(const years& __y)  noexcept
+      {
+       *this = *this - __y;
+       return *this;
+      }
+
+      constexpr chrono::year
+      year() const noexcept
+      { return _M_y; }
+
+      constexpr chrono::month
+      month() const noexcept
+      { return _M_mdl.month(); }
+
+      constexpr chrono::month_day_last
+      month_day_last() const noexcept
+      { return _M_mdl; }
+
+      // Return A day representing the last day of this year, month pair.
+      constexpr chrono::day
+      day() const noexcept
+      {
+       if (!_M_mdl.ok() || (month() == February && _M_y.is_leap()))
+         return chrono::day{29};
+       return chrono::day{__detail::__last_day[unsigned(month()) - 1]};
+      }
+
+      constexpr
+      operator sys_days() const noexcept
+      { return sys_days{year() / month() / day()}; }
+
+      explicit constexpr
+      operator local_days() const noexcept
+      { return local_days{sys_days{*this}.time_since_epoch()}; }
+
+      constexpr bool
+      ok() const noexcept
+      { return _M_y.ok() && _M_mdl.ok(); }
+
+      friend constexpr bool
+      operator==(const year_month_day_last& __x,
+                const year_month_day_last& __y) noexcept
+      {
+       return __x.year() == __y.year()
+         && __x.month_day_last() == __y.month_day_last();
+      }
+
+      friend constexpr strong_ordering
+      operator<=>(const year_month_day_last& __x,
+                 const year_month_day_last& __y) noexcept
+       = default;
+
+      friend constexpr year_month_day_last
+      operator+(const year_month_day_last& __ymdl,
+               const months& __dm) noexcept
+      { return (__ymdl.year() / __ymdl.month() + __dm) / last; }
+
+      friend constexpr year_month_day_last
+      operator+(const months& __dm,
+               const year_month_day_last& __ymdl) noexcept
+      { return __ymdl + __dm; }
+
+      friend constexpr year_month_day_last
+      operator-(const year_month_day_last& __ymdl,
+               const months& __dm) noexcept
+      { return __ymdl + -__dm; }
+
+      friend constexpr year_month_day_last
+      operator+(const year_month_day_last& __ymdl,
+               const years& __dy) noexcept
+      { return {__ymdl.year() + __dy, __ymdl.month_day_last()}; }
+
+      friend constexpr year_month_day_last
+      operator+(const years& __dy,
+               const year_month_day_last& __ymdl) noexcept
+      { return __ymdl + __dy; }
+
+      friend constexpr year_month_day_last
+      operator-(const year_month_day_last& __ymdl,
+               const years& __dy) noexcept
+      { return __ymdl + -__dy; }
+
+      friend constexpr year_month_day_last
+      operator/(const year_month& __ym, last_spec) noexcept
+      { return {__ym.year(), chrono::month_day_last{__ym.month()}}; }
+
+      friend constexpr year_month_day_last
+      operator/(const chrono::year& __y,
+               const chrono::month_day_last& __mdl) noexcept
+      { return {__y, __mdl}; }
+
+      friend constexpr year_month_day_last
+      operator/(int __y, const chrono::month_day_last& __mdl) noexcept
+      { return chrono::year(__y) / __mdl; }
+
+      friend constexpr year_month_day_last
+      operator/(const chrono::month_day_last& __mdl,
+               const chrono::year& __y) noexcept
+      { return __y / __mdl; }
+
+      friend constexpr year_month_day_last
+      operator/(const chrono::month_day_last& __mdl, int __y) noexcept
+      { return chrono::year(__y) / __mdl; }
+
+      // TODO: Implement operator<<.
+    };
+
+    // year_month_day ctor from year_month_day_last
+    constexpr
+    year_month_day::year_month_day(const year_month_day_last& __ymdl) noexcept
+    : _M_y{__ymdl.year()}, _M_m{__ymdl.month()}, _M_d{__ymdl.day()}
+    { }
+
+    constexpr bool
+    year_month_day::ok() const noexcept
+    {
+      if (!_M_y.ok() || !_M_m.ok())
+       return false;
+      return chrono::day{1} <= _M_d && _M_d <= (_M_y / _M_m / last).day();
+    }
+
+    // YEAR_MONTH_WEEKDAY
+
+    class year_month_weekday
+    {
+    private:
+      chrono::year _M_y;
+      chrono::month _M_m;
+      chrono::weekday_indexed _M_wdi;
+
+      static constexpr year_month_weekday
+      _S_from_sys_days(const sys_days& __dp)
+      {
+       year_month_day __ymd{__dp};
+       chrono::weekday __wd{__dp};
+       auto __index = __wd[(unsigned{__ymd.day()} - 1) / 7 + 1];
+       return {__ymd.year(), __ymd.month(), __index};
+      }
+
+    public:
+      year_month_weekday() = default;
+
+      constexpr
+      year_month_weekday(const chrono::year& __y, const chrono::month& __m,
+                        const chrono::weekday_indexed& __wdi) noexcept
+      : _M_y{__y}, _M_m{__m}, _M_wdi{__wdi}
+      { }
+
+      constexpr
+      year_month_weekday(const sys_days& __dp) noexcept
+      : year_month_weekday{_S_from_sys_days(__dp)}
+      { }
+
+      explicit constexpr
+      year_month_weekday(const local_days& __dp) noexcept
+      : year_month_weekday{sys_days{__dp.time_since_epoch()}}
+      { }
+
+      constexpr year_month_weekday&
+      operator+=(const months& __m) noexcept
+      {
+       *this = *this + __m;
+       return *this;
+      }
+
+      constexpr year_month_weekday&
+      operator-=(const months& __m) noexcept
+      {
+       *this = *this - __m;
+       return *this;
+      }
+
+      constexpr year_month_weekday&
+      operator+=(const years& __y) noexcept
+      {
+       *this = *this + __y;
+       return *this;
+      }
+
+      constexpr year_month_weekday&
+      operator-=(const years& __y) noexcept
+      {
+       *this = *this - __y;
+       return *this;
+      }
+
+      constexpr chrono::year
+      year() const noexcept
+      { return _M_y; }
+
+      constexpr chrono::month
+      month() const noexcept
+      { return _M_m; }
+
+      constexpr chrono::weekday
+      weekday() const noexcept
+      { return _M_wdi.weekday(); }
+
+      constexpr unsigned
+      index() const noexcept
+      { return _M_wdi.index(); }
+
+      constexpr chrono::weekday_indexed
+      weekday_indexed() const noexcept
+      { return _M_wdi; }
+
+      constexpr
+      operator sys_days() const noexcept
+      {
+       auto __d = sys_days{year() / month() / 1};
+       return __d + (weekday() - chrono::weekday(__d) + days{(index()-1)*7});
+      }
+
+      explicit constexpr
+      operator local_days() const noexcept
+      { return local_days{sys_days{*this}.time_since_epoch()}; }
+
+      constexpr bool
+      ok() const noexcept
+      {
+       if (!_M_y.ok() || !_M_m.ok() || !_M_wdi.ok())
+         return false;
+       if (_M_wdi.index() <= 4)
+         return true;
+       days __d = (_M_wdi.weekday()
+                   - chrono::weekday{sys_days{_M_y / _M_m / 1}}
+                   + days((_M_wdi.index()-1)*7 + 1));
+       __glibcxx_assert(__d >= 1);
+       return __d.count() <= unsigned{(_M_y / _M_m / last).day()};
+      }
+
+      friend constexpr bool
+      operator==(const year_month_weekday& __x,
+                const year_month_weekday& __y) noexcept
+      {
+       return __x.year() == __y.year()
+         && __x.month() == __y.month()
+         && __x.weekday() == __y.weekday();
+      }
+
+      friend constexpr year_month_weekday
+      operator+(const year_month_weekday& __ymwd, const months& __dm) noexcept
+      { return (__ymwd.year() / __ymwd.month() + __dm) / __ymwd.weekday_indexed(); }
+
+      friend constexpr year_month_weekday
+      operator+(const months& __dm, const year_month_weekday& __ymwd) noexcept
+      { return __ymwd + __dm; }
+
+      friend constexpr year_month_weekday
+      operator+(const year_month_weekday& __ymwd, const years& __dy) noexcept
+      { return {__ymwd.year() + __dy, __ymwd.month(), __ymwd.weekday_indexed()}; }
+
+      friend constexpr year_month_weekday
+      operator+(const years& __dy, const year_month_weekday& __ymwd) noexcept
+      { return __ymwd + __dy; }
+
+      friend constexpr year_month_weekday
+      operator-(const year_month_weekday& __ymwd, const months& __dm) noexcept
+      { return __ymwd + -__dm; }
+
+      friend constexpr year_month_weekday
+      operator-(const year_month_weekday& __ymwd, const years& __dy) noexcept
+      { return __ymwd + -__dy; }
+
+      friend constexpr year_month_weekday
+      operator/(const year_month& __ym,
+               const chrono::weekday_indexed& __wdi) noexcept
+      { return {__ym.year(), __ym.month(), __wdi}; }
+
+      friend constexpr year_month_weekday
+      operator/(const chrono::year& __y, const month_weekday& __mwd) noexcept
+      { return {__y, __mwd.month(), __mwd.weekday_indexed()}; }
+
+      friend constexpr year_month_weekday
+      operator/(int __y, const month_weekday& __mwd) noexcept
+      { return chrono::year(__y) / __mwd; }
+
+      friend constexpr year_month_weekday
+      operator/(const month_weekday& __mwd, const chrono::year& __y) noexcept
+      { return __y / __mwd; }
+
+      friend constexpr year_month_weekday
+      operator/(const month_weekday& __mwd, int __y) noexcept
+      { return chrono::year(__y) / __mwd; }
+
+      // TODO: Implement operator<<.
+    };
+
+    // YEAR_MONTH_WEEKDAY_LAST
+
+    class year_month_weekday_last
+    {
+    private:
+      chrono::year _M_y;
+      chrono::month _M_m;
+      chrono::weekday_last _M_wdl;
+
+    public:
+      constexpr
+      year_month_weekday_last(const chrono::year& __y, const chrono::month& __m,
+                             const chrono::weekday_last& __wdl) noexcept
+      : _M_y{__y}, _M_m{__m}, _M_wdl{__wdl}
+      { }
+
+      constexpr year_month_weekday_last&
+      operator+=(const months& __m) noexcept
+      {
+       *this = *this + __m;
+       return *this;
+      }
+
+      constexpr year_month_weekday_last&
+      operator-=(const months& __m) noexcept
+      {
+       *this = *this - __m;
+       return *this;
+      }
+
+      constexpr year_month_weekday_last&
+      operator+=(const years& __y)  noexcept
+      {
+       *this = *this + __y;
+       return *this;
+      }
+
+      constexpr year_month_weekday_last&
+      operator-=(const years& __y)  noexcept
+      {
+       *this = *this - __y;
+       return *this;
+      }
+
+      constexpr chrono::year
+      year() const noexcept
+      { return _M_y; }
+
+      constexpr chrono::month
+      month() const noexcept
+      { return _M_m; }
+
+      constexpr chrono::weekday
+      weekday() const noexcept
+      { return _M_wdl.weekday(); }
+
+      constexpr chrono::weekday_last
+      weekday_last() const noexcept
+      { return _M_wdl; }
+
+      constexpr
+      operator sys_days() const noexcept
+      {
+       const auto __d = sys_days{_M_y / _M_m / last};
+       return sys_days{(__d - (chrono::weekday{__d}
+                               - _M_wdl.weekday())).time_since_epoch()};
+      }
+
+      explicit constexpr
+      operator local_days() const noexcept
+      { return local_days{sys_days{*this}.time_since_epoch()}; }
+
+      constexpr bool
+      ok() const noexcept
+      { return _M_y.ok() && _M_m.ok() && _M_wdl.ok(); }
+
+      friend constexpr bool
+      operator==(const year_month_weekday_last& __x,
+                const year_month_weekday_last& __y) noexcept
+      {
+       return __x.year() == __y.year()
+         && __x.month() == __y.month()
+         && __x.weekday_last() == __y.weekday_last();
+      }
+
+      friend constexpr year_month_weekday_last
+      operator+(const year_month_weekday_last& __ymwdl,
+               const months& __dm) noexcept
+      { return (__ymwdl.year() / __ymwdl.month() + __dm) / __ymwdl.weekday_last(); }
+
+      friend constexpr year_month_weekday_last
+      operator+(const months& __dm,
+               const year_month_weekday_last& __ymwdl) noexcept
+      { return __ymwdl + __dm; }
+
+      friend constexpr year_month_weekday_last
+      operator+(const year_month_weekday_last& __ymwdl,
+               const years& __dy) noexcept
+      { return {__ymwdl.year() + __dy, __ymwdl.month(), __ymwdl.weekday_last()}; }
+
+      friend constexpr year_month_weekday_last
+      operator+(const years& __dy,
+               const year_month_weekday_last& __ymwdl) noexcept
+      { return __ymwdl + __dy; }
+
+      friend constexpr year_month_weekday_last
+      operator-(const year_month_weekday_last& __ymwdl,
+               const months& __dm) noexcept
+      { return __ymwdl + -__dm; }
+
+      friend constexpr year_month_weekday_last
+      operator-(const year_month_weekday_last& __ymwdl,
+               const years& __dy) noexcept
+      { return __ymwdl + -__dy; }
+
+      friend constexpr year_month_weekday_last
+      operator/(const year_month& __ym,
+               const chrono::weekday_last& __wdl) noexcept
+      { return {__ym.year(), __ym.month(), __wdl}; }
+
+      friend constexpr year_month_weekday_last
+      operator/(const chrono::year& __y,
+               const chrono::month_weekday_last& __mwdl) noexcept
+      { return {__y, __mwdl.month(), __mwdl.weekday_last()}; }
+
+      friend constexpr year_month_weekday_last
+      operator/(int __y, const chrono::month_weekday_last& __mwdl) noexcept
+      { return chrono::year(__y) / __mwdl; }
+
+      friend constexpr year_month_weekday_last
+      operator/(const chrono::month_weekday_last& __mwdl,
+               const chrono::year& __y) noexcept
+      { return __y / __mwdl; }
+
+      friend constexpr year_month_weekday_last
+      operator/(const chrono::month_weekday_last& __mwdl, int __y) noexcept
+      { return chrono::year(__y) / __mwdl; }
+
+      // TODO: Implement operator<<.
+    };
+
+    // HH_MM_SS
+
+    namespace __detail
+    {
+      consteval long long
+      __pow10(unsigned __n)
+      {
+       long long __r = 1;
+       while (__n-- > 0)
+         __r *= 10;
+       return __r;
+      }
+    }
+
+    template<typename _Duration>
+      class hh_mm_ss
+      {
+      private:
+       static constexpr int
+       _S_fractional_width()
+       {
+         int __multiplicity_2 = 0;
+         int __multiplicity_5 = 0;
+         auto __den = _Duration::period::den;
+         while ((__den % 2) == 0)
+           {
+             ++__multiplicity_2;
+             __den /= 2;
+           }
+         while ((__den % 5) == 0)
+           {
+             ++__multiplicity_5;
+             __den /= 5;
+           }
+         if (__den != 1)
+           return 6;
+
+         int __width = (__multiplicity_2 > __multiplicity_5
+                        ? __multiplicity_2 : __multiplicity_5);
+         if (__width > 18)
+           __width = 18;
+         return __width;
+       }
+
+      public:
+       static constexpr unsigned fractional_width = {_S_fractional_width()};
+
+       using precision
+         = duration<common_type_t<typename _Duration::rep,
+                                  chrono::seconds::rep>,
+                    ratio<1, __detail::__pow10(fractional_width)>>;
+
+       constexpr
+       hh_mm_ss() noexcept
+       : hh_mm_ss{_Duration::zero()}
+       { }
+
+       constexpr explicit
+       hh_mm_ss(_Duration __d) noexcept
+       : _M_is_neg (__d < _Duration::zero()),
+         _M_h (duration_cast<chrono::hours>(abs(__d))),
+         _M_m (duration_cast<chrono::minutes>(abs(__d) - hours())),
+         _M_s (duration_cast<chrono::seconds>(abs(__d) - hours() - minutes()))
+       {
+         if constexpr (treat_as_floating_point_v<typename precision::rep>)
+           _M_ss = abs(__d) - hours() - minutes() - seconds();
+         else
+           _M_ss = duration_cast<precision>(abs(__d) - hours()
+                                            - minutes() - seconds());
+       }
+
+       constexpr bool
+       is_negative() const noexcept
+       { return _M_is_neg; }
+
+       constexpr chrono::hours
+       hours() const noexcept
+       { return _M_h; }
+
+       constexpr chrono::minutes
+       minutes() const noexcept
+       { return _M_m; }
+
+       constexpr chrono::seconds
+       seconds() const noexcept
+       { return _M_s; }
+
+       constexpr precision
+       subseconds() const noexcept
+       { return _M_ss; }
+
+       constexpr explicit
+       operator precision() const noexcept
+       { return to_duration(); }
+
+       constexpr precision
+       to_duration() const noexcept
+       {
+         if (_M_is_neg)
+           return -(_M_h + _M_m + _M_s + _M_ss);
+         else
+           return _M_h + _M_m + _M_s + _M_ss;
+       }
+
+       // TODO: Implement operator<<.
+
+      private:
+       bool _M_is_neg;
+       chrono::hours _M_h;
+       chrono::minutes _M_m;
+       chrono::seconds _M_s;
+       precision _M_ss;
+      };
+#endif // C++20
+
+    // @}
+  } // namespace chrono
+
+#if __cplusplus > 201103L
+
+#define __cpp_lib_chrono_udls 201304
+
+  inline namespace literals
+  {
+  /** ISO C++ 2014  namespace for suffixes for duration literals.
+   *
+   * These suffixes can be used to create `chrono::duration` values with
+   * tick periods of hours, minutes, seconds, milliseconds, microseconds
+   * or nanoseconds. For example, `std::chrono::seconds(5)` can be written
+   * as `5s` after making the suffix visible in the current scope.
+   * The suffixes can be made visible by a using-directive or
+   * using-declaration such as:
+   *  - `using namespace std::chrono_literals;`
+   *  - `using namespace std::literals;`
+   *  - `using namespace std::chrono;`
+   *  - `using namespace std;`
+   *  - `using std::chrono_literals::operator""s;`
+   *
+   * The result of these suffixes on an integer literal is one of the
+   * standard typedefs such as `std::chrono::hours`.
+   * The result on a floating-point literal is a duration type with the
+   * specified tick period and an unspecified floating-point representation,
+   * for example `1.5e2ms` might be equivalent to
+   * `chrono::duration<long double, chrono::milli>(1.5e2)`.
+   *
+   * @ingroup chrono
+   */
+  inline namespace chrono_literals
+  {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wliteral-suffix"
+    /// @cond undocumented
+    template<typename _Dur, char... _Digits>
+      constexpr _Dur __check_overflow()
+      {
+       using _Val = __parse_int::_Parse_int<_Digits...>;
+       constexpr typename _Dur::rep __repval = _Val::value;
+       static_assert(__repval >= 0 && __repval == _Val::value,
+                     "literal value cannot be represented by duration type");
+       return _Dur(__repval);
+      }
+    /// @endcond
+
+    /// Literal suffix for durations representing non-integer hours
+    constexpr chrono::duration<long double, ratio<3600,1>>
+    operator""h(long double __hours)
+    { return chrono::duration<long double, ratio<3600,1>>{__hours}; }
+
+    /// Literal suffix for durations of type `std::chrono::hours`
+    template <char... _Digits>
+      constexpr chrono::hours
+      operator""h()
+      { return __check_overflow<chrono::hours, _Digits...>(); }
+
+    /// Literal suffix for durations representing non-integer minutes
+    constexpr chrono::duration<long double, ratio<60,1>>
+    operator""min(long double __mins)
+    { return chrono::duration<long double, ratio<60,1>>{__mins}; }
+
+    /// Literal suffix for durations of type `std::chrono::minutes`
+    template <char... _Digits>
+      constexpr chrono::minutes
+      operator""min()
+      { return __check_overflow<chrono::minutes, _Digits...>(); }
+
+    /// Literal suffix for durations representing non-integer seconds
+    constexpr chrono::duration<long double>
+    operator""s(long double __secs)
+    { return chrono::duration<long double>{__secs}; }
+
+    /// Literal suffix for durations of type `std::chrono::seconds`
+    template <char... _Digits>
+      constexpr chrono::seconds
+      operator""s()
+      { return __check_overflow<chrono::seconds, _Digits...>(); }
+
+    /// Literal suffix for durations representing non-integer milliseconds
+    constexpr chrono::duration<long double, milli>
+    operator""ms(long double __msecs)
+    { return chrono::duration<long double, milli>{__msecs}; }
+
+    /// Literal suffix for durations of type `std::chrono::milliseconds`
+    template <char... _Digits>
+      constexpr chrono::milliseconds
+      operator""ms()
+      { return __check_overflow<chrono::milliseconds, _Digits...>(); }
+
+    /// Literal suffix for durations representing non-integer microseconds
+    constexpr chrono::duration<long double, micro>
+    operator""us(long double __usecs)
+    { return chrono::duration<long double, micro>{__usecs}; }
+
+    /// Literal suffix for durations of type `std::chrono::microseconds`
+    template <char... _Digits>
+      constexpr chrono::microseconds
+      operator""us()
+      { return __check_overflow<chrono::microseconds, _Digits...>(); }
+
+    /// Literal suffix for durations representing non-integer nanoseconds
+    constexpr chrono::duration<long double, nano>
+    operator""ns(long double __nsecs)
+    { return chrono::duration<long double, nano>{__nsecs}; }
+
+    /// Literal suffix for durations of type `std::chrono::nanoseconds`
+    template <char... _Digits>
+      constexpr chrono::nanoseconds
+      operator""ns()
+      { return __check_overflow<chrono::nanoseconds, _Digits...>(); }
+
+#if __cplusplus > 201703L
+    constexpr chrono::day
+    operator""d(unsigned long long __d) noexcept
+    { return chrono::day{static_cast<unsigned>(__d)}; }
+
+    constexpr chrono::year
+    operator""y(unsigned long long __y) noexcept
+    { return chrono::year{static_cast<int>(__y)}; }
+#endif // C++20
+
+#pragma GCC diagnostic pop
+  } // inline namespace chrono_literals
+  } // inline namespace literals
+
+  namespace chrono
+  {
+    using namespace literals::chrono_literals;
+  } // namespace chrono
+
+#if __cplusplus > 201703L
+  namespace chrono
+  {
+    // 12/24 HOURS FUNCTIONS
+
+    constexpr bool
+    is_am(const hours& __h) noexcept
+    { return 0h <= __h && __h <= 11h; }
+
+    constexpr bool
+    is_pm(const hours& __h) noexcept
+    { return 12h <= __h && __h <= 23h; }
+
+    constexpr hours
+    make12(const hours& __h) noexcept
+    {
+      if (__h == 0h)
+       return 12h;
+      else if (__h > 12h)
+       return __h - 12h;
+      return __h;
+    }
+
+    constexpr hours
+    make24(const hours& __h, bool __is_pm) noexcept
+    {
+      if (!__is_pm)
+       {
+         if (__h == 12h)
+           return 0h;
+         else
+           return __h;
+       }
+      else
+       {
+         if (__h == 12h)
+           return __h;
+         else
+           return __h + 12h;
+       }
+    }
+  }
+#endif
 
 #if __cplusplus >= 201703L
   namespace filesystem
diff --git a/libstdc++-v3/testsuite/20_util/time_point/4.cc b/libstdc++-v3/testsuite/20_util/time_point/4.cc
new file mode 100644 (file)
index 0000000..5ae4acb
--- /dev/null
@@ -0,0 +1,42 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// 20.8.4 Class template time_point [time.point]
+
+#include <chrono>
+
+constexpr bool
+test_time_point_increment_ops()
+{
+  using namespace std::chrono;
+  bool ok = true;
+  time_point<local_t, seconds> tp(seconds(1));
+
+  ok &= tp.time_since_epoch() == 1s;
+  ok &= (tp++).time_since_epoch() == 1s;
+  ok &= tp.time_since_epoch() == 2s;
+  ok &= (++tp).time_since_epoch() == 3s;
+  ok &= (tp--).time_since_epoch() == 3s;
+  ok &= tp.time_since_epoch() == 2s;
+  ok &= (--tp).time_since_epoch() == 1s;
+  ok &= tp.time_since_epoch() == 1s;
+  return ok;
+}
+static_assert(test_time_point_increment_ops());
diff --git a/libstdc++-v3/testsuite/std/time/day/1.cc b/libstdc++-v3/testsuite/std/time/day/1.cc
new file mode 100644 (file)
index 0000000..7e5abc4
--- /dev/null
@@ -0,0 +1,67 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Class template day [time.cal.day]
+
+#include <chrono>
+
+constexpr void
+constexpr_day()
+{
+  using namespace std::chrono;
+
+  day dd{};
+  ++(++dd);
+  dd++;
+  --(--dd);
+  dd--;
+  dd += days{3};
+  dd -= days{3};
+
+  static_assert(day{1} + days{2} == day{3});
+  static_assert(days{2} + day{1} == day{3});
+  static_assert(day{3} - day{1} == days{2});
+  static_assert(day{3} - days{1} == day{2});
+
+  static_assert(++day{4} == day{5});
+  static_assert(day{4}++ == day{4});
+  static_assert(--day{4} == day{3});
+  static_assert(day{4}-- == day{4});
+  static_assert((day{4} += days{3}) == day{7});
+  static_assert((day{4} -= days{3}) == day{1});
+
+  static_assert(!day{}.ok());
+  static_assert(day{1}.ok());
+  static_assert(day{31}.ok());
+  static_assert(!day{32}.ok());
+
+  static_assert(unsigned{day{7}} == 7);
+
+  static_assert(!(day{0} == day{1}));
+  static_assert( (day{0} != day{2}));
+  static_assert( (day{0} <  day{3}));
+  static_assert(!(day{0} >  day{4}));
+  static_assert( (day{0} <= day{5}));
+  static_assert(!(day{0} >= day{6}));
+
+  static_assert(day{0} <=> day{1} == std::strong_ordering::less);
+  static_assert(day{3} <=> day{3} == std::strong_ordering::equal);
+  static_assert(day{5} <=> day{2} == std::strong_ordering::greater);
+}
diff --git a/libstdc++-v3/testsuite/std/time/hh_mm_ss/1.cc b/libstdc++-v3/testsuite/std/time/hh_mm_ss/1.cc
new file mode 100644 (file)
index 0000000..acb8643
--- /dev/null
@@ -0,0 +1,63 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Class template hh_mm_ss [time.hh_mm_ss]
+
+#include <chrono>
+
+constexpr void
+constexpr_hh_mm_ss()
+{
+  using namespace std::chrono;
+  using std::ratio;
+
+  static_assert(hh_mm_ss<hours>::fractional_width == 0);
+  static_assert(hh_mm_ss<minutes>::fractional_width == 0);
+  static_assert(hh_mm_ss<seconds>::fractional_width == 0);
+  static_assert(hh_mm_ss<milliseconds>::fractional_width == 3);
+  static_assert(hh_mm_ss<microseconds>::fractional_width == 6);
+  static_assert(hh_mm_ss<nanoseconds>::fractional_width == 9);
+  static_assert(hh_mm_ss<duration<int, ratio<1, 2>>>::fractional_width == 1);
+  static_assert(hh_mm_ss<duration<int, ratio<1, 3>>>::fractional_width == 6);
+  static_assert(hh_mm_ss<duration<int, ratio<1, 4>>>::fractional_width == 2);
+  static_assert(hh_mm_ss<duration<int, ratio<2, 4>>>::fractional_width == 1);
+  static_assert(hh_mm_ss<duration<int, ratio<1, 5>>>::fractional_width == 1);
+  static_assert(hh_mm_ss<duration<int, ratio<1, 6>>>::fractional_width == 6);
+  static_assert(hh_mm_ss<duration<int, ratio<1, 7>>>::fractional_width == 6);
+  static_assert(hh_mm_ss<duration<int, ratio<1, 8>>>::fractional_width == 3);
+  static_assert(hh_mm_ss<duration<int, ratio<1, 9>>>::fractional_width == 6);
+  static_assert(hh_mm_ss<duration<int, ratio<1, 10>>>::fractional_width == 1);
+  static_assert(hh_mm_ss<duration<int, ratio<756, 625>>>::fractional_width == 4);
+  static_assert(hh_mm_ss<duration<int, ratio<1, (1ll << 62)>>>::fractional_width
+               == 18);
+
+  constexpr auto hms = hh_mm_ss{-(8h + 9min + 10s + 11ms + 12us + 13ns)};
+  static_assert(__is_same(decltype(hms)::precision, nanoseconds));
+  static_assert(hms.hours() == 8h);
+  static_assert(hms.minutes() == 9min);
+  static_assert(hms.seconds() == 10s);
+  static_assert(hms.subseconds() == 11ms + 12us + 13ns);
+  static_assert(hms.is_negative());
+  static_assert(hh_mm_ss{hms.to_duration()}.to_duration() == hms.to_duration());
+
+  static_assert(seconds{hh_mm_ss{100min}} == 100min);
+
+  // TODO: treat_as_floating_point_v
+}
diff --git a/libstdc++-v3/testsuite/std/time/is_am/1.cc b/libstdc++-v3/testsuite/std/time/is_am/1.cc
new file mode 100644 (file)
index 0000000..c452f4b
--- /dev/null
@@ -0,0 +1,35 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Function is_am [time.12]
+
+#include <chrono>
+
+constexpr void
+constexpr_is_am()
+{
+  using namespace std::chrono;
+  static_assert(is_am(0h));
+  static_assert(is_am(5h));
+  static_assert(is_am(11h));
+  static_assert(!is_am(12h));
+  static_assert(!is_am(15h));
+  static_assert(!is_am(23h));
+}
diff --git a/libstdc++-v3/testsuite/std/time/is_pm/1.cc b/libstdc++-v3/testsuite/std/time/is_pm/1.cc
new file mode 100644 (file)
index 0000000..4ca5d93
--- /dev/null
@@ -0,0 +1,35 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Function is_pm [time.12]
+
+#include <chrono>
+
+constexpr void
+constexpr_is_pm()
+{
+  using namespace std::chrono;
+  static_assert(!is_pm(0h));
+  static_assert(!is_pm(5h));
+  static_assert(!is_pm(11h));
+  static_assert(is_pm(12h));
+  static_assert(is_pm(15h));
+  static_assert(is_pm(23h));
+}
diff --git a/libstdc++-v3/testsuite/std/time/make12/1.cc b/libstdc++-v3/testsuite/std/time/make12/1.cc
new file mode 100644 (file)
index 0000000..c13167b
--- /dev/null
@@ -0,0 +1,36 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Function is_pm [time.12]
+
+#include <chrono>
+
+constexpr void
+constexpr_make12()
+{
+  using namespace std::chrono;
+  static_assert(make12(0h) == 12h);
+  static_assert(make12(1h) == 1h);
+  static_assert(make12(5h) == 5h);
+  static_assert(make12(12h) == 12h);
+  static_assert(make12(13h) == 1h);
+  static_assert(make12(19h) == 7h);
+  static_assert(make12(23h) == 11h);
+}
diff --git a/libstdc++-v3/testsuite/std/time/make24/1.cc b/libstdc++-v3/testsuite/std/time/make24/1.cc
new file mode 100644 (file)
index 0000000..ee4c3f9
--- /dev/null
@@ -0,0 +1,41 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Function is_pm [time.12]
+
+#include <chrono>
+
+constexpr void
+constexpr_make24()
+{
+  using namespace std::chrono;
+
+  static_assert(make24(0h, false) == 0h);
+  static_assert(make24(1h, false) == 1h);
+  static_assert(make24(5h, false) == 5h);
+  static_assert(make24(11h, false) == 11h);
+  static_assert(make24(12h, false) == 0h);
+
+  static_assert(make24(0h, true) == 12h);
+  static_assert(make24(1h, true) == 13h);
+  static_assert(make24(5h, true) == 17h);
+  static_assert(make24(11h, true) == 23h);
+  static_assert(make24(12h, true) == 12h);
+}
diff --git a/libstdc++-v3/testsuite/std/time/month/1.cc b/libstdc++-v3/testsuite/std/time/month/1.cc
new file mode 100644 (file)
index 0000000..b5e74b0
--- /dev/null
@@ -0,0 +1,75 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Class template day [time.cal.month]
+
+#include <chrono>
+
+constexpr void
+constexpr_month()
+{
+  using namespace std::chrono;
+
+  month dm{};
+  ++(++dm);
+  dm++;
+  --(--dm);
+  dm--;
+  dm += months{3};
+  dm -= months{3};
+
+  static_assert(February + months{11} == January);
+  static_assert(January + months{1200} == January);
+  static_assert(January + months{1201} == February);
+  static_assert(months{-1200} + January == January);
+  static_assert(months{-1201} + January == December);
+  static_assert(January - months{1200} == January);
+  static_assert(January - months{-1200} == January);
+  static_assert(January - months{1201} == December);
+
+  static_assert(January - February == months{11});
+  static_assert(February - January == months{1});
+  static_assert(June - June == months{});
+
+  static_assert(++month{4} == month{5});
+  static_assert(month{4}++ == month{4});
+  static_assert(--month{4} == month{3});
+  static_assert(month{4}-- == month{4});
+  static_assert((month{4} += months{3}) == month{7});
+  static_assert((month{4} -= months{3}) == month{1});
+
+  static_assert(!month{}.ok());
+  static_assert(month{1}.ok());
+  static_assert(month{12}.ok());
+  static_assert(!month{13}.ok());
+
+  static_assert(unsigned{month{7}} == 7);
+
+  static_assert(!(month{0} == month{1}));
+  static_assert( (month{0} != month{2}));
+  static_assert( (month{0} <  month{3}));
+  static_assert(!(month{0} >  month{4}));
+  static_assert( (month{0} <= month{5}));
+  static_assert(!(month{0} >= month{6}));
+
+  static_assert(month{0} <=> month{1} == std::strong_ordering::less);
+  static_assert(month{3} <=> month{3} == std::strong_ordering::equal);
+  static_assert(month{5} <=> month{2} == std::strong_ordering::greater);
+}
diff --git a/libstdc++-v3/testsuite/std/time/month_day/1.cc b/libstdc++-v3/testsuite/std/time/month_day/1.cc
new file mode 100644 (file)
index 0000000..2d184f9
--- /dev/null
@@ -0,0 +1,73 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Class template month_day [time.cal.month_day]
+
+#include <chrono>
+
+using namespace std::chrono;
+
+constexpr void
+constexpr_month_day()
+{
+  month_day md0 = April/4;
+  month_day md2 = 4d/April;
+
+  constexpr auto md1 = month_day{month{3}, day{13}};
+  static_assert(md1.month() == month{3});
+  static_assert(md1.day() == day{13});
+
+  static_assert(!month_day{month{1}, day{}}.ok());
+  static_assert( month_day{month{2}, day{1}}.ok());
+  static_assert( month_day{month{3}, day{31}}.ok());
+  static_assert(!month_day{month{4}, day{32}}.ok());
+  static_assert(!month_day{month{0}, day{11}}.ok());
+  static_assert(!month_day{month{13}, day{7}}.ok());
+  static_assert( month_day{month{2}, day{28}}.ok());
+  static_assert( month_day{month{2}, day{29}}.ok());
+  static_assert(!month_day{month{2}, day{30}}.ok());
+
+  using md = month_day;
+  static_assert(!(md{month{1}, day{0}} == md{month{1}, day{1}}));
+  static_assert( (md{month{2}, day{0}} != md{month{2}, day{2}}));
+  static_assert( (md{month{3}, day{0}} <  md{month{3}, day{3}}));
+  static_assert(!(md{month{4}, day{0}} >  md{month{4}, day{4}}));
+  static_assert( (md{month{5}, day{0}} <= md{month{5}, day{5}}));
+  static_assert(!(md{month{6}, day{0}} >= md{month{6}, day{6}}));
+  static_assert( (md{month{10}, day{13}} == md{month{10}, day{13}}));
+  static_assert( (md{month{9}, day{13}} != md{month{10}, day{13}}));
+  static_assert( (md{month{8}, day{13}} < md{month{10}, day{13}}));
+  static_assert( (md{month{11}, day{13}} > md{month{10}, day{13}}));
+  static_assert( (md{month{10}, day{13}} <= md{month{10}, day{13}}));
+  static_assert( (md{month{10}, day{13}} >= md{month{10}, day{13}}));
+
+  static_assert( (md{month{10}, day{13}} <=> md{month{10}, day{13}})
+               == std::strong_ordering::equal);
+  static_assert( (md{month{3}, day{0}} <=>  md{month{3}, day{3}})
+               == std::strong_ordering::less);
+  static_assert( (md{month{11}, day{13}} <=> md{month{10}, day{13}})
+               == std::strong_ordering::greater);
+
+  static_assert(August/14d == month_day{month{8}, day{14}});
+  static_assert(August/14 == month_day{month{8}, day{14}});
+  static_assert(8/14d == month_day{month{8}, day{14}});
+  static_assert(14d/August == month_day{month{8}, day{14}});
+  static_assert(14d/8 == month_day{month{8}, day{14}});
+}
diff --git a/libstdc++-v3/testsuite/std/time/month_day_last/1.cc b/libstdc++-v3/testsuite/std/time/month_day_last/1.cc
new file mode 100644 (file)
index 0000000..979d36f
--- /dev/null
@@ -0,0 +1,65 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Class template day [time.cal.month_day_last]
+
+#include <chrono>
+
+constexpr void
+constexpr_month_day_last()
+{
+  using namespace std::chrono;
+  using mdl = month_day_last;
+
+  constexpr auto mdl0 = February / last;
+  static_assert(mdl0.month() == February);
+
+  constexpr auto mdl1 = month_day_last{month{3}};
+  static_assert(mdl1.month() == month{3});
+
+  static_assert( mdl{month{3}}.ok());
+  static_assert(!mdl{month{0}}.ok());
+  static_assert(!mdl{month{13}}.ok());
+
+  static_assert( (mdl{month{1}} == mdl{month{1}}));
+  static_assert(!(mdl{month{2}} != mdl{month{2}}));
+  static_assert(!(mdl{month{3}} <  mdl{month{3}}));
+  static_assert(!(mdl{month{4}} >  mdl{month{4}}));
+  static_assert( (mdl{month{5}} <= mdl{month{5}}));
+  static_assert( (mdl{month{6}} >= mdl{month{6}}));
+  static_assert( (mdl{month{10}} == mdl{month{10}}));
+  static_assert( (mdl{month{9}} != mdl{month{10}}));
+  static_assert( (mdl{month{8}} < mdl{month{10}}));
+  static_assert( (mdl{month{11}} > mdl{month{10}}));
+  static_assert( (mdl{month{10}} <= mdl{month{10}}));
+  static_assert( (mdl{month{10}} >= mdl{month{10}}));
+
+  static_assert( (mdl{month{1}} <=> mdl{month{1}})
+               == std::strong_ordering::equal);
+  static_assert( (mdl{month{11}} <=> mdl{month{10}})
+               == std::strong_ordering::greater);
+  static_assert( (mdl{month{8}} <=> mdl{month{10}})
+               == std::strong_ordering::less);
+
+  static_assert(August/last == mdl{month{8}});
+  static_assert(8/last == mdl{month{8}});
+  static_assert(last/August == mdl{month{8}});
+  static_assert(last/8 == mdl{month{8}});
+}
diff --git a/libstdc++-v3/testsuite/std/time/month_weekday/1.cc b/libstdc++-v3/testsuite/std/time/month_weekday/1.cc
new file mode 100644 (file)
index 0000000..fd3500d
--- /dev/null
@@ -0,0 +1,48 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Class template day [time.cal.month_weekday]
+
+#include <chrono>
+
+constexpr void
+constexpr_month_weekday()
+{
+  using namespace std::chrono;
+  using mwd = month_weekday;
+
+  // mwd0 is the third Tuesday of February of an as yet unspecified year.
+  constexpr auto mwd0 = February / Tuesday[3];
+  static_assert(mwd0.ok());
+  static_assert(mwd0.month() == February);
+  static_assert(mwd0.weekday_indexed() == Tuesday[3]);
+
+  static_assert(!mwd{month{0}, Tuesday[3]}.ok());
+  static_assert(!mwd{February, Tuesday[0]}.ok());
+
+  static_assert(mwd{January, Monday[2]} == mwd{January, Monday[2]});
+  static_assert(mwd{January, Monday[2]} != mwd{January, Monday[3]});
+  static_assert(mwd{February, Monday[2]} != mwd{January, Monday[2]});
+
+  static_assert(August/Friday[2] == mwd{month{8}, weekday_indexed{weekday{5u}, 2}});
+  static_assert(8/Friday[2] == mwd{month{8}, weekday_indexed{weekday{5u}, 2}});
+  static_assert(Friday[2]/August == mwd{month{8}, weekday_indexed{weekday{5u}, 2}});
+  static_assert(Friday[2]/8 == mwd{month{8}, weekday_indexed{weekday{5u}, 2}});
+}
diff --git a/libstdc++-v3/testsuite/std/time/month_weekday_last/1.cc b/libstdc++-v3/testsuite/std/time/month_weekday_last/1.cc
new file mode 100644 (file)
index 0000000..4d2c1bd
--- /dev/null
@@ -0,0 +1,48 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Class template day [time.cal.month_weekday_last]
+
+#include <chrono>
+
+constexpr void
+constexpr_month_weekday_last()
+{
+  using namespace std::chrono;
+  using mwdl = month_weekday_last;
+
+  // mwd0 is the third Tuesday of February of an as yet unspecified year.
+  constexpr auto mwdl0 = February / Tuesday[last];
+  static_assert(mwdl0.ok());
+  static_assert(mwdl0.month() == February);
+  static_assert(mwdl0.weekday_last() == Tuesday[last]);
+
+  static_assert(!mwdl{January, weekday_last{weekday{10}}}.ok());
+  static_assert(!mwdl{month{0}, Tuesday[last]}.ok());
+
+  static_assert(mwdl{January, Monday[last]} == mwdl{January, Monday[last]});
+  static_assert(mwdl{January, Monday[last]} != mwdl{January, Tuesday[last]});
+  static_assert(mwdl{February, Monday[last]} != mwdl{January, Monday[last]});
+
+  static_assert(August/Friday[last] == mwdl{month{8}, weekday_last{weekday{5u}}});
+  static_assert(8/Friday[last] == mwdl{month{8}, weekday_last{weekday{5u}}});
+  static_assert(Friday[last]/August == mwdl{month{8}, weekday_last{weekday{5u}}});
+  static_assert(Friday[last]/8 == mwdl{month{8}, weekday_last{weekday{5u}}});
+}
diff --git a/libstdc++-v3/testsuite/std/time/weekday/1.cc b/libstdc++-v3/testsuite/std/time/weekday/1.cc
new file mode 100644 (file)
index 0000000..d7330cd
--- /dev/null
@@ -0,0 +1,102 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Class template day [time.cal.weekday]
+
+#include <chrono>
+
+constexpr void
+constexpr_weekday()
+{
+  using namespace std::chrono;
+
+  weekday dwd{};
+  ++dwd;
+  dwd++;
+  --dwd;
+  dwd--;
+  dwd += days{3};
+  dwd -= days{3};
+
+  static_assert(weekday{3}[2].weekday() == weekday{3});
+  static_assert(weekday{3}[last].weekday() == weekday{3});
+
+  static_assert(weekday{sys_days{1900y/January/1}} == Monday);
+  static_assert(weekday{sys_days{1970y/January/1}} == Thursday);
+  static_assert(weekday{sys_days{2020y/August/21}} == Friday);
+
+  static_assert(weekday{local_days{1900y/January/1}} == Monday);
+  static_assert(weekday{local_days{1970y/January/1}} == Thursday);
+  static_assert(weekday{local_days{2020y/August/21}} == Friday);
+
+  static_assert(++weekday{3} == weekday{4});
+  static_assert(weekday{3}++ == weekday{3});
+  static_assert(--weekday{3} == weekday{2});
+  static_assert(weekday{3}-- == weekday{3});
+  static_assert((weekday{3} += days{3}) == weekday{6});
+  static_assert((weekday{3} -= days{3}) == weekday{0});
+
+  static_assert(Monday + days{7000} == Monday);
+  static_assert(Monday + days{-7000} == Monday);
+  static_assert(days{7001} + Monday == Tuesday);
+  static_assert(days{-7001} + Monday == Sunday);
+  static_assert(Monday - days{7000} == Monday);
+  static_assert(Monday - days{-7000} == Monday);
+  static_assert(Monday - days{7001} == Sunday);
+
+  static_assert([] {
+    constexpr unsigned diff_tbl[7][7]
+      = { { 0, 6, 5, 4, 3, 2, 1},
+         { 1, 0, 6, 5, 4, 3, 2},
+         { 2, 1, 0, 6, 5, 4, 3},
+         { 3, 2, 1, 0, 6, 5, 4},
+         { 4, 3, 2, 1, 0, 6, 5},
+         { 5, 4, 3, 2, 1, 0, 6},
+         { 6, 5, 4, 3, 2, 1, 0} };
+    for (unsigned x = 0; x < 7; x++)
+      for (unsigned y = 0; y < 7; y++)
+       {
+         if (weekday{x} - weekday{y} != days{diff_tbl[x][y]})
+           return false;
+         if (weekday{x} - days{diff_tbl[x][y]} != weekday{y})
+           return false;
+         if (weekday{x} != weekday{y} + days{diff_tbl[x][y]})
+           return false;
+         if (weekday{x} != days{diff_tbl[x][y]} + weekday{y})
+           return false;
+       }
+    return true;
+  }());
+
+  static_assert(Sunday.c_encoding() == 0);
+  static_assert(Sunday.iso_encoding() == 7);
+  static_assert(Monday.c_encoding() == 1);
+  static_assert(Monday.iso_encoding() == 1);
+
+  static_assert(!weekday{127}.ok());
+  static_assert(weekday{0}.ok());
+  static_assert(weekday{6}.ok());
+  static_assert(weekday{7}.ok()); // Ctor wraps 7 to 0.
+  static_assert(!weekday{8}.ok());
+
+  static_assert(weekday{7} == weekday{0});
+  static_assert(!(weekday{0} == weekday{1}));
+  static_assert( (weekday{0} != weekday{2}));
+}
diff --git a/libstdc++-v3/testsuite/std/time/weekday_indexed/1.cc b/libstdc++-v3/testsuite/std/time/weekday_indexed/1.cc
new file mode 100644 (file)
index 0000000..01b5b3d
--- /dev/null
@@ -0,0 +1,53 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Class template day [time.cal.weekday_indexed]
+
+#include <chrono>
+
+constexpr void
+constexpr_weekday_indexed()
+{
+  using namespace std::chrono;
+
+  weekday_indexed dwdi{};
+
+  // wdi0 is the second Sunday of an as yet unspecified month.
+  constexpr auto wdi0 = Sunday[2];
+  static_assert(wdi0.weekday() == Sunday);
+  static_assert(wdi0.index() == 2);
+
+  constexpr weekday_indexed wdi1 = {weekday{3}, 2};
+  static_assert(wdi1.weekday() == weekday{3});
+  static_assert(wdi1.index() == 2);
+
+  static_assert(!weekday_indexed{weekday{127}, 1}.ok());
+  static_assert(weekday_indexed{weekday{0}, 1}.ok());
+  static_assert(weekday_indexed{weekday{6}, 2}.ok());
+  static_assert(weekday_indexed{weekday{7}, 3}.ok()); // Weekday wraps 7 to 0.
+  static_assert(!weekday_indexed{weekday{8}, 1}.ok());
+  static_assert(!weekday_indexed{weekday{6}, 6}.ok());
+
+  static_assert(weekday{7}[1] == weekday{0}[1]);
+  static_assert(!(weekday{0}[2] == weekday{1}[2]));
+  static_assert(!(weekday{0}[2] == weekday{0}[3]));
+  static_assert( (weekday{0}[3] != weekday{2}[3]));
+  static_assert( (weekday{0}[3] != weekday{0}[2]));
+}
diff --git a/libstdc++-v3/testsuite/std/time/weekday_last/1.cc b/libstdc++-v3/testsuite/std/time/weekday_last/1.cc
new file mode 100644 (file)
index 0000000..60269f9
--- /dev/null
@@ -0,0 +1,48 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Class template day [time.cal.weekday_last]
+
+#include <chrono>
+
+constexpr void
+constexpr_weekday_last()
+{
+  using namespace std::chrono;
+
+  constexpr auto wdl0 = Sunday[last];
+  static_assert(wdl0.weekday() == Sunday);
+
+  constexpr auto wdl1 = weekday{3}[2];
+  static_assert(wdl1.weekday() == weekday{3});
+  static_assert(wdl1.index() == 2);
+  constexpr auto wdll = weekday{3}[last];
+  static_assert(wdll.weekday() == weekday{3});
+
+  static_assert(!weekday_last{weekday{127}}.ok());
+  static_assert(weekday_last{weekday{0}}.ok());
+  static_assert(weekday_last{weekday{6}}.ok());
+  static_assert(weekday_last{weekday{7}}.ok()); // Weekday wraps 7 to 0.
+  static_assert(!weekday_last{weekday{8}}.ok());
+
+  static_assert( (weekday_last{weekday{7}} == weekday_last{weekday{0}}));
+  static_assert(!(weekday_last{weekday{0}} == weekday_last{weekday{1}}));
+  static_assert( (weekday_last{weekday{0}} != weekday_last{weekday{2}}));
+}
diff --git a/libstdc++-v3/testsuite/std/time/year/1.cc b/libstdc++-v3/testsuite/std/time/year/1.cc
new file mode 100644 (file)
index 0000000..f3dbfe0
--- /dev/null
@@ -0,0 +1,85 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Class template day [time.cal.year]
+
+#include <chrono>
+
+constexpr void
+constexpr_year()
+{
+  using namespace std::chrono;
+
+  year dy{};
+  ++(++dy);
+  dy++;
+  --(--dy);
+  dy--;
+  dy += years{3};
+  dy -= years{3};
+
+  static_assert(++year{4} == year{5});
+  static_assert(year{4}++ == year{4});
+  static_assert(--year{4} == year{3});
+  static_assert(year{4}-- == year{4});
+  static_assert((year{4} += years{3}) == year{7});
+  static_assert((year{4} -= years{3}) == year{1});
+
+  static_assert(year{3} + years{7} == year{10});
+  static_assert(years{3} + year{7} == year{10});
+  static_assert(year{3} - years{7} == year{-4});
+  static_assert(year{10} - year{30} == years{-20});
+
+  const auto my = -dy;
+  const auto py = +dy;
+
+  static_assert((-year{1066} == year{-1066}));
+  static_assert((-year{-332} == year{332}));
+  static_assert((+year{1066} == year{1066}));
+  static_assert((+year{-332} == year{-332}));
+
+  year::min();
+  year::max();
+
+  static_assert(year{-12345}.ok());
+  static_assert(year{1}.ok());
+  static_assert(year{12}.ok());
+  static_assert(year{13}.ok());
+
+  static_assert(int{year{-42}} == -42);
+
+  static_assert(!(year{0} == year{1}));
+  static_assert( (year{0} != year{2}));
+  static_assert( (year{0} <  year{3}));
+  static_assert(!(year{0} >  year{4}));
+  static_assert( (year{0} <= year{5}));
+  static_assert(!(year{0} >= year{6}));
+
+  static_assert(year{10} <=> year{11} == std::strong_ordering::less);
+  static_assert(year{13} <=> year{13} == std::strong_ordering::equal);
+  static_assert(year{15} <=> year{12} == std::strong_ordering::greater);
+
+  static_assert( year{400}.is_leap());
+  static_assert( year{1984}.is_leap());
+  static_assert(!year{1}.is_leap());
+  static_assert( year{1600}.is_leap());
+  static_assert(!year{3000}.is_leap());
+  static_assert(!year{2019}.is_leap());
+}
diff --git a/libstdc++-v3/testsuite/std/time/year_month/1.cc b/libstdc++-v3/testsuite/std/time/year_month/1.cc
new file mode 100644 (file)
index 0000000..007cfeb
--- /dev/null
@@ -0,0 +1,86 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Class template year_month [time.cal.year_month]
+
+#include <chrono>
+
+constexpr void
+constexpr_year_month()
+{
+  using namespace std::chrono;
+  using ym = year_month;
+
+  ym ym0 = 2015y/April;
+  ym0 += years{100};
+  ym0 -= years{100};
+  ym0 += months{50};
+  ym0 -= months{50};
+
+  constexpr ym ym1 = {2015y, June};
+  static_assert(ym1.year() == year{2015});
+  static_assert(ym1.month() == June);
+  static_assert(ym1.ok());
+
+  constexpr ym ym2 = {2016y, May};
+  static_assert(ym2.year() == year{2016});
+  static_assert(ym2.month() == May);
+  static_assert(ym2.ok());
+
+  static_assert(ym1 == ym1);
+  static_assert(ym1 != ym2);
+  static_assert(ym1 < ym2);
+  static_assert(ym1 <= ym2);
+  static_assert(ym2 > ym1);
+  static_assert(ym2 >= ym2);
+
+  static_assert(ym1 <=> ym1 == std::strong_ordering::equal);
+  static_assert(ym1 <=> ym2 == std::strong_ordering::less);
+  static_assert(ym2 <=> ym1 == std::strong_ordering::greater);
+
+  static_assert(2015y/August == ym{year{2015}, August});
+  static_assert(2015y/8 == ym{year{2015}, August});
+
+  static_assert(ym1 + months{6} == 2015y/December);
+  static_assert(ym1 + months{7} == 2016y/January);
+  static_assert(months{24} + ym1 == 2017y/June);
+  static_assert(months{25} + ym1 == 2017y/July);
+
+  static_assert(ym1 + months{-5} == 2015y/January);
+  static_assert(ym1 + months{-6} == 2014y/December);
+  static_assert(ym1 + months{-24} == 2013y/June);
+  static_assert(ym1 + months{-25} == 2013y/May);
+
+  static_assert(ym1 - months{5} == 2015y/January);
+  static_assert(ym1 - months{6} == 2014y/December);
+  static_assert(ym1 - months{24} == 2013y/June);
+  static_assert(ym1 - months{25} == 2013y/May);
+
+  static_assert(ym2 - ym1 == months{11});
+  static_assert(ym1 - ym2 == -months{11});
+
+  static_assert(ym2 + years{1} == 2017y/May);
+  static_assert(ym2 + years{-1} == 2015y/May);
+  static_assert(ym2 - years{1} == 2015y/May);
+
+  static_assert(2017y/33 + months{0} == 2019y/9);
+
+  static_assert(2010y/January + months{-12} == 2009y/January);
+}
diff --git a/libstdc++-v3/testsuite/std/time/year_month_day/1.cc b/libstdc++-v3/testsuite/std/time/year_month_day/1.cc
new file mode 100644 (file)
index 0000000..24546c3
--- /dev/null
@@ -0,0 +1,91 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Class template day [time.cal.year_month_day]
+
+#include <chrono>
+
+constexpr void
+constexpr_year_month_day()
+{
+  using namespace std::chrono;
+  using ymd = year_month_day;
+
+  constexpr ymd ymd1{year{1984}, August, 3d};
+  static_assert(ymd1.ok());
+  static_assert(ymd1.year() == year{1984});
+  static_assert(ymd1.month() == August);
+  static_assert(ymd1.day() == 3d);
+  //static_assert(sys_days(ymd1) == time_point_cast<days>(days{5356}));
+  //static_assert(local_days(ymd1) == time_point_cast<days>(days{5356}));
+
+  static_assert(2015y/August/14d == ymd{year{2015}, month{8}, day{14}});
+  static_assert(2015y/August/14 == ymd{year{2015}, month{8}, day{14}});
+  static_assert(2015y/(August/14d) == ymd{year{2015}, month{8}, day{14}});
+  static_assert(2015/(August/14d) == ymd{year{2015}, month{8}, day{14}});
+  static_assert(August/14d/2015y == ymd{year{2015}, month{8}, day{14}});
+  static_assert(August/14d/2015 == ymd{year{2015}, month{8}, day{14}});
+
+  static_assert(((ymd{1000y, January, 1d} += months{1}) += years{1})
+               == February/1d/1001y);
+  static_assert(((ymd{1000y, January, 1d} -= years{1}) -= months{1})
+               == December/1d/998y);
+
+  static_assert(!ymd{1000y, February, 30d}.ok());
+
+  static_assert(June/1d/1977y == June/1d/1977y);
+  static_assert(June/1d/1977y != June/1d/1987y);
+  static_assert(May/15d/1950y <=> May/15d/1950y == std::strong_ordering::equal);
+  static_assert(May/15d/1950y <=> May/14d/1950y == std::strong_ordering::greater);
+  static_assert(April/15d/1950y <=> May/14d/1950y == std::strong_ordering::less);
+
+  static_assert(January/1d/1900y + months{13} == February/1d/1901y);
+  static_assert(months{13} + January/1d/1900y == February/1d/1901y);
+  static_assert(January/1d/1900y + years{1} == January/1d/1901y);
+  static_assert(years{1} + January/1d/1900y == January/1d/1901y);
+  static_assert(January/1d/1900y - months{13} == December/1d/1898y);
+  static_assert(January/1d/1900y - years{1} == January/1d/1899y);
+
+  // N.B. unix seems to be a macro somewhere!
+  constexpr ymd myunix = 1970y/1/1;
+  static_assert(myunix.ok());
+  static_assert(myunix.year() == year{1970});
+  static_assert(myunix.month() == January);
+  static_assert(myunix.day() == day{1});
+  static_assert(sys_days(myunix).time_since_epoch() == days{0});
+  //static_assert(local_days(myunix) == time_point_cast<days>(days{0}));
+
+  static_assert(sys_days{August/20d/2020y}.time_since_epoch() == days{18494});
+
+  static_assert(ymd{sys_days{2017y/January/0}}  == 2016y/December/31);
+  static_assert(ymd{sys_days{2017y/January/31}} == 2017y/January/31);
+  static_assert(ymd{sys_days{2017y/January/32}} == 2017y/February/1);
+  static_assert(ymd{sys_days{2017y/33/59 + months{0}}} == 2019y/10/29);
+
+  static_assert(ymd{local_days{2017y/January/0}}  == 2016y/December/31);
+  static_assert(ymd{local_days{2017y/January/31}} == 2017y/January/31);
+  static_assert(ymd{local_days{2017y/January/32}} == 2017y/February/1);
+  static_assert(ymd{local_days{2017y/33/59 + months{0}}} == 2019y/10/29);
+
+  static_assert((2000y/February/29d).ok());
+  static_assert(!(2001y/February/29d).ok());
+  static_assert(!(2100y/February/29d).ok());
+  static_assert(!(1999y/February/29d).ok());
+}
diff --git a/libstdc++-v3/testsuite/std/time/year_month_day_last/1.cc b/libstdc++-v3/testsuite/std/time/year_month_day_last/1.cc
new file mode 100644 (file)
index 0000000..a0cb9e7
--- /dev/null
@@ -0,0 +1,82 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Class template day [time.cal.year_month_day_last]
+
+#include <chrono>
+
+constexpr void
+constexpr_year_month_day_last()
+{
+  using namespace std::chrono;
+  using mdl = month_day_last;
+  using ymdl = year_month_day_last;
+
+  year_month_day_last ymdl1{year{1066}, mdl{October}};
+  ymdl1 += months{9};
+  ymdl1 -= months{9};
+  ymdl1 += years{12};
+  ymdl1 -= years{12};
+
+  constexpr ymdl ymdl2{year{1984}, mdl{August}};
+  static_assert(ymdl2.year() == year{1984});
+  static_assert(ymdl2.month() == August);
+  static_assert(ymdl2.month_day_last() == mdl{August});
+  static_assert(ymdl2.day() == day{31});
+  static_assert(sys_days(ymdl2).time_since_epoch().count() == 5356);
+  static_assert(local_days(ymdl2).time_since_epoch().count() == 5356);
+
+  static_assert( (ymdl{year{1984}, mdl{August}}.ok()));
+  static_assert(!(ymdl{year{1984}, mdl{month{13}}}.ok()));
+
+  static_assert(2015y/August/last == ymdl{year{2015}, month_day_last{month{8}}});
+  static_assert(2015y/(August/last) == ymdl{year{2015}, month_day_last{month{8}}});
+  static_assert(2015/(August/last) == ymdl{year{2015}, month_day_last{month{8}}});
+  static_assert(August/last/2015y == ymdl{year{2015}, month_day_last{month{8}}});
+  static_assert(August/last/2015 == ymdl{year{2015}, month_day_last{month{8}}});
+
+  static_assert(January/last/2000 <=> January/last/2000
+               == std::strong_ordering::equal);
+  static_assert(January/last/2000 <=> February/last/2000
+               == std::strong_ordering::less);
+  static_assert(January/last/2000 <=> January/last/1999
+               == std::strong_ordering::greater);
+
+  static_assert(January/last/2000 + months{13} == February/last/2001);
+  static_assert(January/last/2000 + months{-1} == December/last/1999);
+  static_assert(January/last/2000 - months{13} == December/last/1998);
+  static_assert(January/last/2000 - months{-13} == February/last/2001);
+
+  static_assert(January/last/2000 + years{5} == January/last/2005);
+  static_assert(January/last/2000 - years{5} == January/last/1995);
+
+  static_assert(year_month_day{January/last/2000} == January/31/2000);
+  static_assert(year_month_day{February/last/2000} == February/29/2000);
+  static_assert(year_month_day{March/last/2000} == March/31/2000);
+  static_assert(year_month_day{April/last/2000} == April/30/2000);
+  static_assert(year_month_day{May/last/2000} == May/31/2000);
+  static_assert(year_month_day{June/last/2000} == June/30/2000);
+  static_assert(year_month_day{July/last/2000} == July/31/2000);
+  static_assert(year_month_day{August/last/2000} == August/31/2000);
+  static_assert(year_month_day{September/last/2000} == September/30/2000);
+  static_assert(year_month_day{October/last/2000} == October/31/2000);
+  static_assert(year_month_day{November/last/2000} == November/30/2000);
+  static_assert(year_month_day{December/last/2000} == December/31/2000);
+}
diff --git a/libstdc++-v3/testsuite/std/time/year_month_weekday/1.cc b/libstdc++-v3/testsuite/std/time/year_month_weekday/1.cc
new file mode 100644 (file)
index 0000000..3781f17
--- /dev/null
@@ -0,0 +1,74 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Class template day [time.cal.year_month_weekday]
+
+#include <chrono>
+
+constexpr void
+constexpr_year_month_weekday()
+{
+  using namespace std::chrono;
+  using ymwd = year_month_weekday;
+
+  year_month_weekday ymwd1{};
+  ymwd1 += months{9};
+  ymwd1 -= months{9};
+  ymwd1 += years{12};
+  ymwd1 -= years{12};
+
+  constexpr ymwd ymwd2{year{1984}, month{August},
+                      weekday_indexed{Wednesday, 3}};
+  static_assert(ymwd2.ok());
+  static_assert(ymwd2.year() == year{1984});
+  static_assert(ymwd2.month() == August);
+  static_assert(ymwd2.weekday() == Wednesday);
+  static_assert(ymwd2.index() == 3);
+  static_assert(ymwd2.weekday_indexed() == weekday_indexed{Wednesday, 3});
+  static_assert(ymwd{sys_days{ymwd2}} == ymwd2);
+  static_assert(ymwd{local_days{ymwd2}} == ymwd2);
+
+  static_assert(2015y/August/Friday[2] == ymwd{year{2015}, month{8}, weekday_indexed{weekday{5u}, 2}});
+  static_assert(2015y/(August/Friday[2]) == ymwd{year{2015}, month{8}, weekday_indexed{weekday{5u}, 2}});
+  static_assert(2015/(August/Friday[2]) == ymwd{year{2015}, month{8}, weekday_indexed{weekday{5u}, 2}});
+  static_assert(August/Friday[2]/2015y == ymwd{year{2015}, month{8}, weekday_indexed{weekday{5u}, 2}});
+  static_assert(August/Friday[2]/2015 == ymwd{year{2015}, month{8}, weekday_indexed{weekday{5u}, 2}});
+
+  static_assert(January/Tuesday[2]/1900y + months{1} == February/Tuesday[2]/1900y);
+  static_assert(months{1} + January/Tuesday[2]/1900y == February/Tuesday[2]/1900y);
+  static_assert(January/Tuesday[2]/1900y - months{1} == December/Tuesday[2]/1899y);
+  static_assert(January/Tuesday[2]/1900y + years{1} == January/Tuesday[2]/1901y);
+  static_assert(years{1} + January/Tuesday[2]/1900y == January/Tuesday[2]/1901y);
+  static_assert(January/Tuesday[2]/1900y - years{1} == January/Tuesday[2]/1899y);
+
+  // N.B. unix seems to be a macro somewhere!
+  constexpr ymwd myunix(local_days{days{0}});
+  static_assert(myunix.ok());
+  static_assert(myunix.year() == year{1970});
+  static_assert(myunix.month() == January);
+  static_assert(myunix.weekday() == Thursday);
+  static_assert(myunix.index() == 1);
+  static_assert(myunix.weekday_indexed() == weekday_indexed{Thursday, 1});
+  static_assert(ymwd{sys_days{myunix}} == myunix);
+  static_assert(ymwd{local_days{myunix}} == myunix);
+
+  static_assert((2020y/August/Monday[5]).ok());
+  static_assert(!(2020y/August/Tuesday[5]).ok());
+}
diff --git a/libstdc++-v3/testsuite/std/time/year_month_weekday_last/1.cc b/libstdc++-v3/testsuite/std/time/year_month_weekday_last/1.cc
new file mode 100644 (file)
index 0000000..efb5385
--- /dev/null
@@ -0,0 +1,61 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// Class template month_day [time.cal.month_day]
+
+#include <chrono>
+
+constexpr void
+constexpr_year_month_weekday_last()
+{
+  using namespace std::chrono;
+  using ymwdl = year_month_weekday_last;
+
+  constexpr ymwdl ymwdl1 = {2015y, August, weekday_last{Friday}};
+  static_assert(ymwdl1.ok());
+  static_assert(ymwdl1.year() == 2015y);
+  static_assert(ymwdl1.month() == August);
+  static_assert(ymwdl1.weekday() == Friday);
+  static_assert(ymwdl1.weekday_last() == Friday[last]);
+  static_assert(year_month_day{sys_days{ymwdl1}} == 2015y/August/28d);
+  static_assert(year_month_day{local_days{ymwdl1}} == 2015y/August/28d);
+
+  static_assert(2015y/August/Friday[last] == ymwdl{year{2015}, month{8}, weekday_last{weekday{5u}}});
+  static_assert(2015y/(August/Friday[last]) == ymwdl{year{2015}, month{8}, weekday_last{weekday{5u}}});
+  static_assert(2015/(August/Friday[last]) == ymwdl{year{2015}, month{8}, weekday_last{weekday{5u}}});
+  static_assert(August/Friday[last]/2015y == ymwdl{year{2015}, month{8}, weekday_last{weekday{5u}}});
+  static_assert(August/Friday[last]/2015 == ymwdl{year{2015}, month{8}, weekday_last{weekday{5u}}});
+
+  static_assert((ymwdl{ymwdl1} += months{5} -= months{5}) == ymwdl1);
+  static_assert((ymwdl{ymwdl1} += years{5} -= years{5}) == ymwdl1);
+
+  static_assert(ymwdl1 + months{10} == 2016y/June/Friday[last]);
+  static_assert(months{10} + ymwdl1 == ymwdl1 + months{10});
+  static_assert(ymwdl1 - months{10} == 2014y/October/Friday[last]);
+
+  static_assert(ymwdl1 + years{10} == 2025y/August/Friday[last]);
+  static_assert(years{10} + ymwdl1 == ymwdl1 + years{10});
+  static_assert(ymwdl1 - years{10} == 2005y/August/Friday[last]);
+
+  constexpr ymwdl ymwdl2 = Saturday[last]/August/2015y;
+  static_assert(ymwdl2.ok());
+  static_assert(ymwdl1 == ymwdl1);
+  static_assert(ymwdl1 != ymwdl2);
+}