]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libstdc++-v3/include/std/chrono
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / include / std / chrono
index bf0d7e7af76638ee8fdfd84c21398d443174d262..b3ad2a0b1acd55e89a5aefac288c3a58fb12c25c 100644 (file)
@@ -1,6 +1,6 @@
 // <chrono> -*- C++ -*-
 
-// Copyright (C) 2008-2020 Free Software Foundation, Inc.
+// Copyright (C) 2008-2024 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
 
 #pragma GCC system_header
 
+#include <bits/requires_hosted.h> // for <ctime> and clocks
+
 #if __cplusplus < 201103L
 # include <bits/c++0x_warning.h>
 #else
 
-#include <ratio>
-#include <type_traits>
-#include <limits>
-#include <ctime>
-#include <bits/parse_numbers.h> // for literals support.
-#if __cplusplus > 201703L
-# include <concepts>
-# include <compare>
+#include <bits/chrono.h>
+
+#if __cplusplus >= 202002L
+# include <bit>
+# include <sstream>
+# include <string>
+# include <vector>
+# include <bits/stl_algo.h> // upper_bound
+# include <bits/shared_ptr.h>
+# include <bits/unique_ptr.h>
 #endif
 
+#define __glibcxx_want_chrono
+#define __glibcxx_want_chrono_udls
+#include <bits/version.h>
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
-#if __cplusplus >= 201703L
-  namespace filesystem { struct __file_clock; };
-#endif
-
   /**
    * @defgroup chrono Time
    * @ingroup utilities
    *
    * Classes and functions for time.
-   * @{
+   *
+   * @since C++11
    */
 
   /** @namespace std::chrono
    *  @brief ISO C++ 2011 namespace for date and time utilities
+   *  @ingroup chrono
    */
   namespace chrono
   {
-    template<typename _Rep, typename _Period = ratio<1>>
-      struct duration;
+#if __cplusplus >= 202002L
+    /// @addtogroup chrono
+    /// @{
+    struct local_t { };
+    template<typename _Duration>
+      using local_time = time_point<local_t, _Duration>;
+    using local_seconds = local_time<seconds>;
+    using local_days = local_time<days>;
+
+    class utc_clock;
+    class tai_clock;
+    class gps_clock;
 
-    template<typename _Clock, typename _Dur = typename _Clock::duration>
-      struct time_point;
-  }
+    template<typename _Duration>
+      using utc_time = time_point<utc_clock, _Duration>;
+    using utc_seconds = utc_time<seconds>;
 
-  // 20.11.4.3 specialization of common_type (for duration, sfinae-friendly)
+    template<typename _Duration>
+      using tai_time = time_point<tai_clock, _Duration>;
+    using tai_seconds = tai_time<seconds>;
 
-  /// @cond undocumented
+    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<typename _CT, typename _Period1, typename _Period2, typename = void>
-    struct __duration_common_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;
 
-  template<typename _CT, typename _Period1, typename _Period2>
-    struct __duration_common_type<_CT, _Period1, _Period2,
-                                 __void_t<typename _CT::type>>
+    struct leap_second_info
     {
-    private:
-      using __gcd_num = __static_gcd<_Period1::num, _Period2::num>;
-      using __gcd_den = __static_gcd<_Period1::den, _Period2::den>;
-      using __cr = typename _CT::type;
-      using __r = ratio<__gcd_num::value,
-                       (_Period1::den / __gcd_den::value) * _Period2::den>;
+      bool is_leap_second;
+      seconds elapsed;
+    };
+
+    template<typename _Duration>
+      leap_second_info
+      get_leap_second_info(const utc_time<_Duration>& __ut);
 
+    /** A clock that measures Universal Coordinated Time (UTC).
+     *
+     * The epoch is 1970-01-01 00:00:00.
+     *
+     * @since C++20
+     */
+    class utc_clock
+    {
     public:
-      using type = chrono::duration<__cr, __r>;
-    };
+      using rep                       = system_clock::rep;
+      using period                    = system_clock::period;
+      using duration                  = chrono::duration<rep, period>;
+      using time_point                = chrono::time_point<utc_clock>;
+      static constexpr bool is_steady = false;
 
-  template<typename _Period1, typename _Period2>
-    struct __duration_common_type<__failure_type, _Period1, _Period2>
-    { typedef __failure_type type; };
+      [[nodiscard]]
+      static time_point
+      now()
+      { return from_sys(system_clock::now()); }
 
-  /// @endcond
+      template<typename _Duration>
+       [[nodiscard]]
+       static sys_time<common_type_t<_Duration, seconds>>
+       to_sys(const utc_time<_Duration>& __t)
+       {
+         using _CDur = common_type_t<_Duration, seconds>;
+         const auto __li = chrono::get_leap_second_info(__t);
+         sys_time<_CDur> __s{__t.time_since_epoch() - __li.elapsed};
+         if (__li.is_leap_second)
+           __s = chrono::floor<seconds>(__s) + seconds{1} - _CDur{1};
+         return __s;
+       }
 
-  /// Specialization of common_type for chrono::duration types.
-  /// @relates duration
-  template<typename _Rep1, typename _Period1, typename _Rep2, typename _Period2>
-    struct common_type<chrono::duration<_Rep1, _Period1>,
-                      chrono::duration<_Rep2, _Period2>>
-    : __duration_common_type<common_type<_Rep1, _Rep2>, _Period1, _Period2>
-    { };
+      template<typename _Duration>
+       [[nodiscard]]
+       static utc_time<common_type_t<_Duration, seconds>>
+       from_sys(const sys_time<_Duration>& __t);
+    };
 
-  // 20.11.4.3 specialization of common_type (for time_point, sfinae-friendly)
+    /** A clock that measures International Atomic Time.
+     *
+     * The epoch is 1958-01-01 00:00:00.
+     *
+     * @since C++20
+     */
+    class tai_clock
+    {
+    public:
+      using rep                       = system_clock::rep;
+      using period                    = system_clock::period;
+      using duration                  = chrono::duration<rep, period>;
+      using time_point                = chrono::time_point<tai_clock>;
+      static constexpr bool is_steady = false; // XXX true for CLOCK_TAI?
+
+      // TODO move into lib, use CLOCK_TAI on linux, add extension point.
+      [[nodiscard]]
+      static time_point
+      now()
+      { return from_utc(utc_clock::now()); }
 
-  /// @cond undocumented
+      template<typename _Duration>
+       [[nodiscard]]
+       static utc_time<common_type_t<_Duration, seconds>>
+       to_utc(const tai_time<_Duration>& __t)
+       {
+         using _CDur = common_type_t<_Duration, seconds>;
+         return utc_time<_CDur>{__t.time_since_epoch()} - 378691210s;
+       }
 
-  template<typename _CT, typename _Clock, typename = void>
-    struct __timepoint_common_type
-    { };
+      template<typename _Duration>
+       [[nodiscard]]
+       static tai_time<common_type_t<_Duration, seconds>>
+       from_utc(const utc_time<_Duration>& __t)
+       {
+         using _CDur = common_type_t<_Duration, seconds>;
+         return tai_time<_CDur>{__t.time_since_epoch()} + 378691210s;
+       }
+    };
 
-  template<typename _CT, typename _Clock>
-    struct __timepoint_common_type<_CT, _Clock, __void_t<typename _CT::type>>
+    /** A clock that measures GPS time.
+     *
+     * The epoch is 1980-01-06 00:00:00.
+     *
+     * @since C++20
+     */
+    class gps_clock
     {
-      using type = chrono::time_point<_Clock, typename _CT::type>;
+    public:
+      using rep                       = system_clock::rep;
+      using period                    = system_clock::period;
+      using duration                  = chrono::duration<rep, period>;
+      using time_point                = chrono::time_point<gps_clock>;
+      static constexpr bool is_steady = false; // XXX
+
+      // TODO move into lib, add extension point.
+      [[nodiscard]]
+      static time_point
+      now()
+      { return from_utc(utc_clock::now()); }
+
+      template<typename _Duration>
+       [[nodiscard]]
+       static utc_time<common_type_t<_Duration, seconds>>
+       to_utc(const gps_time<_Duration>& __t)
+       {
+         using _CDur = common_type_t<_Duration, seconds>;
+         return utc_time<_CDur>{__t.time_since_epoch()} + 315964809s;
+       }
+
+      template<typename _Duration>
+       [[nodiscard]]
+       static gps_time<common_type_t<_Duration, seconds>>
+       from_utc(const utc_time<_Duration>& __t)
+       {
+         using _CDur = common_type_t<_Duration, seconds>;
+         return gps_time<_CDur>{__t.time_since_epoch()} - 315964809s;
+       }
     };
 
-  /// @endcond
 
-  /// Specialization of common_type for chrono::time_point types.
-  /// @relates time_point
-  template<typename _Clock, typename _Duration1, typename _Duration2>
-    struct common_type<chrono::time_point<_Clock, _Duration1>,
-                      chrono::time_point<_Clock, _Duration2>>
-    : __timepoint_common_type<common_type<_Duration1, _Duration2>, _Clock>
-    { };
+    template<typename _DestClock, typename _SourceClock>
+      struct clock_time_conversion
+      { };
 
-  // @} group chrono
+    // Identity conversions
 
