Closed4

chronoライブラリによるカレンダー計算

yohhoyyohhoy

C++20 (N4861) [time]

A duration type measures time between two points in time (time_­points). A duration has a representation which holds a count of ticks and a tick period. The tick period is the amount of time which occurs from one tick to the next, in units of seconds. It is expressed as a rational constant using the template ratio.

template<class Duration>
using sys_time = time_point<system_clock, Duration>;
using sys_days = sys_time<days>;

using hours  = duration</*...*/, ratio<3600>>;
using days   = duration</*...*/, ratio_multiply<ratio<24>, hours::period>>;
using years  = duration</*...*/, ratio_multiply<ratio<146097, 400>, days::period>>;
constexpr year_month_day operator+(const year_month_day& ymd, const years& dy) noexcept;
// Returns: (ymd.year() + dy) / ymd.month() / ymd.day().
template<class Rep1, class Period1, class Rep2, class Period2>
struct common_type<chrono::duration<Rep1, Period1>, chrono::duration<Rep2, Period2>> {
  using type = chrono::duration<common_type_t<Rep1, Rep2>, /*see below*/>;
};
// The period of the duration indicated by this specialization of common_­type is
// the greatest common divisor of Period1 and Period2. [Note: This can be computed
// by forming a ratio of the greatest common divisor of Period1​::​num and Period2​::​num
// and the least common multiple of Period1​::​den and Period2​::​den. -- end note]

template<class Clock, class Duration1, class Rep2, class Period2>
  constexpr time_point<Clock, common_type_t<Duration1, duration<Rep2, Period2>>>
    operator+(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs);
// Returns: CT(lhs.time_­since_­epoch() + rhs), where CT is the type of the return value.
  • days{1} = 24[時間] × 3600[秒] = 86400[秒]
  • years{1} = 146097/400 [日] × 86400[秒] = 31556952[秒]
    • 365 × 303 + 366 × 97 = 146097[日];400年間周期で閏年は97回
  • years{1} = 31556952[秒] = 146097 × 216[秒]
    • common_type_t<days, years> = duration</*...*/, ratio<216, 1>>
yohhoyyohhoy
assert(sys_days{2020y/1/1 + years{1}}  == sys_days{2021y/1/1});  // OK
assert(sys_days{2020y/1/1 + months{1}} == sys_days{2020y/2/1});  // OK
assert(sys_days{2020y/1/1 + days{100}} == sys_days{2020y/4/10});  // NG コンパイルエラー
//              ^^^^^^^^^   ^^^^^^^^^
//         year_month_day + days

2020y/1/1の型year_month_dayでは、年yearsまたは月monthsに対する加減算をサポートする。日daysとの加減算オーバーロードは提供されない。

namespace std::chrono {
  // [time.cal.ymd]
  constexpr year_month_day operator+(const year_month_day& ymd, const months& dm) noexcept;
  constexpr year_month_day operator+(const months& dm, const year_month_day& ymd) noexcept;
  constexpr year_month_day operator+(const year_month_day& ymd, const years& dy) noexcept;
  constexpr year_month_day operator+(const years& dy, const year_month_day& ymd) noexcept;
  constexpr year_month_day operator-(const year_month_day& ymd, const months& dm) noexcept;
  constexpr year_month_day operator-(const year_month_day& ymd, const years& dy) noexcept;
}

year_month_dayクラスはデータメンバとしてyear, month, dayクラスの値をもち;

  • yearクラスは年をshort型で保持する。値域[-32767, 32767][1]
  • monthクラスは月をunsigned char型で保持する。値域[0, 255][2]
  • dayクラスは日をunsigned char型で保持する。値域[0, 255][3]
脚注
  1. C++20 [time.cal.year.overview]/p1: "It can represent values in the range [min(), max()]. It can be constructed with any int value, which will be subsequently truncated to fit into year's unspecified internal storage." ↩︎

  2. C++20 [time.cal.month.overview]/1: "It can be constructed with any unsigned value, which will be subsequently truncated to fit into month's unspecified internal storage." ↩︎

  3. C++20 [time.cal.day.overview]/1: "It can be constructed with any unsigned value, which will be subsequently truncated to fit into day's unspecified internal storage." ↩︎

このスクラップは2021/12/15にクローズされました