// <chrono> -*- C++ -*-

// Copyright (C) 2008-2026 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

// [time]

/** @file include/chrono
 *  This is a Standard C++ Library header.
 *  @ingroup chrono
 */

#ifndef _GLIBCXX_CHRONO
#define _GLIBCXX_CHRONO 1

#ifdef _GLIBCXX_SYSHDR
#pragma GCC system_header
#endif

#ifdef _GLIBCXX_NO_FREESTANDING_CHRONO
# include <bits/requires_hosted.h> // for <ctime> and clocks
#endif

#if __cplusplus < 201103L
# include <bits/c++0x_warning.h>
#else

#define __glibcxx_want_chrono
#define __glibcxx_want_chrono_udls
#include <bits/version.h>

#include <bits/chrono.h>

#if __cpp_lib_bitops >= 201907L
# include <bit> // __countr_zero
#endif
#ifdef __glibcxx_chrono_cxx20
# include <bits/stl_algo.h>     // upper_bound
# include <bits/range_access.h> // begin/end for arrays
#endif
#if __cpp_lib_chrono >= 201803L // C++20 && HOSTED && USE_CXX11_ABI
# include <sstream>
# include <string>
# include <vector>
# include <bits/shared_ptr.h>
# include <bits/unique_ptr.h>
#endif
#if __glibcxx_chrono_cxx20 >= 202306L // C++26
# include <bits/functional_hash.h>
#endif

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION

  /**
   * @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
  {
#ifdef __glibcxx_chrono_cxx20
    /// @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>;

#if _GLIBCXX_HOSTED
    class utc_clock;
    class tai_clock;
    class gps_clock;

    template<typename _Duration>
      using utc_time = time_point<utc_clock, _Duration>;
    using utc_seconds = utc_time<seconds>;

    template<typename _Duration>
      using tai_time = time_point<tai_clock, _Duration>;
    using tai_seconds = tai_time<seconds>;

    template<typename _Duration>
      using gps_time = time_point<gps_clock, _Duration>;
    using gps_seconds = gps_time<seconds>;

    template<> struct is_clock<utc_clock> : true_type { };
    template<> struct is_clock<tai_clock> : true_type { };
    template<> struct is_clock<gps_clock> : true_type { };

    template<> inline constexpr bool is_clock_v<utc_clock> = true;
    template<> inline constexpr bool is_clock_v<tai_clock> = true;
    template<> inline constexpr bool is_clock_v<gps_clock> = true;

    struct leap_second_info
    {
      bool is_leap_second;
      seconds elapsed;
    };

    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 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;

      [[nodiscard]]
      static time_point
      now()
      { return from_sys(system_clock::now()); }

      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;
	}

      template<typename _Duration>
	[[nodiscard]]
	static utc_time<common_type_t<_Duration, seconds>>
	from_sys(const sys_time<_Duration>& __t);
    };

    /** 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;

      [[nodiscard]]
      static time_point
      now();  // in src/c++20/clock.cc

      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 _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;
	}
    };

    /** A clock that measures GPS time.
     *
     * The epoch is 1980-01-06 00:00:00.
     *
     * @since C++20
     */
    class gps_clock
    {
    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;

      [[nodiscard]]
      static time_point
      now();  // in src/c++20/clock.cc

      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;
	}
    };
#endif // _GLIBCXX_HOSTED

    template<typename _DestClock, typename _SourceClock>
      struct clock_time_conversion
      { };

    // Identity conversions

    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; }
      };