-  namespace chrono
-  {
-    /// @addtogroup chrono
-    /// @{
+    template<typename _Clock>
+      struct clock_time_conversion<_Clock, _Clock>
+      {
+       template<typename _Duration>
+         time_point<_Clock, _Duration>
+         operator()(const time_point<_Clock, _Duration>& __t) const
+         { return __t; }
+      };
 
-    /// @cond undocumented
+    template<>
+      struct clock_time_conversion<system_clock, system_clock>
+      {
+       template<typename _Duration>
+         sys_time<_Duration>
+         operator()(const sys_time<_Duration>& __t) const
+         { return __t; }
+      };
 
-    // Primary template for duration_cast impl.
-    template<typename _ToDur, typename _CF, typename _CR,
-            bool _NumIsOne = false, bool _DenIsOne = false>
-      struct __duration_cast_impl
+    template<>
+      struct clock_time_conversion<utc_clock, utc_clock>
       {
-       template<typename _Rep, typename _Period>
-         static constexpr _ToDur
-         __cast(const duration<_Rep, _Period>& __d)
+       template<typename _Duration>
+         utc_time<_Duration>
+         operator()(const utc_time<_Duration>& __t) const
+         { return __t; }
+      };
+
+    // Conversions between system_clock and utc_clock
+
+    template<>
+      struct clock_time_conversion<utc_clock, system_clock>
+      {
+       template<typename _Duration>
+         utc_time<common_type_t<_Duration, seconds>>
+         operator()(const sys_time<_Duration>& __t) const
+         { return utc_clock::from_sys(__t); }
+      };
+
+    template<>
+      struct clock_time_conversion<system_clock, utc_clock>
+      {
+       template<typename _Duration>
+         sys_time<common_type_t<_Duration, seconds>>
+         operator()(const utc_time<_Duration>& __t) const
+         { return utc_clock::to_sys(__t); }
+      };
+
+    template<typename _Tp, typename _Clock>
+      inline constexpr bool __is_time_point_for_v = false;
+
+    template<typename _Clock, typename _Duration>
+      inline constexpr bool
+       __is_time_point_for_v<time_point<_Clock, _Duration>, _Clock> = true;
+
+    // Conversions between system_clock and other clocks
+
+    template<typename _SourceClock>
+      struct clock_time_conversion<system_clock, _SourceClock>
+      {
+       template<typename _Duration, typename _Src = _SourceClock>
+         auto
+         operator()(const time_point<_SourceClock, _Duration>& __t) const
+         -> decltype(_Src::to_sys(__t))
          {
-           typedef typename _ToDur::rep                        __to_rep;
-           return _ToDur(static_cast<__to_rep>(static_cast<_CR>(__d.count())
-             * static_cast<_CR>(_CF::num)
-             / static_cast<_CR>(_CF::den)));
+           using _Ret = decltype(_SourceClock::to_sys(__t));
+           static_assert(__is_time_point_for_v<_Ret, system_clock>);
+           return _SourceClock::to_sys(__t);
          }
       };
 
-    template<typename _ToDur, typename _CF, typename _CR>
-      struct __duration_cast_impl<_ToDur, _CF, _CR, true, true>
+    template<typename _DestClock>
+      struct clock_time_conversion<_DestClock, system_clock>
       {
-       template<typename _Rep, typename _Period>
-         static constexpr _ToDur
-         __cast(const duration<_Rep, _Period>& __d)
+       template<typename _Duration, typename _Dest = _DestClock>
+         auto
+         operator()(const sys_time<_Duration>& __t) const
+         -> decltype(_Dest::from_sys(__t))
          {
-           typedef typename _ToDur::rep                        __to_rep;
-           return _ToDur(static_cast<__to_rep>(__d.count()));
+           using _Ret = decltype(_DestClock::from_sys(__t));
+           static_assert(__is_time_point_for_v<_Ret, _DestClock>);
+           return _DestClock::from_sys(__t);
          }
       };
 
-    template<typename _ToDur, typename _CF, typename _CR>
-      struct __duration_cast_impl<_ToDur, _CF, _CR, true, false>
+    // Conversions between utc_clock and other clocks
+
+    template<typename _SourceClock>
+      struct clock_time_conversion<utc_clock, _SourceClock>
       {
-       template<typename _Rep, typename _Period>
-         static constexpr _ToDur
-         __cast(const duration<_Rep, _Period>& __d)
+       template<typename _Duration, typename _Src = _SourceClock>
+         auto
+         operator()(const time_point<_SourceClock, _Duration>& __t) const
+         -> decltype(_Src::to_utc(__t))
          {
-           typedef typename _ToDur::rep                        __to_rep;
-           return _ToDur(static_cast<__to_rep>(
-             static_cast<_CR>(__d.count()) / static_cast<_CR>(_CF::den)));
+           using _Ret = decltype(_SourceClock::to_utc(__t));
+           static_assert(__is_time_point_for_v<_Ret, utc_clock>);
+           return _SourceClock::to_utc(__t);
          }
       };
 
-    template<typename _ToDur, typename _CF, typename _CR>
-      struct __duration_cast_impl<_ToDur, _CF, _CR, false, true>
+    template<typename _DestClock>
+      struct clock_time_conversion<_DestClock, utc_clock>
       {
-       template<typename _Rep, typename _Period>
-         static constexpr _ToDur
-         __cast(const duration<_Rep, _Period>& __d)
+       template<typename _Duration, typename _Dest = _DestClock>
+         auto
+         operator()(const utc_time<_Duration>& __t) const
+         -> decltype(_Dest::from_utc(__t))
          {
-           typedef typename _ToDur::rep                        __to_rep;
-           return _ToDur(static_cast<__to_rep>(
-             static_cast<_CR>(__d.count()) * static_cast<_CR>(_CF::num)));
+           using _Ret = decltype(_DestClock::from_utc(__t));
+           static_assert(__is_time_point_for_v<_Ret, _DestClock>);
+           return _DestClock::from_utc(__t);
          }
       };
 
-    template<typename _Tp>
-      struct __is_duration
-      : std::false_type
-      { };
-
-    template<typename _Rep, typename _Period>
-      struct __is_duration<duration<_Rep, _Period>>
-      : std::true_type
-      { };
-
-    template<typename _Tp>
-      using __enable_if_is_duration
-       = typename enable_if<__is_duration<_Tp>::value, _Tp>::type;
-
-    template<typename _Tp>
-      using __disable_if_is_duration
-       = typename enable_if<!__is_duration<_Tp>::value, _Tp>::type;
-
+    /// @cond undocumented
+    namespace __detail
+    {
+      template<typename _DestClock, typename _SourceClock, typename _Duration>
+       concept __clock_convs
+         = requires (const time_point<_SourceClock, _Duration>& __t) {
+           clock_time_conversion<_DestClock, _SourceClock>{}(__t);
+         };
+
+      template<typename _DestClock, typename _SourceClock, typename _Duration>
+       concept __clock_convs_sys
+         = requires (const time_point<_SourceClock, _Duration>& __t) {
+           clock_time_conversion<_DestClock, system_clock>{}(
+             clock_time_conversion<system_clock, _SourceClock>{}(__t));
+         };
+
+      template<typename _DestClock, typename _SourceClock, typename _Duration>
+       concept __clock_convs_utc
+         = requires (const time_point<_SourceClock, _Duration>& __t) {
+           clock_time_conversion<_DestClock, utc_clock>{}(
+             clock_time_conversion<utc_clock, _SourceClock>{}(__t));
+         };
+
+      template<typename _DestClock, typename _SourceClock, typename _Duration>
+       concept __clock_convs_sys_utc
+         = requires (const time_point<_SourceClock, _Duration>& __t) {
+           clock_time_conversion<_DestClock, utc_clock>{}(
+             clock_time_conversion<utc_clock, system_clock>{}(
+               clock_time_conversion<system_clock, _SourceClock>{}(__t)));
+         };
+
+      template<typename _DestClock, typename _SourceClock, typename _Duration>
+       concept __clock_convs_utc_sys
+         = requires (const time_point<_SourceClock, _Duration>& __t) {
+           clock_time_conversion<_DestClock, system_clock>{}(
+             clock_time_conversion<system_clock, utc_clock>{}(
+               clock_time_conversion<utc_clock, _SourceClock>{}(__t)));
+         };
+
+    } // namespace __detail
     /// @endcond
 
-    /// duration_cast
-    template<typename _ToDur, typename _Rep, typename _Period>
-      constexpr __enable_if_is_duration<_ToDur>
-      duration_cast(const duration<_Rep, _Period>& __d)
-      {
-       typedef typename _ToDur::period                         __to_period;
-       typedef typename _ToDur::rep                            __to_rep;
-       typedef ratio_divide<_Period, __to_period>              __cf;
-       typedef typename common_type<__to_rep, _Rep, intmax_t>::type
-                                                               __cr;
-       typedef  __duration_cast_impl<_ToDur, __cf, __cr,
-                                     __cf::num == 1, __cf::den == 1> __dc;
-       return __dc::__cast(__d);
+    /// Convert a time point to a different clock.
+    template<typename _DestClock, typename _SourceClock, typename _Duration>
+      [[nodiscard]]
+      inline auto
+      clock_cast(const time_point<_SourceClock, _Duration>& __t)
+      requires __detail::__clock_convs<_DestClock, _SourceClock, _Duration>
+       || __detail::__clock_convs_sys<_DestClock, _SourceClock, _Duration>
+       || __detail::__clock_convs_utc<_DestClock, _SourceClock, _Duration>
+       || __detail::__clock_convs_sys_utc<_DestClock, _SourceClock, _Duration>
+       || __detail::__clock_convs_utc_sys<_DestClock, _SourceClock, _Duration>
+      {
+       constexpr bool __direct
+        = __detail::__clock_convs<_DestClock, _SourceClock, _Duration>;
+       if constexpr (__direct)
+        {
+          return clock_time_conversion<_DestClock, _SourceClock>{}(__t);
+        }
+       else
+        {
+          constexpr bool __convert_via_sys_clock
+            = __detail::__clock_convs_sys<_DestClock, _SourceClock, _Duration>;
+          constexpr bool __convert_via_utc_clock
+            = __detail::__clock_convs_utc<_DestClock, _SourceClock, _Duration>;
+          if constexpr (__convert_via_sys_clock)
+            {
+              static_assert(!__convert_via_utc_clock,
+                "clock_cast requires a unique best conversion, but "
+                "conversion is possible via system_clock and also via"
+                "utc_clock");
+              return clock_time_conversion<_DestClock, system_clock>{}(
+                       clock_time_conversion<system_clock, _SourceClock>{}(__t));
+            }
+          else if constexpr (__convert_via_utc_clock)
+            {
+              return clock_time_conversion<_DestClock, utc_clock>{}(
+                       clock_time_conversion<utc_clock, _SourceClock>{}(__t));
+            }
+          else
+            {
+              constexpr bool __convert_via_sys_and_utc_clocks
+                = __detail::__clock_convs_sys_utc<_DestClock,
+                                                  _SourceClock,
+                                                  _Duration>;
+
+              if constexpr (__convert_via_sys_and_utc_clocks)
+                {
+                  constexpr bool __convert_via_utc_and_sys_clocks
+                    = __detail::__clock_convs_utc_sys<_DestClock,
+                                                      _SourceClock,
+                                                      _Duration>;
+                  static_assert(!__convert_via_utc_and_sys_clocks,
+                    "clock_cast requires a unique best conversion, but "
+                    "conversion is possible via system_clock followed by "
+                    "utc_clock, and also via utc_clock followed by "
+                    "system_clock");
+                  return clock_time_conversion<_DestClock, utc_clock>{}(
+                           clock_time_conversion<utc_clock, system_clock>{}(
+                             clock_time_conversion<system_clock, _SourceClock>{}(__t)));
+                }
+              else
+                {
+                  return clock_time_conversion<_DestClock, system_clock>{}(
+                           clock_time_conversion<system_clock, utc_clock>{}(
+                             clock_time_conversion<utc_clock, _SourceClock>{}(__t)));
+                }
+            }
+        }
       }
 
-    /// treat_as_floating_point
-    template<typename _Rep>
-      struct treat_as_floating_point
-      : is_floating_point<_Rep>
-      { };
+    // 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;
 
-#if __cplusplus > 201402L
-    template <typename _Rep>
-      inline constexpr bool treat_as_floating_point_v =
-        treat_as_floating_point<_Rep>::value;
-#endif // C++17
+    struct last_spec
+    {
+      explicit last_spec() = default;
 
-#if __cplusplus > 201703L
-    template<typename _Tp>
-      struct is_clock;
+      friend constexpr month_day_last
+      operator/(int __m, last_spec) noexcept;
 
-    template<typename _Tp>
-      inline constexpr bool is_clock_v = is_clock<_Tp>::value;
+      friend constexpr month_day_last
+      operator/(last_spec, int __m) noexcept;
+    };
 
-#if __cpp_lib_concepts
-    template<typename _Tp>
-      struct is_clock : false_type
-      { };
+    inline constexpr last_spec last{};
 
-    template<typename _Tp>
-      requires requires {
-       typename _Tp::rep;
-       typename _Tp::period;
-       typename _Tp::duration;
-       typename _Tp::time_point::clock;
-       typename _Tp::time_point::duration;
-       { &_Tp::is_steady } -> same_as<const bool*>;
-       { _Tp::now() } -> same_as<typename _Tp::time_point>;
-       requires same_as<typename _Tp::duration,
-                        duration<typename _Tp::rep, typename _Tp::period>>;
-       requires same_as<typename _Tp::time_point::duration,
-                        typename _Tp::duration>;
+    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)
+      {
+       if (__n >= 0)
+         return __n % __d;
+       else
+         return (__d + (__n % __d)) % __d;
       }
-      struct is_clock<_Tp> : true_type
-      { };
-#else
-    template<typename _Tp, typename = void>
-      struct __is_clock_impl : false_type
-      { };
 
-    template<typename _Tp>
-      struct __is_clock_impl<_Tp,
-                            void_t<typename _Tp::rep, typename _Tp::period,
-                                   typename _Tp::duration,
-                                   typename _Tp::time_point::duration,
-                                   decltype(_Tp::is_steady),
-                                   decltype(_Tp::now())>>
-      : __and_<is_same<typename _Tp::duration,
-                      duration<typename _Tp::rep, typename _Tp::period>>,
-              is_same<typename _Tp::time_point::duration,
-                      typename _Tp::duration>,
-              is_same<decltype(&_Tp::is_steady), const bool*>,
-              is_same<decltype(_Tp::now()), typename _Tp::time_point>>::type
-      { };
+      inline constexpr unsigned __days_per_month[12]
+       = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+    }
 
-    template<typename _Tp>
-      struct is_clock : __is_clock_impl<_Tp>::type
-      { };
-#endif
-#endif // C++20
+    // DAY
+
+    class day
+    {
+    private:
+      unsigned char _M_d;
+
+    public:
+      day() = default;
 
-#if __cplusplus >= 201703L
-# define __cpp_lib_chrono 201611
+      explicit constexpr
+      day(unsigned __d) noexcept
+      : _M_d(__d)
+      { }
 
-    template<typename _ToDur, typename _Rep, typename _Period>
-      constexpr __enable_if_is_duration<_ToDur>
-      floor(const duration<_Rep, _Period>& __d)
+      constexpr day&
+      operator++() noexcept
       {
-       auto __to = chrono::duration_cast<_ToDur>(__d);
-       if (__to > __d)
-         return __to - _ToDur{1};
-       return __to;
+       ++_M_d;
+       return *this;
       }
 
-    template<typename _ToDur, typename _Rep, typename _Period>
-      constexpr __enable_if_is_duration<_ToDur>
-      ceil(const duration<_Rep, _Period>& __d)
+      constexpr day
+      operator++(int) noexcept
       {
-       auto __to = chrono::duration_cast<_ToDur>(__d);
-       if (__to < __d)
-         return __to + _ToDur{1};
-       return __to;
+       auto __ret = *this;
+       ++(*this);
+       return __ret;
       }
 
-    template <typename _ToDur, typename _Rep, typename _Period>
-      constexpr enable_if_t<
-       __and_<__is_duration<_ToDur>,
-              __not_<treat_as_floating_point<typename _ToDur::rep>>>::value,
-       _ToDur>
-      round(const duration<_Rep, _Period>& __d)
-      {
-       _ToDur __t0 = chrono::floor<_ToDur>(__d);
-       _ToDur __t1 = __t0 + _ToDur{1};
-       auto __diff0 = __d - __t0;
-       auto __diff1 = __t1 - __d;
-       if (__diff0 == __diff1)
-       {
-           if (__t0.count() & 1)
-               return __t1;
-           return __t0;
-       }
-       else if (__diff0 < __diff1)
-           return __t0;
-       return __t1;
+      constexpr day&
+      operator--() noexcept
+      {
+       --_M_d;
+       return *this;
       }
 
-    template<typename _Rep, typename _Period>
-      constexpr
-      enable_if_t<numeric_limits<_Rep>::is_signed, duration<_Rep, _Period>>
-      abs(duration<_Rep, _Period> __d)
+      constexpr day
+      operator--(int) noexcept
       {
-       if (__d >= __d.zero())
-         return __d;
-       return -__d;
+       auto __ret = *this;
+       --(*this);
+       return __ret;
       }
-#endif // C++17
 
-    /// duration_values
-    template<typename _Rep>
-      struct duration_values
+      constexpr day&
+      operator+=(const days& __d) noexcept
       {
-       static constexpr _Rep
-       zero() noexcept
-       { return _Rep(0); }
+       *this = *this + __d;
+       return *this;
+      }
 
-       static constexpr _Rep
-       max() noexcept
-       { return numeric_limits<_Rep>::max(); }
+      constexpr day&
+      operator-=(const days& __d) noexcept
+      {
+       *this = *this - __d;
+       return *this;
+      }
 
-       static constexpr _Rep
-       min() noexcept
-       { return numeric_limits<_Rep>::lowest(); }
-      };
+      constexpr explicit
+      operator unsigned() const noexcept
+      { return _M_d; }
 
-    /// @cond undocumented
+      constexpr bool
+      ok() const noexcept
+      { return 1 <= _M_d && _M_d <= 31; }
 
-    template<typename _Tp>
-      struct __is_ratio
-      : std::false_type
-      { };
+      friend constexpr bool
+      operator==(const day& __x, const day& __y) noexcept
+      { return unsigned{__x} == unsigned{__y}; }
 
-    template<intmax_t _Num, intmax_t _Den>
-      struct __is_ratio<ratio<_Num, _Den>>
-      : std::true_type
-      { };
+      friend constexpr strong_ordering
+      operator<=>(const day& __x, const day& __y) noexcept
+      { return unsigned{__x} <=> unsigned{__y}; }
 
-    /// @endcond
+      friend constexpr day
+      operator+(const day& __x, const days& __y) noexcept
+      { return day(unsigned{__x} + __y.count()); }
 
-    /// duration
-    template<typename _Rep, typename _Period>
-      struct duration
-      {
-      private:
-       template<typename _Rep2>
-         using __is_float = treat_as_floating_point<_Rep2>;
+      friend constexpr day
+      operator+(const days& __x, const day& __y) noexcept
+      { return __y + __x; }
 
-       // _Period2 is an exact multiple of _Period
-       template<typename _Period2>
-         using __is_harmonic
-           = __bool_constant<ratio_divide<_Period2, _Period>::den == 1>;
+      friend constexpr day
+      operator-(const day& __x, const days& __y) noexcept
+      { return __x + -__y; }
 
-      public:
+      friend constexpr days
+      operator-(const day& __x, const day& __y) noexcept
+      { return days{int(unsigned{__x}) - int(unsigned{__y})}; }
 
-       typedef _Rep                                            rep;
-       typedef _Period                                         period;
-
-       static_assert(!__is_duration<_Rep>::value, "rep cannot be a duration");
-       static_assert(__is_ratio<_Period>::value,
-                     "period must be a specialization of ratio");
-       static_assert(_Period::num > 0, "period must be positive");
-
-       // 20.11.5.1 construction / copy / destroy
-       constexpr duration() = default;
-
-       duration(const duration&) = default;
-
-       // _GLIBCXX_RESOLVE_LIB_DEFECTS
-       // 3050. Conversion specification problem in chrono::duration
-       template<typename _Rep2, typename = _Require<
-                is_convertible<const _Rep2&, rep>,
-                __or_<__is_float<rep>, __not_<__is_float<_Rep2>>>>>
-         constexpr explicit duration(const _Rep2& __rep)
-         : __r(static_cast<rep>(__rep)) { }
-
-       template<typename _Rep2, typename _Period2, typename = _Require<
-                __or_<__is_float<rep>,
-                      __and_<__is_harmonic<_Period2>,
-                             __not_<__is_float<_Rep2>>>>>>
-         constexpr duration(const duration<_Rep2, _Period2>& __d)
-         : __r(duration_cast<duration>(__d).count()) { }
-
-       ~duration() = default;
-       duration& operator=(const duration&) = default;
-
-       // 20.11.5.2 observer
-       constexpr rep
-       count() const
-       { return __r; }
-
-       // 20.11.5.3 arithmetic
-       constexpr duration
-       operator+() const
-       { return *this; }
-
-       constexpr duration
-       operator-() const
-       { return duration(-__r); }
-
-       _GLIBCXX17_CONSTEXPR duration&
-       operator++()
-       {
-         ++__r;
-         return *this;
-       }
+      friend constexpr month_day
+      operator/(const month& __m, const day& __d) noexcept;
 
-       _GLIBCXX17_CONSTEXPR duration
-       operator++(int)
-       { return duration(__r++); }
+      friend constexpr month_day
+      operator/(int __m, const day& __d) noexcept;
 
-       _GLIBCXX17_CONSTEXPR duration&
-       operator--()
-       {
-         --__r;
-         return *this;
-       }
+      friend constexpr month_day
+      operator/(const day& __d, const month& __m) noexcept;
 
-       _GLIBCXX17_CONSTEXPR duration
-       operator--(int)
-       { return duration(__r--); }
+      friend constexpr month_day
+      operator/(const day& __d, int __m) noexcept;
 
-       _GLIBCXX17_CONSTEXPR duration&
-       operator+=(const duration& __d)
-       {
-         __r += __d.count();
-         return *this;
-       }
-
-       _GLIBCXX17_CONSTEXPR duration&
-       operator-=(const duration& __d)
-       {
-         __r -= __d.count();
-         return *this;
-       }
-
-       _GLIBCXX17_CONSTEXPR duration&
-       operator*=(const rep& __rhs)
-       {
-         __r *= __rhs;
-         return *this;
-       }
-
-       _GLIBCXX17_CONSTEXPR duration&
-       operator/=(const rep& __rhs)
-       {
-         __r /= __rhs;
-         return *this;
-       }
-
-       // DR 934.
-       template<typename _Rep2 = rep>
-         _GLIBCXX17_CONSTEXPR
-         typename enable_if<!treat_as_floating_point<_Rep2>::value,
-                            duration&>::type
-         operator%=(const rep& __rhs)
-         {
-           __r %= __rhs;
-           return *this;
-         }
-
-       template<typename _Rep2 = rep>
-         _GLIBCXX17_CONSTEXPR
-         typename enable_if<!treat_as_floating_point<_Rep2>::value,
-                            duration&>::type
-         operator%=(const duration& __d)
-         {
-           __r %= __d.count();
-           return *this;
-         }
-
-       // 20.11.5.4 special values
-       static constexpr duration
-       zero() noexcept
-       { return duration(duration_values<rep>::zero()); }
-
-       static constexpr duration
-       min() noexcept
-       { return duration(duration_values<rep>::min()); }
-
-       static constexpr duration
-       max() noexcept
-       { return duration(duration_values<rep>::max()); }
-
-      private:
-       rep __r;
-      };
-
-    /// @relates duration @{
-
-    /// The sum of two durations.
-    template<typename _Rep1, typename _Period1,
-            typename _Rep2, typename _Period2>
-      constexpr typename common_type<duration<_Rep1, _Period1>,
-                                    duration<_Rep2, _Period2>>::type
-      operator+(const duration<_Rep1, _Period1>& __lhs,
-               const duration<_Rep2, _Period2>& __rhs)
-      {
-       typedef duration<_Rep1, _Period1>                       __dur1;
-       typedef duration<_Rep2, _Period2>                       __dur2;
-       typedef typename common_type<__dur1,__dur2>::type       __cd;
-       return __cd(__cd(__lhs).count() + __cd(__rhs).count());
-      }
-
-    /// The difference between two durations.
-    template<typename _Rep1, typename _Period1,
-            typename _Rep2, typename _Period2>
-      constexpr typename common_type<duration<_Rep1, _Period1>,
-                                    duration<_Rep2, _Period2>>::type
-      operator-(const duration<_Rep1, _Period1>& __lhs,
-               const duration<_Rep2, _Period2>& __rhs)
-      {
-       typedef duration<_Rep1, _Period1>                       __dur1;
-       typedef duration<_Rep2, _Period2>                       __dur2;
-       typedef typename common_type<__dur1,__dur2>::type       __cd;
-       return __cd(__cd(__lhs).count() - __cd(__rhs).count());
-      }
-
-    /// @}
+      friend constexpr year_month_day
+      operator/(const year_month& __ym, const day& __d) noexcept;
+    };
 
-    /// @cond undocumented
+    // MONTH
 
-    // SFINAE helper to obtain common_type<_Rep1, _Rep2> only if _Rep2
-    // is implicitly convertible to it.
-    // _GLIBCXX_RESOLVE_LIB_DEFECTS
-    // 3050. Conversion specification problem in chrono::duration constructor
-    template<typename _Rep1, typename _Rep2,
-            typename _CRep = typename common_type<_Rep1, _Rep2>::type>
-      using __common_rep_t = typename
-       enable_if<is_convertible<const _Rep2&, _CRep>::value, _CRep>::type;
+    class month
+    {
+    private:
+      unsigned char _M_m;
 
-    /// @endcond
+    public:
+      month() = default;
 
-    /// @relates duration @{
+      explicit constexpr
+      month(unsigned __m) noexcept
+      : _M_m(__m)
+      { }
 
-    /// Multiply a duration by a scalar value.
-    template<typename _Rep1, typename _Period, typename _Rep2>
-      constexpr duration<__common_rep_t<_Rep1, _Rep2>, _Period>
-      operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
+      constexpr month&
+      operator++() noexcept
       {
-       typedef duration<typename common_type<_Rep1, _Rep2>::type, _Period>
-         __cd;
-       return __cd(__cd(__d).count() * __s);
+       *this += months{1};
+       return *this;
       }
 
-    /// Multiply a duration by a scalar value.
-    template<typename _Rep1, typename _Rep2, typename _Period>
-      constexpr duration<__common_rep_t<_Rep2, _Rep1>, _Period>
-      operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d)
-      { return __d * __s; }
-
-    template<typename _Rep1, typename _Period, typename _Rep2>
-      constexpr
-      duration<__common_rep_t<_Rep1, __disable_if_is_duration<_Rep2>>, _Period>
-      operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
+      constexpr month
+      operator++(int) noexcept
       {
-       typedef duration<typename common_type<_Rep1, _Rep2>::type, _Period>
-         __cd;
-       return __cd(__cd(__d).count() / __s);
+       auto __ret = *this;
+       ++(*this);
+       return __ret;
       }
 
-    template<typename _Rep1, typename _Period1,
-            typename _Rep2, typename _Period2>
-      constexpr typename common_type<_Rep1, _Rep2>::type
-      operator/(const duration<_Rep1, _Period1>& __lhs,
-               const duration<_Rep2, _Period2>& __rhs)
+      constexpr month&
+      operator--() noexcept
       {
-       typedef duration<_Rep1, _Period1>                       __dur1;
-       typedef duration<_Rep2, _Period2>                       __dur2;
-       typedef typename common_type<__dur1,__dur2>::type       __cd;
-       return __cd(__lhs).count() / __cd(__rhs).count();
+       *this -= months{1};
+       return *this;
       }
 
-    // DR 934.
-    template<typename _Rep1, typename _Period, typename _Rep2>
-      constexpr
-      duration<__common_rep_t<_Rep1, __disable_if_is_duration<_Rep2>>, _Period>
-      operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s)
+      constexpr month
+      operator--(int) noexcept
       {
-       typedef duration<typename common_type<_Rep1, _Rep2>::type, _Period>
-         __cd;
-       return __cd(__cd(__d).count() % __s);
-      }
-
-    template<typename _Rep1, typename _Period1,
-            typename _Rep2, typename _Period2>
-      constexpr typename common_type<duration<_Rep1, _Period1>,
-                                    duration<_Rep2, _Period2>>::type
-      operator%(const duration<_Rep1, _Period1>& __lhs,
-               const duration<_Rep2, _Period2>& __rhs)
-      {
-       typedef duration<_Rep1, _Period1>                       __dur1;
-       typedef duration<_Rep2, _Period2>                       __dur2;
-       typedef typename common_type<__dur1,__dur2>::type       __cd;
-       return __cd(__cd(__lhs).count() % __cd(__rhs).count());
+       auto __ret = *this;
+       --(*this);
+       return __ret;
       }
 
-    // comparisons
-
-    template<typename _Rep1, typename _Period1,
-            typename _Rep2, typename _Period2>
-      constexpr bool
-      operator==(const duration<_Rep1, _Period1>& __lhs,
-                const duration<_Rep2, _Period2>& __rhs)
+      constexpr month&
+      operator+=(const months& __m) noexcept
       {
-       typedef duration<_Rep1, _Period1>                       __dur1;
-       typedef duration<_Rep2, _Period2>                       __dur2;
-       typedef typename common_type<__dur1,__dur2>::type       __ct;
-       return __ct(__lhs).count() == __ct(__rhs).count();
+       *this = *this + __m;
+       return *this;
       }
 
-    template<typename _Rep1, typename _Period1,
-            typename _Rep2, typename _Period2>
-      constexpr bool
-      operator<(const duration<_Rep1, _Period1>& __lhs,
-               const duration<_Rep2, _Period2>& __rhs)
+      constexpr month&
+      operator-=(const months& __m) noexcept
       {
-       typedef duration<_Rep1, _Period1>                       __dur1;
-       typedef duration<_Rep2, _Period2>                       __dur2;
-       typedef typename common_type<__dur1,__dur2>::type       __ct;
-       return __ct(__lhs).count() < __ct(__rhs).count();
-      }
-
-#if __cpp_lib_three_way_comparison
-    template<typename _Rep1, typename _Period1,
-            typename _Rep2, typename _Period2>
-      requires three_way_comparable<common_type_t<_Rep1, _Rep2>>
-      constexpr auto
-      operator<=>(const duration<_Rep1, _Period1>& __lhs,
-                 const duration<_Rep2, _Period2>& __rhs)
-      {
-       using __ct = common_type_t<duration<_Rep1, _Period1>,
-                                  duration<_Rep2, _Period2>>;
-       return __ct(__lhs).count() <=> __ct(__rhs).count();
+       *this = *this - __m;
+       return *this;
       }
-#else
-    template<typename _Rep1, typename _Period1,
-            typename _Rep2, typename _Period2>
-      constexpr bool
-      operator!=(const duration<_Rep1, _Period1>& __lhs,
-                const duration<_Rep2, _Period2>& __rhs)
-      { return !(__lhs == __rhs); }
-#endif
-
-    template<typename _Rep1, typename _Period1,
-            typename _Rep2, typename _Period2>
-      constexpr bool
-      operator<=(const duration<_Rep1, _Period1>& __lhs,
-                const duration<_Rep2, _Period2>& __rhs)
-      { return !(__rhs < __lhs); }
 
-    template<typename _Rep1, typename _Period1,
-            typename _Rep2, typename _Period2>
-      constexpr bool
-      operator>(const duration<_Rep1, _Period1>& __lhs,
-               const duration<_Rep2, _Period2>& __rhs)
-      { return __rhs < __lhs; }
+      explicit constexpr
+      operator unsigned() const noexcept
+      { return _M_m; }
 
-    template<typename _Rep1, typename _Period1,
-            typename _Rep2, typename _Period2>
       constexpr bool
-      operator>=(const duration<_Rep1, _Period1>& __lhs,
-                const duration<_Rep2, _Period2>& __rhs)
-      { return !(__lhs < __rhs); }
-
-    /// @}
-
-#ifdef _GLIBCXX_USE_C99_STDINT_TR1
-# define _GLIBCXX_CHRONO_INT64_T int64_t
-#elif defined __INT64_TYPE__
-# define _GLIBCXX_CHRONO_INT64_T __INT64_TYPE__
-#else
-    static_assert(std::numeric_limits<unsigned long long>::digits >= 64,
-       "Representation type for nanoseconds must have at least 64 bits");
-# define _GLIBCXX_CHRONO_INT64_T long long
-#endif
-
-    /// nanoseconds
-    using nanoseconds  = duration<_GLIBCXX_CHRONO_INT64_T, nano>;
-
-    /// microseconds
-    using microseconds = duration<_GLIBCXX_CHRONO_INT64_T, micro>;
-
-    /// milliseconds
-    using milliseconds = duration<_GLIBCXX_CHRONO_INT64_T, milli>;
-
-    /// seconds
-    using seconds      = duration<_GLIBCXX_CHRONO_INT64_T>;
-
-    /// minutes
-    using minutes      = duration<_GLIBCXX_CHRONO_INT64_T, ratio< 60>>;
-
-    /// hours
-    using hours                = duration<_GLIBCXX_CHRONO_INT64_T, ratio<3600>>;
+      ok() const noexcept
+      { return 1 <= _M_m && _M_m <= 12; }
 
-#if __cplusplus > 201703L
-    /// days
-    using days         = duration<_GLIBCXX_CHRONO_INT64_T, ratio<86400>>;
+      friend constexpr bool
+      operator==(const month& __x, const month& __y) noexcept
+      { return unsigned{__x} == unsigned{__y}; }
 
-    /// weeks
-    using weeks                = duration<_GLIBCXX_CHRONO_INT64_T, ratio<604800>>;
+      friend constexpr strong_ordering
+      operator<=>(const month& __x, const month& __y) noexcept
+      { return unsigned{__x} <=> unsigned{__y}; }
 
-    /// years
-    using years                = duration<_GLIBCXX_CHRONO_INT64_T, ratio<31556952>>;
+      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};
+      }
 
-    /// months
-    using months       = duration<_GLIBCXX_CHRONO_INT64_T, ratio<2629746>>;
-#endif // C++20
+      friend constexpr month
+      operator+(const months& __x,  const month& __y) noexcept
+      { return __y + __x; }
 
-#undef _GLIBCXX_CHRONO_INT64_T
+      friend constexpr month
+      operator-(const month& __x, const months& __y) noexcept
+      { return __x + -__y; }
 
-    /// time_point
-    template<typename _Clock, typename _Dur>
-      struct time_point
+      friend constexpr months
+      operator-(const month& __x,  const month& __y) noexcept
       {
-       static_assert(__is_duration<_Dur>::value,
-           "duration must be a specialization of std::chrono::duration");
+       const auto __dm = int(unsigned(__x)) - int(unsigned(__y));
+       return months{__dm < 0 ? 12 + __dm : __dm};
+      }
 
-       typedef _Clock                                          clock;
-       typedef _Dur                                            duration;
-       typedef typename duration::rep                          rep;
-       typedef typename duration::period                       period;
+      friend constexpr year_month
+      operator/(const year& __y, const month& __m) noexcept;
 
-       constexpr time_point() : __d(duration::zero())
-       { }
+      friend constexpr month_day
+      operator/(const month& __m, int __d) noexcept;
 
-       constexpr explicit time_point(const duration& __dur)
-       : __d(__dur)
-       { }
+      friend constexpr month_day_last
+      operator/(const month& __m, last_spec) noexcept;
 
-       // conversions
-       template<typename _Dur2,
-                typename = _Require<is_convertible<_Dur2, _Dur>>>
-         constexpr time_point(const time_point<clock, _Dur2>& __t)
-         : __d(__t.time_since_epoch())
-         { }
+      friend constexpr month_day_last
+      operator/(last_spec, const month& __m) noexcept;
 
-       // observer
-       constexpr duration
-       time_since_epoch() const
-       { return __d; }
+      friend constexpr month_weekday
+      operator/(const month& __m, const weekday_indexed& __wdi) noexcept;
 
-#if __cplusplus > 201703L
-       constexpr time_point&
-       operator++()
-       {
-         ++__d;
-         return *this;
-       }
+      friend constexpr month_weekday
+      operator/(const weekday_indexed& __wdi, const month& __m) noexcept;
 
-       constexpr time_point
-       operator++(int)
-       { return time_point{__d++}; }
+      friend constexpr month_weekday_last
+      operator/(const month& __m, const weekday_last& __wdl) noexcept;
 
-       constexpr time_point&
-       operator--()
-       {
-         --__d;
-         return *this;
-       }
+      friend constexpr month_weekday_last
+      operator/(const weekday_last& __wdl, const month& __m) noexcept;
+    };
 
-       constexpr time_point
-       operator--(int)
-       { return time_point{__d--}; }
-#endif
+    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};
 
-       // arithmetic
-       _GLIBCXX17_CONSTEXPR time_point&
-       operator+=(const duration& __dur)
-       {
-         __d += __dur;
-         return *this;
-       }
+    // YEAR
 
-       _GLIBCXX17_CONSTEXPR time_point&
-       operator-=(const duration& __dur)
-       {
-         __d -= __dur;
-         return *this;
-       }
+    class year
+    {
+    private:
+      short _M_y;
 
-       // special values
-       static constexpr time_point
-       min() noexcept
-       { return time_point(duration::min()); }
+    public:
+      year() = default;
 
-       static constexpr time_point
-       max() noexcept
-       { return time_point(duration::max()); }
+      explicit constexpr
+      year(int __y) noexcept
+      : _M_y{static_cast<short>(__y)}
+      { }
 
-      private:
-       duration __d;
-      };
+      static constexpr year
+      min() noexcept
+      { return year{-32767}; }
+
+      static constexpr year
+      max() noexcept
+      { return year{32767}; }
 
-    /// time_point_cast
-    template<typename _ToDur, typename _Clock, typename _Dur>
-      constexpr typename enable_if<__is_duration<_ToDur>::value,
-                                  time_point<_Clock, _ToDur>>::type
-      time_point_cast(const time_point<_Clock, _Dur>& __t)
+      constexpr year&
+      operator++() noexcept
       {
-       typedef time_point<_Clock, _ToDur>                      __time_point;
-       return __time_point(duration_cast<_ToDur>(__t.time_since_epoch()));
+       ++_M_y;
+       return *this;
       }
 
-#if __cplusplus > 201402L
-    template<typename _ToDur, typename _Clock, typename _Dur>
-      constexpr
-      enable_if_t<__is_duration<_ToDur>::value, time_point<_Clock, _ToDur>>
-      floor(const time_point<_Clock, _Dur>& __tp)
+      constexpr year
+      operator++(int) noexcept
       {
-       return time_point<_Clock, _ToDur>{
-           chrono::floor<_ToDur>(__tp.time_since_epoch())};
+       auto __ret = *this;
+       ++(*this);
+       return __ret;
       }
 
-    template<typename _ToDur, typename _Clock, typename _Dur>
-      constexpr
-      enable_if_t<__is_duration<_ToDur>::value, time_point<_Clock, _ToDur>>
-      ceil(const time_point<_Clock, _Dur>& __tp)
+      constexpr year&
+      operator--() noexcept
       {
-       return time_point<_Clock, _ToDur>{
-           chrono::ceil<_ToDur>(__tp.time_since_epoch())};
+       --_M_y;
+       return *this;
       }
 
-    template<typename _ToDur, typename _Clock, typename _Dur>
-      constexpr enable_if_t<
-       __and_<__is_duration<_ToDur>,
-              __not_<treat_as_floating_point<typename _ToDur::rep>>>::value,
-       time_point<_Clock, _ToDur>>
-      round(const time_point<_Clock, _Dur>& __tp)
+      constexpr year
+      operator--(int) noexcept
       {
-       return time_point<_Clock, _ToDur>{
-           chrono::round<_ToDur>(__tp.time_since_epoch())};
-      }
-#endif // C++17
-
-    /// @relates time_point @{
-
-    /// Adjust a time point forwards by the given duration.
-    template<typename _Clock, typename _Dur1,
-            typename _Rep2, typename _Period2>
-      constexpr time_point<_Clock,
-       typename common_type<_Dur1, duration<_Rep2, _Period2>>::type>
-      operator+(const time_point<_Clock, _Dur1>& __lhs,
-               const duration<_Rep2, _Period2>& __rhs)
-      {
-       typedef duration<_Rep2, _Period2>                       __dur2;
-       typedef typename common_type<_Dur1,__dur2>::type        __ct;
-       typedef time_point<_Clock, __ct>                        __time_point;
-       return __time_point(__lhs.time_since_epoch() + __rhs);
+       auto __ret = *this;
+       --(*this);
+       return __ret;
       }
 