#if _GLIBCXX_HOSTED
    template<>
      struct clock_time_conversion<system_clock, system_clock>
      {
	template<typename _Duration>
	  sys_time<_Duration>
	  operator()(const sys_time<_Duration>& __t) const
	  { return __t; }
      };

    template<>
      struct clock_time_conversion<utc_clock, utc_clock>
      {
	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); }
      };

    /// @cond undocumented
    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;
    /// @endcond

    // 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))
	  {
	    using _Ret = decltype(_SourceClock::to_sys(__t));
	    static_assert(__is_time_point_for_v<_Ret, system_clock>);
	    return _SourceClock::to_sys(__t);
	  }
      };

    template<typename _DestClock>
      struct clock_time_conversion<_DestClock, system_clock>
      {
	template<typename _Duration, typename _Dest = _DestClock>
	  auto
	  operator()(const sys_time<_Duration>& __t) const
	  -> decltype(_Dest::from_sys(__t))
	  {
	    using _Ret = decltype(_DestClock::from_sys(__t));
	    static_assert(__is_time_point_for_v<_Ret, _DestClock>);
	    return _DestClock::from_sys(__t);
	  }
      };

    // Conversions between utc_clock and other clocks

    template<typename _SourceClock>
      struct clock_time_conversion<utc_clock, _SourceClock>
      {
	template<typename _Duration, typename _Src = _SourceClock>
	  auto
	  operator()(const time_point<_SourceClock, _Duration>& __t) const
	  -> decltype(_Src::to_utc(__t))
	  {
	    using _Ret = decltype(_SourceClock::to_utc(__t));
	    static_assert(__is_time_point_for_v<_Ret, utc_clock>);
	    return _SourceClock::to_utc(__t);
	  }
      };

    template<typename _DestClock>
      struct clock_time_conversion<_DestClock, utc_clock>
      {
	template<typename _Duration, typename _Dest = _DestClock>
	  auto
	  operator()(const utc_time<_Duration>& __t) const
	  -> decltype(_Dest::from_utc(__t))
	  {
	    using _Ret = decltype(_DestClock::from_utc(__t));
	    static_assert(__is_time_point_for_v<_Ret, _DestClock>);
	    return _DestClock::from_utc(__t);
	  }
      };
#endif // _GLIBCXX_HOSTED

    /// @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);
	  };

#if _GLIBCXX_HOSTED
      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)));
	  };
#endif // _GLIBCXX_HOSTED
    } // namespace __detail
    /// @endcond

    /// 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>
#if _GLIBCXX_HOSTED
	|| __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>
#endif // _GLIBCXX_HOSTED
      {
       constexpr bool __direct
	 = __detail::__clock_convs<_DestClock, _SourceClock, _Duration>;
       if constexpr (__direct)
	 {
	   return clock_time_conversion<_DestClock, _SourceClock>{}(__t);
	 }
#if _GLIBCXX_HOSTED
       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)));
		 }
	     }
	 }