-    /// Adjust a time point forwards by the given duration.
-    template<typename _Rep1, typename _Period1,
-            typename _Clock, typename _Dur2>
-      constexpr time_point<_Clock,
-       typename common_type<duration<_Rep1, _Period1>, _Dur2>::type>
-      operator+(const duration<_Rep1, _Period1>& __lhs,
-               const time_point<_Clock, _Dur2>& __rhs)
-      {
-       typedef duration<_Rep1, _Period1>                       __dur1;
-       typedef typename common_type<__dur1,_Dur2>::type        __ct;
-       typedef time_point<_Clock, __ct>                        __time_point;
-       return __time_point(__rhs.time_since_epoch() + __lhs);
+      constexpr year&
+      operator+=(const years& __y) noexcept
+      {
+       *this = *this + __y;
+       return *this;
       }
 
-    /// Adjust a time point backwards by the given duration.
-    template<typename _Clock, typename _Dur1,
-            typename _Rep2, typename _Period2>
-      constexpr time_point<_Clock,
-       typename common_type<_Dur1, duration<_Rep2, _Period2>>::type>
-      operator-(const time_point<_Clock, _Dur1>& __lhs,
-               const duration<_Rep2, _Period2>& __rhs)
-      {
-       typedef duration<_Rep2, _Period2>                       __dur2;
-       typedef typename common_type<_Dur1,__dur2>::type        __ct;
-       typedef time_point<_Clock, __ct>                        __time_point;
-       return __time_point(__lhs.time_since_epoch() -__rhs);
+      constexpr year&
+      operator-=(const years& __y) noexcept
+      {
+       *this = *this - __y;
+       return *this;
       }
 
-    /// @}
-
-    /// @relates time_point @{
-
-    /// The difference between two time points (as a duration)
-    template<typename _Clock, typename _Dur1, typename _Dur2>
-      constexpr typename common_type<_Dur1, _Dur2>::type
-      operator-(const time_point<_Clock, _Dur1>& __lhs,
-               const time_point<_Clock, _Dur2>& __rhs)
-      { return __lhs.time_since_epoch() - __rhs.time_since_epoch(); }
+      constexpr year
+      operator+() const noexcept
+      { return *this; }
 
-    template<typename _Clock, typename _Dur1, typename _Dur2>
-      constexpr bool
-      operator==(const time_point<_Clock, _Dur1>& __lhs,
-                const time_point<_Clock, _Dur2>& __rhs)
-      { return __lhs.time_since_epoch() == __rhs.time_since_epoch(); }
-
-#if __cpp_lib_three_way_comparison
-    template<typename _Clock, typename _Dur1,
-            three_way_comparable_with<_Dur1> _Dur2>
-      constexpr auto
-      operator<=>(const time_point<_Clock, _Dur1>& __lhs,
-                 const time_point<_Clock, _Dur2>& __rhs)
-      { return __lhs.time_since_epoch() <=> __rhs.time_since_epoch(); }
-#else
-    template<typename _Clock, typename _Dur1, typename _Dur2>
-      constexpr bool
-      operator!=(const time_point<_Clock, _Dur1>& __lhs,
-                const time_point<_Clock, _Dur2>& __rhs)
-      { return !(__lhs == __rhs); }
-#endif
+      constexpr year
+      operator-() const noexcept
+      { return year{-_M_y}; }
 
-    template<typename _Clock, typename _Dur1, typename _Dur2>
       constexpr bool
-      operator<(const time_point<_Clock, _Dur1>& __lhs,
-               const time_point<_Clock, _Dur2>& __rhs)
-      { return  __lhs.time_since_epoch() < __rhs.time_since_epoch(); }
+      is_leap() const noexcept
+      {
+       // Testing divisibility by 100 first gives better performance [1], i.e.,
+       //     return _M_y % 100 == 0 ? _M_y % 400 == 0 : _M_y % 16 == 0;
+       // Furthermore, if _M_y % 100 == 0, then _M_y % 400 == 0 is equivalent
+       // to _M_y % 16 == 0, so we can simplify it to
+       //     return _M_y % 100 == 0 ? _M_y % 16 == 0 : _M_y % 4 == 0.  // #1
+       // Similarly, we can replace 100 with 25 (which is good since
+       // _M_y % 25 == 0 requires one fewer instruction than _M_y % 100 == 0
+       // [2]):
+       //     return _M_y % 25 == 0 ? _M_y % 16 == 0 : _M_y % 4 == 0.  // #2
+       // Indeed, first assume _M_y % 4 != 0.  Then _M_y % 16 != 0 and hence,
+       // _M_y % 4 == 0 and _M_y % 16 == 0 are both false.  Therefore, #2
+       // returns false as it should (regardless of _M_y % 25.) Now assume
+       // _M_y % 4 == 0.  In this case, _M_y % 25 == 0 if, and only if,
+       // _M_y % 100 == 0, that is, #1 and #2 are equivalent.  Finally, #2 is
+       // equivalent to
+       //     return (_M_y & (_M_y % 25 == 0 ? 15 : 3)) == 0.
+
+       // References:
+       // [1] https://github.com/cassioneri/calendar
+       // [2] https://godbolt.org/z/55G8rn77e
+       // [3] https://gcc.gnu.org/pipermail/libstdc++/2021-June/052815.html
+
+       return (_M_y & (_M_y % 25 == 0 ? 15 : 3)) == 0;
+      }
 
-    template<typename _Clock, typename _Dur1, typename _Dur2>
-      constexpr bool
-      operator<=(const time_point<_Clock, _Dur1>& __lhs,
-                const time_point<_Clock, _Dur2>& __rhs)
-      { return !(__rhs < __lhs); }
+      explicit constexpr
+      operator int() const noexcept
+      { return _M_y; }
 
-    template<typename _Clock, typename _Dur1, typename _Dur2>
       constexpr bool
-      operator>(const time_point<_Clock, _Dur1>& __lhs,
-               const time_point<_Clock, _Dur2>& __rhs)
-      { return __rhs < __lhs; }
+      ok() const noexcept
+      { return min()._M_y <= _M_y && _M_y <= max()._M_y; }
 
-    template<typename _Clock, typename _Dur1, typename _Dur2>
-      constexpr bool
-      operator>=(const time_point<_Clock, _Dur1>& __lhs,
-                const time_point<_Clock, _Dur2>& __rhs)
-      { return !(__lhs < __rhs); }
-
-    // @}
-
-    // Clocks.
-
-    // Why nanosecond resolution as the default?
-    // Why have std::system_clock always count in the highest
-    // resolution (ie nanoseconds), even if on some OSes the low 3
-    // or 9 decimal digits will be always zero? This allows later
-    // implementations to change the system_clock::now()
-    // implementation any time to provide better resolution without
-    // changing function signature or units.
-
-    // To support the (forward) evolution of the library's defined
-    // clocks, wrap inside inline namespace so that the current
-    // defintions of system_clock, steady_clock, and
-    // high_resolution_clock types are uniquely mangled. This way, new
-    // code can use the latests clocks, while the library can contain
-    // compatibility definitions for previous versions.  At some
-    // point, when these clocks settle down, the inlined namespaces
-    // can be removed.  XXX GLIBCXX_ABI Deprecated
-    inline namespace _V2 {
-
-    /**
-     *  @brief System clock.
-     *
-     *  Time returned represents wall time from the system-wide clock.
-     *  @ingroup chrono
-    */
-    struct system_clock
-    {
-      typedef chrono::nanoseconds                              duration;
-      typedef duration::rep                                    rep;
-      typedef duration::period                                 period;
-      typedef chrono::time_point<system_clock, duration>       time_point;
+      friend constexpr bool
+      operator==(const year& __x, const year& __y) noexcept
+      { return int{__x} == int{__y}; }
 
-      static_assert(system_clock::duration::min()
-                   < system_clock::duration::zero(),
-                   "a clock's minimum duration cannot be less than its epoch");
-
-      static constexpr bool is_steady = false;
-
-      static time_point
-      now() noexcept;
-
-      // Map to C API
-      static std::time_t
-      to_time_t(const time_point& __t) noexcept
-      {
-       return std::time_t(duration_cast<chrono::seconds>
-                          (__t.time_since_epoch()).count());
-      }
-
-      static time_point
-      from_time_t(std::time_t __t) noexcept
-      {
-       typedef chrono::time_point<system_clock, seconds>       __from;
-       return time_point_cast<system_clock::duration>
-              (__from(chrono::seconds(__t)));
-      }
-    };
-
-
-    /**
-     *  @brief Monotonic clock
-     *
-     *  Time returned has the property of only increasing at a uniform rate.
-     *  @ingroup chrono
-    */
-    struct steady_clock
-    {
-      typedef chrono::nanoseconds                              duration;
-      typedef duration::rep                                    rep;
-      typedef duration::period                                 period;
-      typedef chrono::time_point<steady_clock, duration>       time_point;
-
-      static constexpr bool is_steady = true;
-
-      static time_point
-      now() noexcept;
-    };
-
-
-    /**
-     *  @brief Highest-resolution clock
-     *
-     *  This is the clock "with the shortest tick period." Alias to
-     *  std::system_clock until higher-than-nanosecond definitions
-     *  become feasible.
-     *  @ingroup chrono
-    */
-    using high_resolution_clock = system_clock;
-
-    } // end inline namespace _V2
+      friend constexpr strong_ordering
+      operator<=>(const year& __x, const year& __y) noexcept
+      { return int{__x} <=> int{__y}; }
 
-#if __cplusplus > 201703L
-    template<typename _Duration>
-      using sys_time = time_point<system_clock, _Duration>;
-    using sys_seconds = sys_time<seconds>;
-    using sys_days = sys_time<days>;
+      friend constexpr year
+      operator+(const year& __x, const years& __y) noexcept
+      { return year{int{__x} + static_cast<int>(__y.count())}; }
 
-    using file_clock = ::std::filesystem::__file_clock;
+      friend constexpr year
+      operator+(const years& __x, const year& __y) noexcept
+      { return __y + __x; }
 
-    template<typename _Duration>
-      using file_time = time_point<file_clock, _Duration>;
+      friend constexpr year
+      operator-(const year& __x, const years& __y) noexcept
+      { return __x + -__y; }
 
-    template<> struct is_clock<system_clock> : true_type { };
-    template<> struct is_clock<steady_clock> : true_type { };
-    template<> struct is_clock<file_clock> : true_type { };
+      friend constexpr years
+      operator-(const year& __x, const year& __y) noexcept
+      { return years{int{__x} - int{__y}}; }
 
-    template<> inline constexpr bool is_clock_v<system_clock> = true;
-    template<> inline constexpr bool is_clock_v<steady_clock> = true;
-    template<> inline constexpr bool is_clock_v<file_clock> = true;
+      friend constexpr year_month
+      operator/(const year& __y, int __m) noexcept;
 
-    struct local_t { };
-    template<typename _Duration>
-      using local_time = time_point<local_t, _Duration>;
-    using local_seconds = local_time<seconds>;
-    using local_days = local_time<days>;
+      friend constexpr year_month_day
+      operator/(const year& __y, const month_day& __md) noexcept;
 
-    class utc_clock;
-    class tai_clock;
-    class gps_clock;
+      friend constexpr year_month_day
+      operator/(const month_day& __md, const year& __y) noexcept;
 
-    template<typename _Duration>
-      using utc_time = time_point<utc_clock, _Duration>;
-    using utc_seconds = utc_time<seconds>;
+      friend constexpr year_month_day_last
+      operator/(const year& __y, const month_day_last& __mdl) noexcept;
 
-    template<typename _Duration>
-      using tai_time = time_point<tai_clock, _Duration>;
-    using tai_seconds = tai_time<seconds>;
+      friend constexpr year_month_day_last
+      operator/(const month_day_last& __mdl, const year& __y) noexcept;
 
-    template<typename _Duration>
-      using gps_time = time_point<gps_clock, _Duration>;
-    using gps_seconds = gps_time<seconds>;
+      friend constexpr year_month_weekday
+      operator/(const year& __y, const month_weekday& __mwd) noexcept;
 
-    template<> struct is_clock<utc_clock> : true_type { };
-    template<> struct is_clock<tai_clock> : true_type { };
-    template<> struct is_clock<gps_clock> : true_type { };
+      friend constexpr year_month_weekday
+      operator/(const month_weekday& __mwd, const year& __y) noexcept;
 
-    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;
+      friend constexpr year_month_weekday_last
+      operator/(const year& __y, const month_weekday_last& __mwdl) noexcept;
 
-    struct leap_second_info
-    {
-      bool is_leap_second;
-      seconds elapsed;
+      friend constexpr year_month_weekday_last
+      operator/(const month_weekday_last& __mwdl, const year& __y) noexcept;
     };
 
-    // 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;
+    // WEEKDAY
 
-    struct last_spec
+    class weekday
     {
-      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{};
+    private:
+      unsigned char _M_wd;
 
-    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)
+      static constexpr weekday
+      _S_from_days(const days& __d)
       {
-       if (__n >= 0)
-         return __n % __d;
-       else
-         return (__d + (__n % __d)) % __d;
-      }
-
-      inline constexpr unsigned __days_per_month[12]
-       = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+       using _Rep = days::rep;
+       using _URep = make_unsigned_t<_Rep>;
+       const auto __n = __d.count();
+       const auto __m = static_cast<_URep>(__n);
 
-      inline constexpr unsigned __last_day[12]
-       = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-    }
+       // 1970-01-01 (__n =  0, __m = 0        ) -> Thursday (4)
+       // 1969-31-12 (__n = -1, __m = _URep(-1)) -> Wednesday (3)
+       const auto __offset = __n >= 0 ? _URep(4) : 3 - _URep(-1) % 7 - 7;
+       return weekday((__m + __offset) % 7);
+      }
 
-    // DAY
+    public:
+      weekday() = default;
 
-    class day
-    {
-    private:
-      unsigned char _M_d;
+      explicit constexpr
+      weekday(unsigned __wd) noexcept
+      : _M_wd(__wd == 7 ? 0 : __wd) // __wd % 7 ?
+      { }
 
-    public:
-      day() = default;
+      constexpr
+      weekday(const sys_days& __dp) noexcept
+      : weekday{_S_from_days(__dp.time_since_epoch())}
+      { }
 
       explicit constexpr
-      day(unsigned __d) noexcept
-      : _M_d(__d)
+      weekday(const local_days& __dp) noexcept
+      : weekday{sys_days{__dp.time_since_epoch()}}
       { }
 
-      constexpr day&
+      constexpr weekday&
       operator++() noexcept
       {
-       ++_M_d;
+       *this += days{1};
        return *this;
       }
 
-      constexpr day
+      constexpr weekday
       operator++(int) noexcept
       {
        auto __ret = *this;
@@ -1215,14 +978,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        return __ret;
       }
 
-      constexpr day&
+      constexpr weekday&
       operator--() noexcept
       {
-       --_M_d;
+       *this -= days{1};
        return *this;
       }
 
-      constexpr day
+      constexpr weekday
       operator--(int) noexcept
       {
        auto __ret = *this;
@@ -1230,765 +993,349 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        return __ret;
       }
 
-      constexpr day&
+      constexpr weekday&
       operator+=(const days& __d) noexcept
       {
        *this = *this + __d;
        return *this;
       }
 
-      constexpr day&
+      constexpr weekday&
       operator-=(const days& __d) noexcept
       {
        *this = *this - __d;
        return *this;
       }
 
-      constexpr explicit
-      operator unsigned() const noexcept
-      { return _M_d; }
+      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 1 <= _M_d && _M_d <= 31; }
+      { return _M_wd <= 6; }
 
-      friend constexpr bool
-      operator==(const day& __x, const day& __y) noexcept
-      { return unsigned{__x} == unsigned{__y}; }
+      constexpr weekday_indexed
+      operator[](unsigned __index) const noexcept;
 
-      friend constexpr strong_ordering
-      operator<=>(const day& __x, const day& __y) noexcept
-      { return unsigned{__x} <=> unsigned{__y}; }
+      constexpr weekday_last
+      operator[](last_spec) const noexcept;
 
-      friend constexpr day
-      operator+(const day& __x, const days& __y) noexcept
-      { return day(unsigned{__x} + __y.count()); }
+      friend constexpr bool
+      operator==(const weekday& __x, const weekday& __y) noexcept
+      { return __x._M_wd == __y._M_wd; }
 
-      friend constexpr day
-      operator+(const days& __x, const day& __y) noexcept
+      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 day
-      operator-(const day& __x, const days& __y) noexcept
+      friend constexpr weekday
+      operator-(const weekday& __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.
+      operator-(const weekday& __x, const weekday& __y) noexcept
+      {
+       const auto __n = __x.c_encoding() - __y.c_encoding();
+       return static_cast<int>(__n) >= 0 ? days{__n} : days{__n + 7};
+      }
     };
 
-    // MONTH
+    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};
 
-    class month
+    // WEEKDAY_INDEXED
+
+    class weekday_indexed
     {
     private:
-      unsigned char _M_m;
+      chrono::weekday _M_wd;
+      unsigned char _M_index;
 
     public:
-      month() = default;
+      weekday_indexed() = default;
 
-      explicit constexpr
-      month(unsigned __m) noexcept
-      : _M_m(__m)
+      constexpr
+      weekday_indexed(const chrono::weekday& __wd, unsigned __index) noexcept
+      : _M_wd(__wd), _M_index(__index)
       { }
 
-      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;
-      }
+      constexpr chrono::weekday
+      weekday() const noexcept
+      { return _M_wd; }
 
-      explicit constexpr
-      operator unsigned() const noexcept
-      { return _M_m; }
+      constexpr unsigned
+      index() const noexcept
+      { return _M_index; };
 
       constexpr bool
       ok() const noexcept
-      { return 1 <= _M_m && _M_m <= 12; }
+      { return _M_wd.ok() && 1 <= _M_index && _M_index <= 5; }
 
       friend constexpr bool
-      operator==(const month& __x, const month& __y) noexcept
-      { return unsigned{__x} == unsigned{__y}; }
+      operator==(const weekday_indexed& __x, const weekday_indexed& __y) noexcept
+      { return __x.weekday() == __y.weekday() && __x.index() == __y.index(); }
 
-      friend constexpr strong_ordering
-      operator<=>(const month& __x, const month& __y) noexcept
-      { return unsigned{__x} <=> unsigned{__y}; }
+      friend constexpr month_weekday
+      operator/(const month& __m, const weekday_indexed& __wdi) noexcept;
 
-      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_weekday
+      operator/(int __m, const weekday_indexed& __wdi) noexcept;
 
-      friend constexpr month
-      operator+(const months& __x,  const month& __y) noexcept
-      { return __y + __x; }
+      friend constexpr month_weekday
+      operator/(const weekday_indexed& __wdi, const month& __m) noexcept;
 
-      friend constexpr month
-      operator-(const month& __x, const months& __y) noexcept
-      { return __x + -__y; }
+      friend constexpr month_weekday
+      operator/(const weekday_indexed& __wdi, int __m) noexcept;
 
-      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_weekday
+      operator/(const year_month& __ym, const weekday_indexed& __wdi) noexcept;
+    };
 
-      friend constexpr year_month
-      operator/(const year& __y, const month& __m) noexcept;
+    constexpr weekday_indexed
+    weekday::operator[](unsigned __index) const noexcept
+    { return {*this, __index}; }
 
-      friend constexpr month_day
-      operator/(const month& __m, int __d) noexcept;
+    // WEEKDAY_LAST
 
-      friend constexpr month_day_last
-      operator/(const month& __m, last_spec) noexcept;
+    class weekday_last
+    {
+    private:
+      chrono::weekday _M_wd;
 
-      friend constexpr month_day_last
-      operator/(last_spec, const month& __m) noexcept;
+    public:
+      explicit constexpr
+      weekday_last(const chrono::weekday& __wd) noexcept
+      : _M_wd{__wd}
+      { }
 
-      friend constexpr month_weekday
-      operator/(const month& __m, const weekday_indexed& __wdi) noexcept;
+      constexpr chrono::weekday
+      weekday() const noexcept
+      { return _M_wd; }
 
-      friend constexpr month_weekday
-      operator/(const weekday_indexed& __wdi, const month& __m) noexcept;
+      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/(const month& __m, const weekday_last& __wdl) noexcept;
+      operator/(int __m, const weekday_last& __wdl) noexcept;
 
       friend constexpr month_weekday_last
-      operator/(const weekday_last& __wdl, const month& __m) noexcept;
+      operator/(const weekday_last& __wdl, int __m) noexcept;
 
-      // TODO: Implement operator<<, to_stream, from_stream.
+      friend constexpr year_month_weekday_last
+      operator/(const year_month& __ym, const weekday_last& __wdl) noexcept;
     };
 
-    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};
+    constexpr weekday_last
+    weekday::operator[](last_spec) const noexcept
+    { return weekday_last{*this}; }
 
-    // YEAR
+    // MONTH_DAY
 
-    class year
+    class month_day
     {
     private:
-      short _M_y;
+      chrono::month _M_m;
+      chrono::day _M_d;
 
     public:
-      year() = default;
+      month_day() = default;
 
-      explicit constexpr
-      year(int __y) noexcept
-      : _M_y{static_cast<short>(__y)}
+      constexpr
+      month_day(const chrono::month& __m, const chrono::day& __d) noexcept
+      : _M_m{__m}, _M_d{__d}
       { }
 
-      static constexpr year
-      min() noexcept
-      { return year{-32767}; }
-
-      static constexpr year
-      max() noexcept
-      { return year{32767}; }
+      constexpr chrono::month
+      month() const noexcept
+      { return _M_m; }
 
-      constexpr year&
-      operator++() noexcept
-      {
-       ++_M_y;
-       return *this;
-      }
+      constexpr chrono::day
+      day() const noexcept
+      { return _M_d; }
 
-      constexpr year
-      operator++(int) noexcept
+      constexpr bool
+      ok() const noexcept
       {
-       auto __ret = *this;
-       ++(*this);
-       return __ret;
+       return _M_m.ok()
+         && 1u <= unsigned(_M_d)
+         && unsigned(_M_d) <= __detail::__days_per_month[unsigned(_M_m) - 1];
       }
 
-      constexpr year&
-      operator--() noexcept
-      {
-       --_M_y;
-       return *this;
-      }
+      friend constexpr bool
+      operator==(const month_day& __x, const month_day& __y) noexcept
+      { return __x.month() == __y.month() && __x.day() == __y.day(); }
 
-      constexpr year
-      operator--(int) noexcept
-      {
-       auto __ret = *this;
-       --(*this);
-       return __ret;
-      }
+      friend constexpr strong_ordering
+      operator<=>(const month_day& __x, const month_day& __y) noexcept
+       = default;
 
-      constexpr year&
-      operator+=(const years& __y) noexcept
-      {
-       *this = *this + __y;
-       return *this;
-      }
+      friend constexpr month_day
+      operator/(const chrono::month& __m, const chrono::day& __d) noexcept
+      { return {__m, __d}; }
 
-      constexpr year&
-      operator-=(const years& __y) noexcept
-      {
-       *this = *this - __y;
-       return *this;
-      }
+      friend constexpr month_day
+      operator/(const chrono::month& __m, int __d) noexcept
+      { return {__m, chrono::day(unsigned(__d))}; }
 
-      constexpr year
-      operator+() const noexcept
-      { return *this; }
+      friend constexpr month_day
+      operator/(int __m, const chrono::day& __d) noexcept
+      { return {chrono::month(unsigned(__m)), __d}; }
 
-      constexpr year
-      operator-() const noexcept
-      { return year{-_M_y}; }
+      friend constexpr month_day
+      operator/(const chrono::day& __d, const chrono::month& __m) noexcept
+      { return {__m, __d}; }
 
-      constexpr bool
-      is_leap() const noexcept
-      { return _M_y % 4 == 0 && (_M_y % 100 != 0 || _M_y % 400 == 0); }
+      friend constexpr month_day
+      operator/(const chrono::day& __d, int __m) noexcept
+      { return {chrono::month(unsigned(__m)), __d}; }
 
-      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/(int __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.
+      operator/(const month_day& __md, int __y) noexcept;
     };
 
-    // WEEKDAY
+    // MONTH_DAY_LAST
 
-    class weekday
+    class month_day_last
     {
     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);
-      }
+      chrono::month _M_m;
 
     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()}}
+      month_day_last(const chrono::month& __m) noexcept
+      : _M_m{__m}
       { }
 
-      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 chrono::month
+      month() const noexcept
+      { return _M_m; }
 
       constexpr bool
       ok() const noexcept
-      { return _M_wd <= 6; }
+      { return _M_m.ok(); }
 
-      constexpr weekday_indexed
-      operator[](unsigned __index) const noexcept;
+      friend constexpr bool
+      operator==(const month_day_last& __x, const month_day_last& __y) noexcept
+      { return __x.month() == __y.month(); }
 
-      constexpr weekday_last
-      operator[](last_spec) const noexcept;
+      friend constexpr strong_ordering
+      operator<=>(const month_day_last& __x, const month_day_last& __y) noexcept
+       = default;
 
-      friend constexpr bool
-      operator==(const weekday& __x, const weekday& __y) noexcept
-      { return __x._M_wd == __y._M_wd; }
+      friend constexpr month_day_last
+      operator/(const chrono::month& __m, last_spec) noexcept
+      { return month_day_last{__m}; }
 
-      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 month_day_last
+      operator/(int __m, last_spec) noexcept
+      { return chrono::month(unsigned(__m)) / last; }
 
-      friend constexpr weekday
-      operator+(const days& __x, const weekday& __y) noexcept
-      { return __y + __x; }
+      friend constexpr month_day_last
+      operator/(last_spec, const chrono::month& __m) noexcept
+      { return __m / last; }
 
-      friend constexpr weekday
-      operator-(const weekday& __x, const days& __y) noexcept
-      { return __x + -__y; }
+      friend constexpr month_day_last
+      operator/(last_spec, int __m) noexcept
+      { return __m / last; }
 
-      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)};
-      }
+      friend constexpr year_month_day_last
+      operator/(int __y, const month_day_last& __mdl) noexcept;
 
-      // TODO: operator<<, from_stream.
+      friend constexpr year_month_day_last
+      operator/(const month_day_last& __mdl, int __y) noexcept;
     };
 
-    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
+    // MONTH_WEEKDAY
 
-    class weekday_indexed
+    class month_weekday
     {
     private:
-      chrono::weekday _M_wd;
-      unsigned char _M_index;
+      chrono::month _M_m;
+      chrono::weekday_indexed _M_wdi;
 
     public:
-      weekday_indexed() = default;
-
       constexpr
-      weekday_indexed(const chrono::weekday& __wd, unsigned __index) noexcept
-      : _M_wd(__wd), _M_index(__index)
+      month_weekday(const chrono::month& __m,
+                   const chrono::weekday_indexed& __wdi) noexcept
+      : _M_m{__m}, _M_wdi{__wdi}
       { }
 
-      constexpr chrono::weekday
-      weekday() const noexcept
-      { return _M_wd; }
+      constexpr chrono::month
+      month() const noexcept
+      { return _M_m; }
 
-      constexpr unsigned
-      index() const noexcept
-      { return _M_index; };
+      constexpr chrono::weekday_indexed
+      weekday_indexed() const noexcept
+      { return _M_wdi; }
 
       constexpr bool
       ok() const noexcept
-      { return _M_wd.ok() && 1 <= _M_index && _M_index <= 5; }
+      { return _M_m.ok() && _M_wdi.ok(); }
 
       friend constexpr bool
-      operator==(const weekday_indexed& __x, const weekday_indexed& __y) noexcept
-      { return __x.weekday() == __y.weekday() && __x.index() == __y.index(); }
+      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 month& __m, const weekday_indexed& __wdi) noexcept;
+      operator/(const chrono::month& __m,
+               const chrono::weekday_indexed& __wdi) noexcept
+      { return {__m, __wdi}; }
 
       friend constexpr month_weekday
-      operator/(int __m, const weekday_indexed& __wdi) noexcept;
+      operator/(int __m, const chrono::weekday_indexed& __wdi) noexcept
+      { return chrono::month(unsigned(__m)) / __wdi; }
 
       friend constexpr month_weekday
-      operator/(const weekday_indexed& __wdi, const month& __m) noexcept;
+      operator/(const chrono::weekday_indexed& __wdi,
+               const chrono::month& __m) noexcept
+      { return __m / __wdi; }
 
       friend constexpr month_weekday
-      operator/(const weekday_indexed& __wdi, int __m) noexcept;
+      operator/(const chrono::weekday_indexed& __wdi, int __m) noexcept
+      { return __m / __wdi; }
 
       friend constexpr year_month_weekday
-      operator/(const year_month& __ym, const weekday_indexed& __wdi) noexcept;
+      operator/(int __y, const month_weekday& __mwd) noexcept;
 
-      // TODO: Implement operator<<.
+      friend constexpr year_month_weekday
+      operator/(const month_weekday& __mwd, int __y) noexcept;
     };
 
-    constexpr weekday_indexed
-    weekday::operator[](unsigned __index) const noexcept
-    { return {*this, __index}; }
-
-    // WEEKDAY_LAST
+    // MONTH_WEEKDAY_LAST
 
-    class weekday_last
+    class month_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;
+      chrono::month _M_m;
+      chrono::weekday_last _M_wdl;
 
     public:
       constexpr
@@ -2040,12 +1387,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       friend constexpr year_month_weekday_last
       operator/(const month_weekday_last& __mwdl, int __y) noexcept;
-
-      // TODO: Implement operator<<.
     };
 
     // YEAR_MONTH
 
+    namespace __detail
+    {
+      // [time.cal.ym], [time.cal.ymd], etc constrain the 'months'-based
+      // addition/subtraction operator overloads like so:
+      //
+      //   Constraints: if the argument supplied by the caller for the months
+      //   parameter is convertible to years, its implicit conversion sequence
+      //   to years is worse than its implicit conversion sequence to months.
+      //
+      // We realize this constraint by templatizing the 'months'-based
+      // overloads (using a dummy defaulted template parameter), so that
+      // overload resolution doesn't select the 'months'-based overload unless
+      // the implicit conversion sequence to 'months' is better than that to
+      // 'years'.
+      using __months_years_conversion_disambiguator = void;
+    }
+
     class year_month
     {
     private:
@@ -2068,19 +1430,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       month() const noexcept
       { return _M_m; }
 
-      constexpr year_month&
-      operator+=(const months& __dm) noexcept
-      {
-       *this = *this + __dm;
-       return *this;
-      }
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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;
-      }
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       constexpr year_month&
+       operator-=(const months& __dm) noexcept
+       {
+         *this = *this - __dm;
+         return *this;
+       }
 
       constexpr year_month&
       operator+=(const years& __dy)  noexcept
@@ -2108,25 +1472,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       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;
-      }
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       friend constexpr year_month
+       operator+(const year_month& __ym, const months& __dm) noexcept
+       {
+         // TODO: Optimize?
+         auto __m = __ym.month() + __dm;
+         auto __i = int(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; }
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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; }
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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
@@ -2161,8 +1528,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       friend constexpr year_month_day_last
       operator/(const year_month& __ym, last_spec) noexcept;
-
-      // TODO: Implement operator<<, from_stream.
     };
 
     // YEAR_MONTH_DAY
@@ -2200,19 +1565,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       : year_month_day(sys_days{__dp.time_since_epoch()})
       { }
 
-      constexpr year_month_day&
-      operator+=(const months& __m) noexcept
-      {
-       *this = *this + __m;
-       return *this;
-      }
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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;
-      }
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       constexpr year_month_day&
+       operator-=(const months& __m) noexcept
+       {
+         *this = *this - __m;
+         return *this;
+       }
 
       constexpr year_month_day&
       operator+=(const years& __y) noexcept
@@ -2262,13 +1629,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       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(); }
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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; }
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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
@@ -2278,9 +1647,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       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; }
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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
@@ -2309,44 +1679,73 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       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.
+    // Construct from days since 1970/01/01.
+    // Proposition 6.3 of Neri and Schneider,
+    // "Euclidean Affine Functions and Applications to Calendar Algorithms".
+    // https://arxiv.org/abs/2102.06959
     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)};
+      constexpr auto __z2    = static_cast<uint32_t>(-1468000);
+      constexpr auto __r2_e3 = static_cast<uint32_t>(536895458);
+
+      const auto __r0 = static_cast<uint32_t>(__dp.count()) + __r2_e3;
+
+      const auto __n1 = 4 * __r0 + 3;
+      const auto __q1 = __n1 / 146097;
+      const auto __r1 = __n1 % 146097 / 4;
+
+      constexpr auto __p32 = static_cast<uint64_t>(1) << 32;
+      const auto __n2 = 4 * __r1 + 3;
+      const auto __u2 = static_cast<uint64_t>(2939745) * __n2;
+      const auto __q2 = static_cast<uint32_t>(__u2 / __p32);
+      const auto __r2 = static_cast<uint32_t>(__u2 % __p32) / 2939745 / 4;
+
+      constexpr auto __p16 = static_cast<uint32_t>(1) << 16;
+      const auto __n3 = 2141 * __r2 + 197913;
+      const auto __q3 = __n3 / __p16;
+      const auto __r3 = __n3 % __p16 / 2141;
+
+      const auto __y0 = 100 * __q1 + __q2;
+      const auto __m0 = __q3;
+      const auto __d0 = __r3;
+
+      const auto __j  = __r2 >= 306;
+      const auto __y1 = __y0 + __j;
+      const auto __m1 = __j ? __m0 - 12 : __m0;
+      const auto __d1 = __d0 + 1;
+
+      return year_month_day{chrono::year{static_cast<int>(__y1 + __z2)},
+                           chrono::month{__m1}, chrono::day{__d1}};
     }
 