#endif // _GLIBCXX_HOSTED
      }

    // CALENDRICAL TYPES

    // CLASS DECLARATIONS
    class day;
    class month;
    class year;
    class weekday;
    class weekday_indexed;
    class weekday_last;
    class month_day;
    class month_day_last;
    class month_weekday;
    class month_weekday_last;
    class year_month;
    class year_month_day;
    class year_month_day_last;
    class year_month_weekday;
    class year_month_weekday_last;

    struct last_spec
    {
      explicit last_spec() = default;

      friend constexpr month_day_last
      operator/(int __m, last_spec) noexcept;

      friend constexpr month_day_last
      operator/(last_spec, int __m) noexcept;
    };

    inline constexpr last_spec last{};

    /// @cond undocumented
    namespace __detail
    {
      // Helper to __add_modulo and __sub_modulo.
      template <unsigned __d, typename _Tp>
      consteval auto
      __modulo_offset()
      {
	using _Up = make_unsigned_t<_Tp>;
	auto constexpr __a = _Up(-1) - _Up(255 + __d - 2);
	auto constexpr __b = _Up(__d * (__a / __d) - 1);
	// Notice: b <= a - 1 <= _Up(-1) - (255 + d - 1) and b % d = d - 1.
	return _Up(-1) - __b; // >= 255 + d - 1
      }

      // Compute the remainder of the Euclidean division of __x + __y divided by
      // __d without overflowing.  Typically, __x <= 255 + d - 1 is sum of
      // weekday/month with a shift in [0, d - 1] and __y is a duration count.
      template <unsigned __d, typename _Tp>
      constexpr unsigned
      __add_modulo(unsigned __x, _Tp __y)
      {
	using _Up = make_unsigned_t<_Tp>;
	// For __y >= 0, _Up(__y) has the same mathematical value as __y and
	// this function simply returns (__x + _Up(__y)) % d.  Typically, this
	// doesn't overflow since the range of _Up contains many more positive
	// values than _Tp's.  For __y < 0, _Up(__y) has a mathematical value in
	// the upper-half range of _Up so that adding a positive value to it
	// might overflow.  Moreover, most likely, _Up(__y) != __y mod d.  To
	// fix both issues we subtract from _Up(__y) an __offset >=
	// 255 + d - 1 to make room for the addition to __x and shift the modulo
	// to the correct value.
	auto const __offset = __y >= 0 ? _Up(0) : __modulo_offset<__d, _Tp>();
	return (__x + _Up(__y) - __offset) % __d;
      }

      // Similar to __add_modulo but for __x - __y.
      template <unsigned __d, typename _Tp>
      constexpr unsigned
      __sub_modulo(unsigned __x, _Tp __y)
      {
	using _Up = make_unsigned_t<_Tp>;
	auto const __offset = __y <= 0 ? _Up(0) : __modulo_offset<__d, _Tp>();
	return (__x - _Up(__y) - __offset) % __d;
      }

      inline constexpr unsigned __days_per_month[12]
	= { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    } // namespace __detail
    /// @endcond

    // DAY

    class day
    {
    private:
      unsigned char _M_d;

    public:
      day() = default;

      explicit constexpr
      day(unsigned __d) noexcept
      : _M_d(__d)
      { }

      constexpr day&
      operator++() noexcept
      {
	++_M_d;
	return *this;
      }

      constexpr day
      operator++(int) noexcept
      {
	auto __ret = *this;
	++(*this);
	return __ret;
      }

      constexpr day&
      operator--() noexcept
      {
	--_M_d;
	return *this;
      }

      constexpr day
      operator--(int) noexcept
      {
	auto __ret = *this;
	--(*this);
	return __ret;
      }

      constexpr day&
      operator+=(const days& __d) noexcept
      {
	*this = *this + __d;
	return *this;
      }

      constexpr day&
      operator-=(const days& __d) noexcept
      {
	*this = *this - __d;
	return *this;
      }

      constexpr explicit
      operator unsigned() const noexcept
      { return _M_d; }

      constexpr bool
      ok() const noexcept
      { return 1 <= _M_d && _M_d <= 31; }

      friend constexpr bool
      operator==(const day& __x, const day& __y) noexcept
      { return unsigned{__x} == unsigned{__y}; }

      friend constexpr strong_ordering
      operator<=>(const day& __x, const day& __y) noexcept
      { return unsigned{__x} <=> unsigned{__y}; }

      friend constexpr day
      operator+(const day& __x, const days& __y) noexcept
      { return day(unsigned{__x} + __y.count()); }

      friend constexpr day
      operator+(const days& __x, const day& __y) noexcept
      { return __y + __x; }

      friend constexpr day
      operator-(const day& __x, const days& __y) noexcept
      { return __x + -__y; }

      friend constexpr days
      operator-(const day& __x, const day& __y) noexcept
      { return days{int(unsigned{__x}) - int(unsigned{__y})}; }

      friend constexpr month_day
      operator/(const month& __m, const day& __d) noexcept;

      friend constexpr month_day
      operator/(int __m, const day& __d) noexcept;

      friend constexpr month_day
      operator/(const day& __d, const month& __m) noexcept;

      friend constexpr month_day
      operator/(const day& __d, int __m) noexcept;

      friend constexpr year_month_day
      operator/(const year_month& __ym, const day& __d) noexcept;
    };

    // MONTH

    class month
    {
    private:
      unsigned char _M_m;

    public:
      month() = default;

      explicit constexpr
      month(unsigned __m) noexcept
      : _M_m(__m)
      { }

      constexpr month&
      operator++() noexcept
      {
	*this += months{1};
	return *this;
      }

      constexpr month
      operator++(int) noexcept
      {
	auto __ret = *this;
	++(*this);
	return __ret;
      }

      constexpr month&
      operator--() noexcept
      {
	*this -= months{1};
	return *this;
      }

      constexpr month
      operator--(int) noexcept
      {
	auto __ret = *this;
	--(*this);
	return __ret;
      }

      constexpr month&
      operator+=(const months& __m) noexcept
      {
	*this = *this + __m;
	return *this;
      }

      constexpr month&
      operator-=(const months& __m) noexcept
      {
	*this = *this - __m;
	return *this;
      }

      explicit constexpr
      operator unsigned() const noexcept
      { return _M_m; }

      constexpr bool
      ok() const noexcept
      { return 1 <= _M_m && _M_m <= 12; }

      friend constexpr bool
      operator==(const month& __x, const month& __y) noexcept
      { return unsigned{__x} == unsigned{__y}; }

      friend constexpr strong_ordering
      operator<=>(const month& __x, const month& __y) noexcept
      { return unsigned{__x} <=> unsigned{__y}; }

      friend constexpr month
      operator+(const month& __x, const months& __y) noexcept
      {
	// modulo(x + (y - 1), 12) = modulo(x + (y - 1) + 12, 12)
	//                         = modulo((x + 11) + y    , 12)
	return month{1 + __detail::__add_modulo<12>(
	  unsigned{__x} + 11, __y.count())};
      }

      friend constexpr month
      operator+(const months& __x,  const month& __y) noexcept
      { return __y + __x; }

      friend constexpr month
      operator-(const month& __x, const months& __y) noexcept
      {
	// modulo(x + (-y - 1), 12) = modulo(x + (-y - 1) + 12, 12)
	//                          = modulo((x + 11) - y     , 12)
	return month{1 + __detail::__sub_modulo<12>(
	  unsigned{__x} + 11, __y.count())};
      }

      friend constexpr months
      operator-(const month& __x,  const month& __y) noexcept
      {
	const auto __dm = int(unsigned(__x)) - int(unsigned(__y));
	return months{__dm < 0 ? 12 + __dm : __dm};
      }

      friend constexpr year_month
      operator/(const year& __y, const month& __m) noexcept;

      friend constexpr month_day
      operator/(const month& __m, int __d) noexcept;

      friend constexpr month_day_last
      operator/(const month& __m, last_spec) noexcept;

      friend constexpr month_day_last
      operator/(last_spec, const month& __m) noexcept;

      friend constexpr month_weekday
      operator/(const month& __m, const weekday_indexed& __wdi) noexcept;

      friend constexpr month_weekday
      operator/(const weekday_indexed& __wdi, const month& __m) noexcept;

      friend constexpr month_weekday_last
      operator/(const month& __m, const weekday_last& __wdl) noexcept;

      friend constexpr month_weekday_last
      operator/(const weekday_last& __wdl, const month& __m) noexcept;
    };

    inline constexpr month January{1};
    inline constexpr month February{2};
    inline constexpr month March{3};
    inline constexpr month April{4};
    inline constexpr month May{5};
    inline constexpr month June{6};
    inline constexpr month July{7};
    inline constexpr month August{8};
    inline constexpr month September{9};
    inline constexpr month October{10};
    inline constexpr month November{11};
    inline constexpr month December{12};

    // YEAR

    class year
    {
    private:
      short _M_y;

    public:
      year() = default;

      explicit constexpr
      year(int __y) noexcept
      : _M_y{static_cast<short>(__y)}
      { }

      static constexpr year
      min() noexcept
      { return year{-32767}; }

      static constexpr year
      max() noexcept
      { return year{32767}; }

      constexpr year&
      operator++() noexcept
      {
	++_M_y;
	return *this;
      }

      constexpr year
      operator++(int) noexcept
      {
	auto __ret = *this;
	++(*this);
	return __ret;
      }

      constexpr year&
      operator--() noexcept
      {
	--_M_y;
	return *this;
      }

      constexpr year
      operator--(int) noexcept
      {
	auto __ret = *this;
	--(*this);
	return __ret;
      }

      constexpr year&
      operator+=(const years& __y) noexcept
      {
	*this = *this + __y;
	return *this;
      }

      constexpr year&
      operator-=(const years& __y) noexcept
      {
	*this = *this - __y;
	return *this;
      }

      constexpr year
      operator+() const noexcept
      { return *this; }

      constexpr year
      operator-() const noexcept
      { return year{-_M_y}; }

      constexpr bool
      is_leap() const noexcept
      {
	// 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;
      }

      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} + static_cast<int>(__y.count())}; }

      friend constexpr year
      operator+(const years& __x, const year& __y) noexcept
      { return __y + __x; }

      friend constexpr year
      operator-(const year& __x, const years& __y) noexcept
      { return __x + -__y; }

      friend constexpr years
      operator-(const year& __x, const year& __y) noexcept
      { return years{int{__x} - int{__y}}; }

      friend constexpr year_month
      operator/(const year& __y, int __m) noexcept;

      friend constexpr year_month_day
      operator/(const year& __y, const month_day& __md) noexcept;

      friend constexpr year_month_day
      operator/(const month_day& __md, const year& __y) noexcept;

      friend constexpr year_month_day_last
      operator/(const year& __y, const month_day_last& __mdl) noexcept;

      friend constexpr year_month_day_last
      operator/(const month_day_last& __mdl, const year& __y) noexcept;

      friend constexpr year_month_weekday
      operator/(const year& __y, const month_weekday& __mwd) noexcept;

      friend constexpr year_month_weekday
      operator/(const month_weekday& __mwd, const year& __y) noexcept;

      friend constexpr year_month_weekday_last
      operator/(const year& __y, const month_weekday_last& __mwdl) noexcept;

      friend constexpr year_month_weekday_last
      operator/(const month_weekday_last& __mwdl, const year& __y) noexcept;
    };

    // WEEKDAY

    class weekday
    {
    private:
      unsigned char _M_wd;

      static constexpr weekday
      _S_from_days(const days& __d)
      {
	return weekday{__detail::__add_modulo<7>(4, __d.count())};
      }

    public:
      weekday() = default;

      explicit constexpr
      weekday(unsigned __wd) noexcept
      : _M_wd(__wd == 7 ? 0 : __wd) // __wd % 7 ?
      { }

      constexpr
      weekday(const sys_days& __dp) noexcept
      : weekday{_S_from_days(__dp.time_since_epoch())}
      { }

      explicit constexpr
      weekday(const local_days& __dp) noexcept
      : weekday{sys_days{__dp.time_since_epoch()}}
      { }

      constexpr weekday&
      operator++() noexcept
      {
	*this += days{1};
	return *this;
      }

      constexpr weekday
      operator++(int) noexcept
      {
	auto __ret = *this;
	++(*this);
	return __ret;
      }

      constexpr weekday&
      operator--() noexcept
      {
	*this -= days{1};
	return *this;
      }

      constexpr weekday
      operator--(int) noexcept
      {
	auto __ret = *this;
	--(*this);
	return __ret;
      }

      constexpr weekday&
      operator+=(const days& __d) noexcept
      {
	*this = *this + __d;
	return *this;
      }

      constexpr weekday&
      operator-=(const days& __d) noexcept
      {
	*this = *this - __d;
	return *this;
      }

      constexpr unsigned
      c_encoding() const noexcept
      { return _M_wd; }

      constexpr unsigned
      iso_encoding() const noexcept
      { return _M_wd == 0u ? 7u : _M_wd; }

      constexpr bool
      ok() const noexcept
      { return _M_wd <= 6; }

      constexpr weekday_indexed
      operator[](unsigned __index) const noexcept;

      constexpr weekday_last
      operator[](last_spec) const noexcept;

      friend constexpr bool
      operator==(const weekday& __x, const weekday& __y) noexcept
      { return __x._M_wd == __y._M_wd; }

      friend constexpr weekday
      operator+(const weekday& __x, const days& __y) noexcept
      {
	return weekday{__detail::__add_modulo<7>(__x._M_wd, __y.count())};
      }

      friend constexpr weekday
      operator+(const days& __x, const weekday& __y) noexcept
      { return __y + __x; }

      friend constexpr weekday
      operator-(const weekday& __x, const days& __y) noexcept
      {
	return weekday{__detail::__sub_modulo<7>(__x._M_wd, __y.count())};
      }

      friend constexpr days
      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};
      }
    };

    inline constexpr weekday Sunday{0};
    inline constexpr weekday Monday{1};
    inline constexpr weekday Tuesday{2};
    inline constexpr weekday Wednesday{3};
    inline constexpr weekday Thursday{4};
    inline constexpr weekday Friday{5};
    inline constexpr weekday Saturday{6};

    // WEEKDAY_INDEXED

    class weekday_indexed
    {
    private:
      chrono::weekday _M_wd;
      unsigned char _M_index;

    public:
      weekday_indexed() = default;

      constexpr
      weekday_indexed(const chrono::weekday& __wd, unsigned __index) noexcept
      : _M_wd(__wd), _M_index(__index)
      { }

      constexpr chrono::weekday
      weekday() const noexcept
      { return _M_wd; }

      constexpr unsigned
      index() const noexcept
      { return _M_index; };

      constexpr bool
      ok() const noexcept
      { return _M_wd.ok() && 1 <= _M_index && _M_index <= 5; }

      friend constexpr bool
      operator==(const weekday_indexed& __x, const weekday_indexed& __y) noexcept
      { return __x.weekday() == __y.weekday() && __x.index() == __y.index(); }

      friend constexpr month_weekday
      operator/(const month& __m, const weekday_indexed& __wdi) noexcept;

      friend constexpr month_weekday
      operator/(int __m, const weekday_indexed& __wdi) noexcept;

      friend constexpr month_weekday
      operator/(const weekday_indexed& __wdi, const month& __m) noexcept;

      friend constexpr month_weekday
      operator/(const weekday_indexed& __wdi, int __m) noexcept;

      friend constexpr year_month_weekday
      operator/(const year_month& __ym, const weekday_indexed& __wdi) noexcept;
    };

    constexpr weekday_indexed
    weekday::operator[](unsigned __index) const noexcept
    { return {*this, __index}; }

    // WEEKDAY_LAST

    class weekday_last
    {
    private:
      chrono::weekday _M_wd;

    public:
      explicit constexpr
      weekday_last(const chrono::weekday& __wd) noexcept
      : _M_wd{__wd}
      { }

      constexpr chrono::weekday
      weekday() const noexcept
      { return _M_wd; }

      constexpr bool
      ok() const noexcept
      { return _M_wd.ok(); }

      friend constexpr bool
      operator==(const weekday_last& __x, const weekday_last& __y) noexcept
      { return __x.weekday() == __y.weekday(); }

      friend constexpr month_weekday_last
      operator/(int __m, const weekday_last& __wdl) noexcept;

      friend constexpr month_weekday_last
      operator/(const weekday_last& __wdl, int __m) noexcept;

      friend constexpr year_month_weekday_last
      operator/(const year_month& __ym, const weekday_last& __wdl) noexcept;
    };

    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;
    };

    // 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;
    };

    // 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 chron                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     