-    // Days since 1970/01/01. Magic.
+    // Days since 1970/01/01.
+    // Proposition 6.2 of Neri and Schneider,
+    // "Euclidean Affine Functions and Applications to Calendar Algorithms".
+    // https://arxiv.org/abs/2102.06959
     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};
+      auto constexpr __z2    = static_cast<uint32_t>(-1468000);
+      auto constexpr __r2_e3 = static_cast<uint32_t>(536895458);
+
+      const auto __y1 = static_cast<uint32_t>(static_cast<int>(_M_y)) - __z2;
+      const auto __m1 = static_cast<uint32_t>(static_cast<unsigned>(_M_m));
+      const auto __d1 = static_cast<uint32_t>(static_cast<unsigned>(_M_d));
+
+      const auto __j  = static_cast<uint32_t>(__m1 < 3);
+      const auto __y0 = __y1 - __j;
+      const auto __m0 = __j ? __m1 + 12 : __m1;
+      const auto __d0 = __d1 - 1;
+
+      const auto __q1 = __y0 / 100;
+      const auto __yc = 1461 * __y0 / 4 - __q1 + __q1 / 4;
+      const auto __mc = (979 *__m0 - 2919) / 32;
+      const auto __dc = __d0;
+
+      return days{static_cast<int32_t>(__yc + __mc + __dc - __r2_e3)};
     }
 
     // YEAR_MONTH_DAY_LAST
@@ -2364,19 +1763,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       : _M_y{__y}, _M_mdl{__mdl}
       { }
 
-      constexpr year_month_day_last&
-      operator+=(const months& __m) noexcept
-      {
-       *this = *this + __m;
-       return *this;
-      }
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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;
-      }
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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
@@ -2408,9 +1809,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       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]};
+       const auto __m = static_cast<unsigned>(month());
+
+       // The result is unspecified if __m < 1 or __m > 12.  Hence, assume
+       // 1 <= __m <= 12.  For __m != 2, day() == 30 or day() == 31 or, in
+       // other words, day () == 30 | b, where b is in {0, 1}.
+
+       // If __m in {1, 3, 4, 5, 6, 7}, then b is 1 if, and only if, __m is
+       // odd.  Hence, b = __m & 1 = (__m ^ 0) & 1.
+
+       // If __m in {8, 9, 10, 11, 12}, then b is 1 if, and only if, __m is
+       // even.  Hence, b = (__m ^ 1) & 1.
+
+       // Therefore, b = (__m ^ c) & 1, where c = 0, if __m < 8, or c = 1 if
+       // __m >= 8, that is, c = __m >> 3.
+
+       // Since 30 = (11110)_2 and __m <= 31 = (11111)_2, the "& 1" in b's
+       // calculation is unnecessary.
+
+       // The performance of this implementation does not depend on look-up
+       // tables being on the L1 cache.
+       return chrono::day{__m != 2 ? (__m ^ (__m >> 3)) | 30
+         : _M_y.is_leap() ? 29 : 28};
       }
 
       constexpr
@@ -2438,20 +1858,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                  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; }
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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; }
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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; }
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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,
@@ -2481,698 +1904,1433 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       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,
+               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; }
+    };
+
+    // 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()}}
+      { }
+
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       constexpr year_month_weekday&
+       operator+=(const months& __m) noexcept
+       {
+         *this = *this + __m;
+         return *this;
+       }
+
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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{(static_cast<int>(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.count() >= 1);
+       return (unsigned)__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_indexed() == __y.weekday_indexed();
+      }
+
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       friend constexpr year_month_weekday
+       operator+(const year_month_weekday& __ymwd, const months& __dm) noexcept
+       {
+         return ((__ymwd.year() / __ymwd.month() + __dm)
+                 / __ymwd.weekday_indexed());
+       }
+
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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; }
+
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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; }
+    };
+
+    // 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}
+      { }
+
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       constexpr year_month_weekday_last&
+       operator+=(const months& __m) noexcept
+       {
+         *this = *this + __m;
+         return *this;
+       }
+
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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();
+      }
+
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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());
+       }
+
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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; }
+
+      template<typename = __detail::__months_years_conversion_disambiguator>
+       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; }
+    };
+
+    // HH_MM_SS
+
+    /// @cond undocumented
+    namespace __detail
+    {
+      consteval long long
+      __pow10(unsigned __n)
+      {
+       long long __r = 1;
+       while (__n-- > 0)
+         __r *= 10;
+       return __r;
+      }
+
+      template<typename _Duration> struct __utc_leap_second;
+    }
+    /// @endcond
+
+    /** Utility for splitting a duration into hours, minutes, and seconds
+     *
+     * This is a convenience type that provides accessors for the constituent
+     * parts (hours, minutes, seconds and subseconds) of a duration.
+     *
+     * @since C++20
+     */
+    template<typename _Duration>
+      class hh_mm_ss
+      {
+       static_assert( __is_duration<_Duration>::value );
+
+      private:
+       static consteval int
+       _S_fractional_width()
+       {
+         auto __den = _Duration::period::den;
+         const int __multiplicity_2 = std::__countr_zero((uintmax_t)__den);
+         __den >>= __multiplicity_2;
+         int __multiplicity_5 = 0;
+         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;
+       }
+
+       constexpr
+       hh_mm_ss(_Duration __d, bool __is_neg)
+       : _M_h (duration_cast<chrono::hours>(__d)),
+         _M_m (duration_cast<chrono::minutes>(__d - hours())),
+         _M_s (duration_cast<chrono::seconds>(__d - hours() - minutes())),
+         _M_is_neg(__is_neg)
+       {
+         auto __ss = __d - hours() - minutes() - seconds();
+         if constexpr (treat_as_floating_point_v<typename precision::rep>)
+           _M_ss._M_r = __ss.count();
+         else if constexpr (precision::period::den != 1)
+           _M_ss._M_r = duration_cast<precision>(__ss).count();
+       }
+
+       static constexpr _Duration
+       _S_abs(_Duration __d)
+       {
+         if constexpr (numeric_limits<typename _Duration::rep>::is_signed)
+           return chrono::abs(__d);
+         else
+           return __d;
+       }
+
+      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 = default;
+
+       constexpr explicit
+       hh_mm_ss(_Duration __d)
+       : hh_mm_ss(_S_abs(__d), __d < _Duration::zero())
+       { }
+
+       constexpr bool
+       is_negative() const noexcept
+       {
+         if constexpr (!_S_is_unsigned)
+           return _M_is_neg;
+         else
+           return false;
+       }
+
+       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 static_cast<precision>(_M_ss); }
+
+       constexpr explicit
+       operator precision() const noexcept
+       { return to_duration(); }
+
+       constexpr precision
+       to_duration() const noexcept
+       {
+         if constexpr (!_S_is_unsigned)
+           if (_M_is_neg)
+             return -(_M_h + _M_m + _M_s + subseconds());
+         return _M_h + _M_m + _M_s + subseconds();
+       }
+
+      private:
+       static constexpr bool _S_is_unsigned
+         = __and_v<is_integral<typename _Duration::rep>,
+                   is_unsigned<typename _Duration::rep>>;
+
+       template<typename _Ratio>
+         using __byte_duration = duration<unsigned char, _Ratio>;
+
+       // The type of the _M_ss member that holds the subsecond precision.
+       template<typename _Dur>
+         struct __subseconds
+         {
+           typename _Dur::rep _M_r{};
+
+           constexpr explicit
+           operator _Dur() const noexcept
+           { return _Dur(_M_r); }
+         };
+
+       // An empty class if this precision doesn't need subseconds.
+       template<typename _Rep>
+         requires (!treat_as_floating_point_v<_Rep>)
+         struct __subseconds<duration<_Rep, ratio<1>>>
+         {
+           constexpr explicit
+           operator duration<_Rep, ratio<1>>() const noexcept
+           { return {}; }
+         };
+
+       template<typename _Rep, typename _Period>
+         requires (!treat_as_floating_point_v<_Rep>)
+           && ratio_less_v<_Period, ratio<1, 1>>
+           && ratio_greater_equal_v<_Period, ratio<1, 250>>
+         struct __subseconds<duration<_Rep, _Period>>
+         {
+           unsigned char _M_r{};
+
+           constexpr explicit
+           operator duration<_Rep, _Period>() const noexcept
+           { return duration<_Rep, _Period>(_M_r); }
+         };
+
+       template<typename _Rep, typename _Period>
+         requires (!treat_as_floating_point_v<_Rep>)
+           && ratio_less_v<_Period, ratio<1, 250>>
+           && ratio_greater_equal_v<_Period, ratio<1, 4000000000>>
+         struct __subseconds<duration<_Rep, _Period>>
+         {
+           uint_least32_t _M_r{};
+
+           constexpr explicit
+           operator duration<_Rep, _Period>() const noexcept
+           { return duration<_Rep, _Period>(_M_r); }
+         };
+
+       chrono::hours               _M_h{};
+       __byte_duration<ratio<60>>  _M_m{};
+       __byte_duration<ratio<1>>   _M_s{};
+       bool                        _M_is_neg{};
+       __subseconds<precision>     _M_ss{};
+
+       template<typename> friend struct __detail::__utc_leap_second;
+      };
+
+    /// @cond undocumented
+    namespace __detail
+    {
+      // Represents a time that is within a leap second insertion.
+      template<typename _Duration>
+       struct __utc_leap_second
+       {
+         explicit
+         __utc_leap_second(const sys_time<_Duration>& __s)
+         : _M_date(chrono::floor<days>(__s)), _M_time(__s - _M_date)
+         {
+           ++_M_time._M_s;
+         }
+
+         sys_days _M_date;
+         hh_mm_ss<common_type_t<_Duration, days>> _M_time;
+       };
+    }
+    /// @endcond
+
+    // 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;
+       }
+    }
+
+#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
+    // C++20 [time.zones] Time zones
 
-      friend constexpr year_month_day_last
-      operator/(const chrono::month_day_last& __mdl, int __y) noexcept
-      { return chrono::year(__y) / __mdl; }
+    struct tzdb;
 
-      // TODO: Implement operator<<.
+    struct sys_info
+    {
+      sys_seconds begin;
+      sys_seconds end;
+      seconds offset;
+      minutes save;
+      string abbrev;
     };
 
-    // 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
+    struct local_info
     {
-      if (!_M_y.ok() || !_M_m.ok())
-       return false;
-      return chrono::day{1} <= _M_d && _M_d <= (_M_y / _M_m / last).day();
-    }
+      static constexpr int unique      = 0;
+      static constexpr int nonexistent = 1;
+      static constexpr int ambiguous   = 2;
 
-    // YEAR_MONTH_WEEKDAY
+      int result;
+      sys_info first;
+      sys_info second;
+    };
 
-    class year_month_weekday
+    class nonexistent_local_time : public runtime_error
     {
-    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()}}
-      { }
+      template<typename _Duration>
+       nonexistent_local_time(const local_time<_Duration>& __tp,
+                              const local_info& __i)
+       : runtime_error(_S_make_what_str(__tp, __i))
+       { __glibcxx_assert(__i.result == local_info::nonexistent); }
 
-      constexpr year_month_weekday&
-      operator+=(const months& __m) noexcept
-      {
-       *this = *this + __m;
-       return *this;
-      }
+    private:
+      template<typename _Duration>
+       static string
+       _S_make_what_str(const local_time<_Duration>& __tp,
+                        const local_info& __i)
+       {
+         std::ostringstream __os;
+         __os << __tp << " is in a gap between\n"
+              << local_seconds(__i.first.end.time_since_epoch())
+              + __i.first.offset << ' ' << __i.first.abbrev << " and\n"
+              << local_seconds(__i.second.begin.time_since_epoch())
+              + __i.second.offset << ' ' << __i.second.abbrev
+              << " which are both equivalent to\n"
+              << __i.first.end << " UTC";
+         return std::move(__os).str();
+       }
+    };
 
-      constexpr year_month_weekday&
-      operator-=(const months& __m) noexcept
-      {
-       *this = *this - __m;
-       return *this;
-      }
+    class ambiguous_local_time : public runtime_error
+    {
+    public:
+      template<typename _Duration>
+       ambiguous_local_time(const local_time<_Duration>& __tp,
+                            const local_info& __i)
+       : runtime_error(_S_make_what_str(__tp, __i))
+       { __glibcxx_assert(__i.result == local_info::ambiguous); }
 
-      constexpr year_month_weekday&
-      operator+=(const years& __y) noexcept
-      {
-       *this = *this + __y;
-       return *this;
-      }
+    private:
+      template<typename _Duration>
+       static string
+       _S_make_what_str(const local_time<_Duration>& __tp,
+                        const local_info& __i)
+       {
+         std::ostringstream __os;
+         __os << __tp << " is ambiguous.  It could be\n"
+              << __tp << ' ' << __i.first.abbrev << " == "
+              << __tp - __i.first.offset << " UTC or\n"
+              << __tp << ' ' << __i.second.abbrev << " == "
+              << __tp - __i.second.offset << " UTC";
+         return std::move(__os).str();
+       }
+    };
 
-      constexpr year_month_weekday&
-      operator-=(const years& __y) noexcept
-      {
-       *this = *this - __y;
-       return *this;
+    template<typename _Duration>
+      [[noreturn]] void
+      __throw_bad_local_time(const local_time<_Duration>& __tp,
+                            const local_info& __i)
+      {
+#if __cpp_exceptions
+       if (__i.result == local_info::nonexistent)
+         throw nonexistent_local_time(__tp, __i);
+       throw ambiguous_local_time(__tp, __i);
+#else
+       __builtin_abort();
+#endif
       }
 
-      constexpr chrono::year
-      year() const noexcept
-      { return _M_y; }
+    enum class choose { earliest, latest };
 
-      constexpr chrono::month
-      month() const noexcept
-      { return _M_m; }
+    class time_zone
+    {
+    public:
+      time_zone(time_zone&&) = default;
+      time_zone& operator=(time_zone&&) = default;
 
-      constexpr chrono::weekday
-      weekday() const noexcept
-      { return _M_wdi.weekday(); }
+      ~time_zone();
 
-      constexpr unsigned
-      index() const noexcept
-      { return _M_wdi.index(); }
+      [[nodiscard]]
+      string_view name() const noexcept { return _M_name; }
 
-      constexpr chrono::weekday_indexed
-      weekday_indexed() const noexcept
-      { return _M_wdi; }
+      template<typename _Duration>
+       sys_info
+       get_info(const sys_time<_Duration>& __st) const
+       { return _M_get_sys_info(chrono::floor<seconds>(__st)); }
 
-      constexpr
-      operator sys_days() const noexcept
-      {
-       auto __d = sys_days{year() / month() / 1};
-       return __d + (weekday() - chrono::weekday(__d) + days{(index()-1)*7});
-      }
+      template<typename _Duration>
+       local_info
+       get_info(const local_time<_Duration>& __tp) const
+       { return _M_get_local_info(chrono::floor<seconds>(__tp)); }
 
-      explicit constexpr
-      operator local_days() const noexcept
-      { return local_days{sys_days{*this}.time_since_epoch()}; }
+      template<typename _Duration>
+       sys_time<common_type_t<_Duration, seconds>>
+       to_sys(const local_time<_Duration>& __tp) const
+       {
+         local_info __info = get_info(__tp);
 
-      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()};
-      }
+         if (__info.result != local_info::unique)
+           __throw_bad_local_time(__tp, __info);
 
-      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();
-      }
+         return sys_time<_Duration>(__tp.time_since_epoch())
+                  - __info.first.offset;
+       }
 
-      friend constexpr year_month_weekday
-      operator+(const year_month_weekday& __ymwd, const months& __dm) noexcept
-      { return (__ymwd.year() / __ymwd.month() + __dm) / __ymwd.weekday_indexed(); }
+      template<typename _Duration>
+       sys_time<common_type_t<_Duration, seconds>>
+       to_sys(const local_time<_Duration>& __tp, choose __z) const
+       {
+         local_info __info = get_info(__tp);
 
-      friend constexpr year_month_weekday
-      operator+(const months& __dm, const year_month_weekday& __ymwd) noexcept
-      { return __ymwd + __dm; }
+         if (__info.result == local_info::nonexistent)
+           return __info.first.end; // Last second of the previous sys_info.
 
-      friend constexpr year_month_weekday
-      operator+(const year_month_weekday& __ymwd, const years& __dy) noexcept
-      { return {__ymwd.year() + __dy, __ymwd.month(), __ymwd.weekday_indexed()}; }
+         sys_time<_Duration> __st(__tp.time_since_epoch());
 
-      friend constexpr year_month_weekday
-      operator+(const years& __dy, const year_month_weekday& __ymwd) noexcept
-      { return __ymwd + __dy; }
+         if (__info.result == local_info::ambiguous && __z == choose::latest)
+           return __st - __info.second.offset; // Time in the later sys_info.
+         // else if __z == earliest, use __info.first.offset as below:
 
-      friend constexpr year_month_weekday
-      operator-(const year_month_weekday& __ymwd, const months& __dm) noexcept
-      { return __ymwd + -__dm; }
+         return __st - __info.first.offset;
+       }
 
-      friend constexpr year_month_weekday
-      operator-(const year_month_weekday& __ymwd, const years& __dy) noexcept
-      { return __ymwd + -__dy; }
+      template<typename _Duration>
+       local_time<common_type_t<_Duration, seconds>>
+       to_local(const sys_time<_Duration>& __tp) const
+       {
+         auto __d = (__tp + get_info(__tp).offset).time_since_epoch();
+         return local_time<common_type_t<_Duration, seconds>>(__d);
+       }
 
-      friend constexpr year_month_weekday
-      operator/(const year_month& __ym,
-               const chrono::weekday_indexed& __wdi) noexcept
-      { return {__ym.year(), __ym.month(), __wdi}; }
+      [[nodiscard]] friend bool
+      operator==(const time_zone& __x, const time_zone& __y) noexcept
+      { return __x._M_name == __y._M_name; }
 
-      friend constexpr year_month_weekday
-      operator/(const chrono::year& __y, const month_weekday& __mwd) noexcept
-      { return {__y, __mwd.month(), __mwd.weekday_indexed()}; }
+      [[nodiscard]] friend strong_ordering
+      operator<=>(const time_zone& __x, const time_zone& __y) noexcept
+      { return __x._M_name <=> __y._M_name; }
 
-      friend constexpr year_month_weekday
-      operator/(int __y, const month_weekday& __mwd) noexcept
-      { return chrono::year(__y) / __mwd; }
+    private:
+      sys_info _M_get_sys_info(sys_seconds) const;
+      local_info _M_get_local_info(local_seconds) const;
 
-      friend constexpr year_month_weekday
-      operator/(const month_weekday& __mwd, const chrono::year& __y) noexcept
-      { return __y / __mwd; }
+      friend const tzdb& reload_tzdb();
+      friend struct tzdb;
+      friend class tzdb_list;
 
-      friend constexpr year_month_weekday
-      operator/(const month_weekday& __mwd, int __y) noexcept
-      { return chrono::year(__y) / __mwd; }
+      struct _Impl;
 
-      // TODO: Implement operator<<.
+      explicit time_zone(unique_ptr<_Impl> __p);
+      string _M_name;
+      unique_ptr<_Impl> _M_impl;
     };
 
-    // YEAR_MONTH_WEEKDAY_LAST
+    const time_zone* locate_zone(string_view __tz_name);
+    const time_zone* current_zone();
 
-    class year_month_weekday_last
+    /** The list of `chrono::tzdb` objects
+     *
+     * A single object of this type is constructed by the C++ runtime,
+     * and can be accessed by calling `chrono::get_tzdb_list()`.
+     *
+     * The front of the list is the current `tzdb` object and can be accessed
+     * via `chrono::get_tzdb_list().front()` or `chrono::get_tzdb()` or
+     * `*chrono::get_tzdb_list().begin()`.
+     *
+     * The `chrono::reload_tzdb()` function will check for a newer version
+     * and if found, insert it at the front of the list.
+     *
+     * @since C++20
+     */
+    class tzdb_list
     {
-    private:
-      chrono::year _M_y;
-      chrono::month _M_m;
-      chrono::weekday_last _M_wdl;
+      struct _Node;
 
     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
+      tzdb_list(const tzdb_list&) = delete;
+      tzdb_list& operator=(const tzdb_list&) = delete;
+
+      /** An iterator into the `tzdb_list`
+       *
+       * As a extension, in libstdc++ each `tzdb` is reference-counted
+       * and the `const_iterator` type shares ownership of the object it
+       * refers to. This ensures that a `tzdb` erased from the list will
+       * not be destroyed while there is an iterator that refers to it.
+       */
+      class const_iterator
       {
-       *this = *this + __y;
-       return *this;
-      }
+      public:
+       using value_type        = tzdb;
+       using reference         = const tzdb&;
+       using pointer           = const tzdb*;
+       using difference_type   = ptrdiff_t;
+       using iterator_category = forward_iterator_tag;
 
-      constexpr year_month_weekday_last&
-      operator-=(const years& __y)  noexcept
-      {
-       *this = *this - __y;
-       return *this;
-      }
+       constexpr const_iterator() = default;
+       const_iterator(const const_iterator&) = default;
+       const_iterator(const_iterator&&) = default;
+       const_iterator& operator=(const const_iterator&) = default;
+       const_iterator& operator=(const_iterator&&) = default;
 
-      constexpr chrono::year
-      year() const noexcept
-      { return _M_y; }
+       reference operator*() const noexcept;
+       pointer operator->() const noexcept { return &**this; }
+       const_iterator& operator++();
+       const_iterator operator++(int);
 
-      constexpr chrono::month
-      month() const noexcept
-      { return _M_m; }
+       bool operator==(const const_iterator&) const noexcept = default;
 
-      constexpr chrono::weekday
-      weekday() const noexcept
-      { return _M_wdl.weekday(); }
+      private:
+       explicit const_iterator(const shared_ptr<_Node>&) noexcept;
 
-      constexpr chrono::weekday_last
-      weekday_last() const noexcept
-      { return _M_wdl; }
+       friend class tzdb_list;
 
-      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()};
-      }
+       shared_ptr<_Node> _M_node;
+       void* _M_reserved = nullptr;
+      };
 
-      explicit constexpr
-      operator local_days() const noexcept
-      { return local_days{sys_days{*this}.time_since_epoch()}; }
+      /** Access the current `tzdb` at the front of the list.
+       *
+       * This returns a reference to the same object as `chrono::get_tzdb()`.
+       *
+       * @returns A reference to the current tzdb object.
+       * @since C++20
+       */
+      const tzdb& front() const noexcept;
+
+      /** Remove the tzdb object _after_ the one the iterator refers to.
+       *
+       * Calling this function concurently with any of `front()`, `begin()`,
+       * or `end()` does not cause a data race, but in general this function
+       * is not thread-safe. The behaviour may be undefined if erasing an
+       * element from the list while another thread is calling the same
+       * function, or incrementing an iterator into the list, or accessing
+       * the element being erased (unless it is accessed through an iterator).
+       *
+       * @param __p A dereferenceable iterator.
+       * @returns An iterator the element after the one that was erased
+       *          (or `end()` if there is no such element).
+       * @since C++20
+       */
+      const_iterator erase_after(const_iterator __p);
+
+      const_iterator begin() const noexcept;
+      const_iterator end() const noexcept { return {}; }
+      const_iterator cbegin() const noexcept { return begin(); }
+      const_iterator cend() const noexcept { return end(); }
 
-      constexpr bool
-      ok() const noexcept
-      { return _M_y.ok() && _M_m.ok() && _M_wdl.ok(); }
+    private:
+      constexpr explicit tzdb_list(nullptr_t);
+
+      friend tzdb_list& get_tzdb_list();
+      friend const tzdb& get_tzdb();
+      friend const tzdb& reload_tzdb();
+      friend struct tzdb;
+      friend class leap_second;
+      friend struct time_zone::_Impl;
+      friend class time_zone_link;
+    };
 
-      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();
-      }
+    class time_zone_link
+    {
+    public:
+      time_zone_link(time_zone_link&&) = default;
+      time_zone_link& operator=(time_zone_link&&) = default;
 
-      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(); }
+      string_view name() const noexcept { return _M_name; }
+      string_view target() const noexcept { return _M_target; }
 
-      friend constexpr year_month_weekday_last
-      operator+(const months& __dm,
-               const year_month_weekday_last& __ymwdl) noexcept
-      { return __ymwdl + __dm; }
+      friend bool
+      operator==(const time_zone_link& __x, const time_zone_link& __y) noexcept
+      { return __x.name() == __y.name(); }
 
-      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 strong_ordering
+      operator<=>(const time_zone_link& __x, const time_zone_link& __y) noexcept
+      { return __x.name() <=> __y.name(); }
 
-      friend constexpr year_month_weekday_last
-      operator+(const years& __dy,
-               const year_month_weekday_last& __ymwdl) noexcept
-      { return __ymwdl + __dy; }
+    private:
+      friend const tzdb& reload_tzdb();
+      friend struct tzdb_list::_Node;
 
-      friend constexpr year_month_weekday_last
-      operator-(const year_month_weekday_last& __ymwdl,
-               const months& __dm) noexcept
-      { return __ymwdl + -__dm; }
+      explicit time_zone_link(nullptr_t) { }
 
-      friend constexpr year_month_weekday_last
-      operator-(const year_month_weekday_last& __ymwdl,
-               const years& __dy) noexcept
-      { return __ymwdl + -__dy; }
+      string _M_name;
+      string _M_target;
+    };
 
-      friend constexpr year_month_weekday_last
-      operator/(const year_month& __ym,
-               const chrono::weekday_last& __wdl) noexcept
-      { return {__ym.year(), __ym.month(), __wdl}; }
+    class leap_second
+    {
+    public:
+      leap_second(const leap_second&) = default;
+      leap_second& operator=(const leap_second&) = default;
+
+      [[nodiscard]]
+      constexpr sys_seconds
+      date() const noexcept
+      {
+       if (_M_s >= _M_s.zero()) [[likely]]
+         return sys_seconds(_M_s);
+       return sys_seconds(-_M_s);
+      }
+
+      [[nodiscard]]
+      constexpr seconds
+      value() const noexcept
+      {
+       if (_M_s >= _M_s.zero()) [[likely]]
+         return seconds(1);
+       return seconds(-1);
+      }
+
+      // This can be defaulted because the database will never contain two
+      // leap_second objects with the same date but different signs.
+      [[nodiscard]] friend constexpr bool
+      operator==(const leap_second&, const leap_second&) noexcept = default;
+
+      [[nodiscard]] friend constexpr strong_ordering
+      operator<=>(const leap_second& __x, const leap_second& __y) noexcept
+      { return __x.date() <=> __y.date(); }
+
+      template<typename _Duration>
+       [[nodiscard]] friend constexpr bool
+       operator==(const leap_second& __x,
+                  const sys_time<_Duration>& __y) noexcept
+       { return __x.date() == __y; }
+
+      template<typename _Duration>
+       [[nodiscard]] friend constexpr bool
+       operator<(const leap_second& __x,
+                 const sys_time<_Duration>& __y) noexcept
+       { return __x.date() < __y; }
+
+      template<typename _Duration>
+       [[nodiscard]] friend constexpr bool
+       operator<(const sys_time<_Duration>& __x,
+                 const leap_second& __y) noexcept
+       { return __x < __y.date(); }
+
+      template<typename _Duration>
+       [[nodiscard]] friend constexpr bool
+       operator>(const leap_second& __x,
+                 const sys_time<_Duration>& __y) noexcept
+       { return __y < __x.date(); }
+
+      template<typename _Duration>
+       [[nodiscard]] friend constexpr bool
+       operator>(const sys_time<_Duration>& __x,
+                 const leap_second& __y) noexcept
+       { return __y.date() < __x; }
+
+      template<typename _Duration>
+       [[nodiscard]] friend constexpr bool
+       operator<=(const leap_second& __x,
+                  const sys_time<_Duration>& __y) noexcept
+       { return !(__y < __x.date()); }
+
+      template<typename _Duration>
+       [[nodiscard]] friend constexpr bool
+       operator<=(const sys_time<_Duration>& __x,
+                  const leap_second& __y) noexcept
+       { return !(__y.date() < __x); }
+
+      template<typename _Duration>
+       [[nodiscard]] friend constexpr bool
+       operator>=(const leap_second& __x,
+                  const sys_time<_Duration>& __y) noexcept
+       { return !(__x.date() < __y); }
+
+      template<typename _Duration>
+       [[nodiscard]] friend constexpr bool
+       operator>=(const sys_time<_Duration>& __x,
+                  const leap_second& __y) noexcept
+       { return !(__x < __y.date()); }
+
+      template<three_way_comparable_with<seconds> _Duration>
+       [[nodiscard]] friend constexpr auto
+       operator<=>(const leap_second& __x,
+                   const sys_time<_Duration>& __y) noexcept
+       { return __x.date() <=> __y; }
 
-      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()}; }
+    private:
+      explicit leap_second(seconds::rep __s) : _M_s(__s) { }
 
-      friend constexpr year_month_weekday_last
-      operator/(int __y, const chrono::month_weekday_last& __mwdl) noexcept
-      { return chrono::year(__y) / __mwdl; }
+      friend struct tzdb_list::_Node;
 
-      friend constexpr year_month_weekday_last
-      operator/(const chrono::month_weekday_last& __mwdl,
-               const chrono::year& __y) noexcept
-      { return __y / __mwdl; }
+      friend const tzdb& reload_tzdb();
 
-      friend constexpr year_month_weekday_last
-      operator/(const chrono::month_weekday_last& __mwdl, int __y) noexcept
-      { return chrono::year(__y) / __mwdl; }
+      template<typename _Duration>
+       friend leap_second_info
+       get_leap_second_info(const utc_time<_Duration>&);
 
-      // TODO: Implement operator<<.
+      seconds _M_s; // == date().time_since_epoch() * value().count()
     };
 
-    // HH_MM_SS
+    template<class _Tp> struct zoned_traits { };
 
-    namespace __detail
-    {
-      consteval long long
-      __pow10(unsigned __n)
+    template<>
+      struct zoned_traits<const time_zone*>
       {
-       long long __r = 1;
-       while (__n-- > 0)
-         __r *= 10;
-       return __r;
-      }
-    }
+       static const time_zone*
+       default_zone()
+       { return std::chrono::locate_zone("UTC"); }
 
-    template<typename _Duration>
-      class hh_mm_ss
+       static const time_zone*
+       locate_zone(string_view __name)
+       { return std::chrono::locate_zone(__name); }
+      };
+
+    struct tzdb
+    {
+      string version;
+      _GLIBCXX_STD_C::vector<time_zone> zones;
+      _GLIBCXX_STD_C::vector<time_zone_link> links;
+      _GLIBCXX_STD_C::vector<leap_second> leap_seconds;
+
+      const time_zone*
+      locate_zone(string_view __tz_name) const;
+
+      const time_zone*
+      current_zone() const;
+
+    private:
+      friend const tzdb& reload_tzdb();
+      friend class time_zone;
+      friend struct tzdb_list::_Node;
+    };
+
+    tzdb_list& get_tzdb_list();
+    const tzdb& get_tzdb();
+
+    const tzdb& reload_tzdb();
+    string remote_version();
+
+    template<typename _Duration, typename _TimeZonePtr = const time_zone*>
+      class zoned_time
       {
-      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;
+       static_assert(__is_duration_v<_Duration>);
 
-         int __width = (__multiplicity_2 > __multiplicity_5
-                        ? __multiplicity_2 : __multiplicity_5);
-         if (__width > 18)
-           __width = 18;
-         return __width;
-       }
+       using _Traits = zoned_traits<_TimeZonePtr>;
+
+       // Every constructor that accepts a string_view as its first parameter
+       // does not participate in class template argument deduction.
+       using string_view = type_identity_t<std::string_view>;
 
       public:
-       static constexpr unsigned fractional_width = {_S_fractional_width()};
+       using duration = common_type_t<_Duration, seconds>;
 
-       using precision
-         = duration<common_type_t<typename _Duration::rep,
-                                  chrono::seconds::rep>,
-                    ratio<1, __detail::__pow10(fractional_width)>>;
+       zoned_time() requires requires { _Traits::default_zone(); }
+       { }
 
-       constexpr
-       hh_mm_ss() noexcept
-       : hh_mm_ss{_Duration::zero()}
+       zoned_time(const zoned_time&) = default;
+       zoned_time& operator=(const zoned_time&) = default;
+
+       zoned_time(const sys_time<_Duration>& __st)
+         requires requires { _Traits::default_zone(); }
+       : _M_tp(__st)
        { }
 
-       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());
+       explicit
+       zoned_time(_TimeZonePtr __z) : _M_zone(std::move(__z)) { }
+
+       explicit
+       zoned_time(string_view __name)
+         requires requires {
+           _TimeZonePtr{_Traits::locate_zone(std::string_view{})};
+         }
+       : _M_zone(_Traits::locate_zone(__name))
+       { }
+
+       template<typename _Duration2>
+         zoned_time(const zoned_time<_Duration2, _TimeZonePtr>& __zt)
+         requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>
+         : _M_zone(__zt._M_zone), _M_tp(__zt._M_tp)
+         { }
+
+       zoned_time(_TimeZonePtr __z, const sys_time<_Duration>& __st)
+       : _M_zone(std::move(__z)), _M_tp(__st)
+       { }
+
+       zoned_time(string_view __name, const sys_time<_Duration>& __st)
+       : zoned_time(_Traits::locate_zone(__name), __st)
+       { }
+
+       zoned_time(_TimeZonePtr __z, const local_time<_Duration>& __tp)
+       requires requires {
+         { __z->to_sys(__tp) } -> convertible_to<sys_time<_Duration>>;
        }
+       : _M_zone(std::move(__z)), _M_tp(_M_zone->to_sys(__tp))
+       { }
 
-       constexpr bool
-       is_negative() const noexcept
-       { return _M_is_neg; }
+       zoned_time(string_view __name, const local_time<_Duration>& __tp)
+       requires requires (_TimeZonePtr __z) {
+         { _Traits::locate_zone(__name) } -> convertible_to<_TimeZonePtr>;
+         { __z->to_sys(__tp) } -> convertible_to<sys_time<_Duration>>;
+       }
+       : zoned_time(_Traits::locate_zone(__name), __tp)
+       { }
 
-       constexpr chrono::hours
-       hours() const noexcept
-       { return _M_h; }
+       zoned_time(_TimeZonePtr __z, const local_time<_Duration>& __tp,
+                  choose __c)
+       requires requires {
+         { __z->to_sys(__tp, __c) } -> convertible_to<sys_time<_Duration>>;
+       }
+       : _M_zone(std::move(__z)), _M_tp(_M_zone->to_sys(__tp, __c))
+       { }
 
-       constexpr chrono::minutes
-       minutes() const noexcept
-       { return _M_m; }
+       zoned_time(string_view __name, const local_time<_Duration>& __tp,
+                  choose __c)
+       requires requires (_TimeZonePtr __z) {
+         { _Traits::locate_zone(__name) } -> convertible_to<_TimeZonePtr>;
+         { __z->to_sys(__tp, __c) } -> convertible_to<sys_time<_Duration>>;
+       }
+       : _M_zone(_Traits::locate_zone(__name)),
+         _M_tp(_M_zone->to_sys(__tp, __c))
+       { }
 
-       constexpr chrono::seconds
-       seconds() const noexcept
-       { return _M_s; }
+       template<typename _Duration2, typename _TimeZonePtr2>
+         zoned_time(_TimeZonePtr __z,
+                    const zoned_time<_Duration2, _TimeZonePtr2>& __zt)
+         requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>
+         : _M_zone(__z), _M_tp(__zt._M_tp)
+         { }
 
-       constexpr precision
-       subseconds() const noexcept
-       { return _M_ss; }
+       template<typename _Duration2, typename _TimeZonePtr2>
+         zoned_time(_TimeZonePtr __z,
+                    const zoned_time<_Duration2, _TimeZonePtr2>& __zt,
+                    choose)
+         requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>
+         : _M_zone(__z), _M_tp(__zt._M_tp)
+         { }
 
-       constexpr explicit
-       operator precision() const noexcept
-       { return to_duration(); }
+       template<typename _Duration2, typename _TimeZonePtr2>
+         zoned_time(string_view __name,
+                    const zoned_time<_Duration2, _TimeZonePtr2>& __zt)
+         requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>
+         && requires {
+           { _Traits::locate_zone(__name) } -> convertible_to<_TimeZonePtr>;
+         }
+         : _M_zone(_Traits::locate_zone(__name)), _M_tp(__zt._M_tp)
+         { }
 
-       constexpr precision
-       to_duration() const noexcept
+       template<typename _Duration2, typename _TimeZonePtr2>
+         zoned_time(string_view __name,
+                    const zoned_time<_Duration2, _TimeZonePtr2>& __zt,
+                    choose)
+         requires is_convertible_v<sys_time<_Duration2>, sys_time<_Duration>>
+         && requires {
+           { _Traits::locate_zone(__name) } -> convertible_to<_TimeZonePtr>;
+         }
+         : _M_zone(_Traits::locate_zone(__name)), _M_tp(__zt._M_tp)
+         { }
+
+       zoned_time&
+       operator=(const sys_time<_Duration>& __st)
        {
-         if (_M_is_neg)
-           return -(_M_h + _M_m + _M_s + _M_ss);
-         else
-           return _M_h + _M_m + _M_s + _M_ss;
+         _M_tp = __st;
+         return *this;
        }
 
-       // TODO: Implement operator<<.
+       zoned_time&
+       operator=(const local_time<_Duration>& __lt)
+       {
+         _M_tp = _M_zone->to_sys(__lt);
+         return *this;
+       }
 
-      private:
-       bool _M_is_neg;
-       chrono::hours _M_h;
-       chrono::minutes _M_m;
-       chrono::seconds _M_s;
-       precision _M_ss;
-      };
-#endif // C++20
+       [[nodiscard]]
+       operator sys_time<duration>() const { return _M_tp; }
 
-    // @}
-  } // namespace chrono
+       [[nodiscard]]
+       explicit operator local_time<duration>() const
+       { return get_local_time(); }
 
-#if __cplusplus > 201103L
+       [[nodiscard]]
+       _TimeZonePtr
+       get_time_zone() const
+       { return _M_zone; }
 
-#define __cpp_lib_chrono_udls 201304
+       [[nodiscard]]
+       local_time<duration>
+       get_local_time() const
+       { return _M_zone->to_local(_M_tp); }
 
-  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
+       [[nodiscard]]
+       sys_time<duration>
+       get_sys_time() const
+       { return _M_tp; }
 
-    /// 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)}; }
+       [[nodiscard]]
+       sys_info
+       get_info() const
+       { return _M_zone->get_info(_M_tp); }
 
-    constexpr chrono::year
-    operator""y(unsigned long long __y) noexcept
-    { return chrono::year{static_cast<int>(__y)}; }
-#endif // C++20
+       [[nodiscard]] friend bool
+       operator==(const zoned_time&, const zoned_time&) = default;
 
-#pragma GCC diagnostic pop
-  } // inline namespace chrono_literals
-  } // inline namespace literals
+      private:
+       _TimeZonePtr       _M_zone{ _Traits::default_zone() };
+       sys_time<duration> _M_tp{};
 
-  namespace chrono
-  {
-    using namespace literals::chrono_literals;
-  } // namespace chrono
+       template<typename _Duration2, typename _TimeZonePtr2>
+         friend class zoned_time;
+      };
 
-#if __cplusplus > 201703L
-  namespace chrono
-  {
-    // 12/24 HOURS FUNCTIONS
+    zoned_time() -> zoned_time<seconds>;
 
-    constexpr bool
-    is_am(const hours& __h) noexcept
-    { return 0h <= __h && __h <= 11h; }
+    template<typename _Duration>
+    zoned_time(sys_time<_Duration>)
+      -> zoned_time<common_type_t<_Duration, seconds>>;
 
-    constexpr bool
-    is_pm(const hours& __h) noexcept
-    { return 12h <= __h && __h <= 23h; }
+  /// @cond undocumented
+  template<typename _TimeZonePtrOrName>
+    using __time_zone_representation
+      = __conditional_t<is_convertible_v<_TimeZonePtrOrName, string_view>,
+                       const time_zone*,
+                       remove_cvref_t<_TimeZonePtrOrName>>;
+  /// @endcond
 
-    constexpr hours
-    make12(const hours& __h) noexcept
+  template<typename _TimeZonePtrOrName>
+    zoned_time(_TimeZonePtrOrName&&)
+      -> zoned_time<seconds, __time_zone_representation<_TimeZonePtrOrName>>;
+
+  template<typename _TimeZonePtrOrName, typename _Duration>
+    zoned_time(_TimeZonePtrOrName&&, sys_time<_Duration>)
+      -> zoned_time<common_type_t<_Duration, seconds>,
+                    __time_zone_representation<_TimeZonePtrOrName>>;
+
+  template<typename _TimeZonePtrOrName, typename _Duration>
+    zoned_time(_TimeZonePtrOrName&&, local_time<_Duration>,
+               choose = choose::earliest)
+      -> zoned_time<common_type_t<_Duration, seconds>,
+                    __time_zone_representation<_TimeZonePtrOrName>>;
+
+  template<typename _Duration, typename _TimeZonePtrOrName,
+          typename _TimeZonePtr2>
+    zoned_time(_TimeZonePtrOrName&&, zoned_time<_Duration, _TimeZonePtr2>,
+               choose = choose::earliest)
+      -> zoned_time<common_type_t<_Duration, seconds>,
+                    __time_zone_representation<_TimeZonePtrOrName>>;
+
+  template<typename _Dur1, typename _TZPtr1, typename _Dur2, typename _TZPtr2>
+    [[nodiscard]]
+    inline bool
+    operator==(const zoned_time<_Dur1, _TZPtr1>& __x,
+              const zoned_time<_Dur2, _TZPtr2>& __y)
     {
-      if (__h == 0h)
-       return 12h;
-      else if (__h > 12h)
-       return __h - 12h;
-      return __h;
+      return __x.get_time_zone() == __y.get_time_zone()
+              && __x.get_sys_time() == __y.get_sys_time();
     }
 
-    constexpr hours
-    make24(const hours& __h, bool __is_pm) noexcept
+    using zoned_seconds = zoned_time<seconds>;
+#endif // _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
+
+namespace __detail
+{
+    inline leap_second_info
+    __get_leap_second_info(sys_seconds __ss, bool __is_utc)
     {
-      if (!__is_pm)
+      if (__ss < sys_seconds{}) [[unlikely]]
+       return {};
+
+      const seconds::rep __leaps[] {
+         78796800, // 1 Jul 1972
+         94694400, // 1 Jan 1973
+        126230400, // 1 Jan 1974
+        157766400, // 1 Jan 1975
+        189302400, // 1 Jan 1976
+        220924800, // 1 Jan 1977
+        252460800, // 1 Jan 1978
+        283996800, // 1 Jan 1979
+        315532800, // 1 Jan 1980
+        362793600, // 1 Jul 1981
+        394329600, // 1 Jul 1982
+        425865600, // 1 Jul 1983
+        489024000, // 1 Jul 1985
+        567993600, // 1 Jan 1988
+        631152000, // 1 Jan 1990
+        662688000, // 1 Jan 1991
+        709948800, // 1 Jul 1992
+        741484800, // 1 Jul 1993
+        773020800, // 1 Jul 1994
+        820454400, // 1 Jan 1996
+        867715200, // 1 Jul 1997
+        915148800, // 1 Jan 1999
+       1136073600, // 1 Jan 2006
+       1230768000, // 1 Jan 2009
+       1341100800, // 1 Jul 2012
+       1435708800, // 1 Jul 2015
+       1483228800, // 1 Jan 2017
+      };
+      // The list above is known to be valid until (at least) this date
+      // and only contains positive leap seconds.
+      const sys_seconds __expires(1703721600s); // 2023-12-28 00:00:00 UTC
+
+#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
+      if (__ss > __expires)
        {
-         if (__h == 12h)
-           return 0h;
-         else
-           return __h;
+         // Use updated leap_seconds from tzdb.
+         size_t __n = std::size(__leaps);
+
+         auto __db = get_tzdb_list().begin();
+         auto __first = __db->leap_seconds.begin() + __n;
+         auto __last = __db->leap_seconds.end();
+         auto __pos = std::upper_bound(__first, __last, __ss);
+         seconds __elapsed(__n);
+         for (auto __i = __first; __i != __pos; ++__i)
+           __elapsed += __i->value();
+
+         if (__is_utc)
+           {
+             // Convert utc_time to sys_time:
+             __ss -= __elapsed;
+             // See if that sys_time is before (or during) previous leap sec:
+             if (__pos != __first && __ss < __pos[-1])
+               {
+                 if ((__ss + 1s) >= __pos[-1])
+                   return {true, __elapsed};
+                 __elapsed -= __pos[-1].value();
+               }
+           }
+         return {false, __elapsed};
        }
       else
+#endif
        {
-         if (__h == 12h)
-           return __h;
-         else
-           return __h + 12h;
+         seconds::rep __s = __ss.time_since_epoch().count();
+         const seconds::rep* __first = std::begin(__leaps);
+         const seconds::rep* __last = std::end(__leaps);
+
+         // Don't bother searching the list if we're after the last one.
+         if (__s > (__last[-1] + (__last - __first) + 1))
+           return { false, seconds(__last - __first) };
+
+         auto __pos = std::upper_bound(__first, __last, __s);
+         seconds __elapsed{__pos - __first};
+         if (__is_utc)
+           {
+             // Convert utc_time to sys_time:
+             __s -= __elapsed.count();
+             // See if that sys_time is before (or during) previous leap sec:
+             if (__pos != __first && __s < __pos[-1])
+               {
+                 if ((__s + 1) >= __pos[-1])
+                   return {true, __elapsed};
+                 --__elapsed;
+               }
+           }
+         return {false, __elapsed};
        }
     }
-  }
-#endif
+} // namespace __detail
 
-#if __cplusplus >= 201703L
-  namespace filesystem
-  {
-    struct __file_clock
-    {
-      using duration                  = chrono::nanoseconds;
-      using rep                       = duration::rep;
-      using period                    = duration::period;
-      using time_point                = chrono::time_point<__file_clock>;
-      static constexpr bool is_steady = false;
+    template<typename _Duration>
+      [[nodiscard]]
+      inline leap_second_info
+      get_leap_second_info(const utc_time<_Duration>& __ut)
+      {
+       auto __s = chrono::duration_cast<seconds>(__ut.time_since_epoch());
+       return __detail::__get_leap_second_info(sys_seconds(__s), true);
+      }
 
-      static time_point
-      now() noexcept
-      { return _S_from_sys(chrono::system_clock::now()); }
-
-#if __cplusplus > 201703L
-      template<typename _Dur>
-       static
-       chrono::file_time<_Dur>
-       from_sys(const chrono::sys_time<_Dur>& __t) noexcept
-       { return _S_from_sys(__t); }
-
-      // For internal use only
-      template<typename _Dur>
-       static
-       chrono::sys_time<_Dur>
-       to_sys(const chrono::file_time<_Dur>& __t) noexcept
-       { return _S_to_sys(__t); }
+    template<typename _Duration>
+      [[nodiscard]]
+      inline utc_time<common_type_t<_Duration, seconds>>
+      utc_clock::from_sys(const sys_time<_Duration>& __t)
+      {
+       using _CDur = common_type_t<_Duration, seconds>;
+       auto __s = chrono::time_point_cast<seconds>(__t);
+       const auto __li = __detail::__get_leap_second_info(__s, false);
+       return utc_time<_CDur>{__t.time_since_epoch()} + __li.elapsed;
+      }
+
+    /// @} group chrono
 #endif // C++20
+  } // namespace chrono
 
-    private:
-      using __sys_clock = chrono::system_clock;
-
-      // This clock's (unspecified) epoch is 2174-01-01 00:00:00 UTC.
-      // A signed 64-bit duration with nanosecond resolution gives roughly
-      // +/- 292 years, which covers the 1901-2446 date range for ext4.
-      static constexpr chrono::seconds _S_epoch_diff{6437664000};
-
-    protected:
-      // For internal use only
-      template<typename _Dur>
-       static
-       chrono::time_point<__file_clock, _Dur>
-       _S_from_sys(const chrono::time_point<__sys_clock, _Dur>& __t) noexcept
-       {
-         using __file_time = chrono::time_point<__file_clock, _Dur>;
-         return __file_time{__t.time_since_epoch()} - _S_epoch_diff;
-       }
+#if __cplusplus >= 202002L
+  inline namespace literals
+  {
+  inline namespace chrono_literals
+  {
+    /// @addtogroup chrono
+    /// @{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wliteral-suffix"
+    /// Literal suffix for creating chrono::day objects.
+    /// @since C++20
+    constexpr chrono::day
+    operator""d(unsigned long long __d) noexcept
+    { return chrono::day{static_cast<unsigned>(__d)}; }
 
-      // For internal use only
-      template<typename _Dur>
-       static
-       chrono::time_point<__sys_clock, _Dur>
-       _S_to_sys(const chrono::time_point<__file_clock, _Dur>& __t) noexcept
-       {
-         using __sys_time = chrono::time_point<__sys_clock, _Dur>;
-         return __sys_time{__t.time_since_epoch()} + _S_epoch_diff;
-       }
-    };
-  } // namespace filesystem
-#endif // C++17
-#endif // C++14
+    /// Literal suffix for creating chrono::year objects.
+    /// @since C++20
+    constexpr chrono::year
+    operator""y(unsigned long long __y) noexcept
+    { return chrono::year{static_cast<int>(__y)}; }
+#pragma GCC diagnostic pop
+    /// @}
+  } // inline namespace chrono_literals
+  } // inline namespace literals
+#endif // C++20
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 
+#if __cplusplus >= 202002L
+# include <bits/chrono_io.h>
+#endif
+
 #endif // C++11
 
 #endif //_GLIBCXX_CHRONO