最終更新日時(UTC):
が更新

履歴 編集

class
<chrono>

std::chrono::year_month_day(C++20)

namespace std::chrono {
  class year_month_day;
}

概要

year_month_dayは、年、月、日を表すカレンダー表現のためクラスである。

このクラスは、年、および月に関する演算に対応している。ただし、日に関する演算はできない。

このクラスは等値比較および大小比較ができ、EqualityComparableおよびLessThanComparableの要件を満たす。

このクラスは、トリビアルコピー可能で、かつスタンダードレイアウト型である。

メンバ関数

構築/コピー/破棄

名前 説明 対応バージョン
(constructor) コンストラクタ C++20
year_month_day& operator=(const year_month_day&) = default;
year_month_day& operator=(year_month_day&&) = default;
代入演算子 C++20

算術演算

名前 説明 対応バージョン
operator+= 加算の複合代入 C++20
operator-= 減算の複合代入 C++20

観測

名前 説明 対応バージョン
year 年要素を取得する C++20
month 月要素を取得する C++20
day 日要素を取得する C++20

変換

名前 説明 対応バージョン
operator sys_days システム時間の日付への型変換演算子 C++20
operator local_days ローカル時間の日付への型変換演算子 C++20

検証

名前 説明 対応バージョン
ok 値が範囲に収まっているか判定する C++20

非メンバ関数

算術演算

名前 説明 対応バージョン
operator+ 加算 C++20
operator- 減算 C++20

比較演算

名前 説明 対応バージョン
operator== 等値比較を行う C++20
bool operator!=(const year_month_day&, const year_month_day&) noexcept; 非等値比較を行う (==により使用可能) C++20
operator<=> 三方比較を行う C++20
bool operator<(const year_month_day&, const year_month_day&) noexcept; 左辺が右辺より小さいかを判定する (<=>により使用可能) C++20
bool operator<=(const year_month_day&, const year_month_day&) noexcept; 左辺が右辺以下を判定する (<=>により使用可能) C++20
bool operator>(const year_month_day&, const year_month_day&) noexcept; 左辺が右辺より大きいかを判定する (<=>により使用可能) C++20
bool operator>=(const year_month_day&, const year_month_day&) noexcept; 左辺が右辺以上を判定する (<=>により使用可能) C++20

入出力

名前 説明 対応バージョン
operator<< 出力ストリームに出力する C++20
from_stream フォーマット指定して入力ストリームから入力する C++20

文字列フォーマットサポート

名前 説明 対応バージョン
formatter std::formatterクラスの特殊化 C++20

ハッシュサポート

名前 説明 対応バージョン
template <class T> struct hash; hashクラスの先行宣言 C++26
template<> struct hash<chrono::year_month_day>; hashクラスのyear_month_dayに対する特殊化 C++26

基本的な使い方 (C++20)

#include <iostream>
#include <chrono>

namespace chrono = std::chrono;
using namespace std::chrono_literals;

int main()
{
  // すべて2020年3月1日を表す
  chrono::year_month_day date1 = 2020y/3/1;
  chrono::year_month_day date2 = 2020y/chrono::March/1;
  chrono::year_month_day date3 = 2020y/chrono::March/1d;
  chrono::year_month_day date4 = 1d/chrono::March/2020;
  chrono::year_month_day date5 = 1d/3/2020;
  chrono::year_month_day date6 = chrono::March/1/2020;
  chrono::year_month_day date7 = 3/1d/2020;

  // 各カレンダー要素のコンストラクタはexplicitなので、
  // 指定順は年、月、日で決まっているが、int値は指定できない
  chrono::year_month_day date8{2020y, chrono::March, 1d};
  chrono::year_month_day date9{chrono::year{2020}, chrono::month{3}, chrono::day{1}};
  std::cout << date9 << std::endl;

  // 年、月、月の最終日の組み合わせから、年、月、日に変換。
  // 以下はすべて2020年2月29日を表す
  chrono::year_month_day date10 = 2020y/3/chrono::last;
  chrono::year_month_day date11 = 3/chrono::last/2020;
  chrono::year_month_day date12 = chrono::last/3/2020;
  std::cout << date12 << std::endl;

  // 日単位のシステム時間に変換
  chrono::sys_days sd{date9};
  std::cout << sd << std::endl;
  std::cout << sd.time_since_epoch().count() << std::endl; // 1970年1月1日からの経過日
  std::cout <<
    chrono::time_point_cast<chrono::seconds>(sd).time_since_epoch().count()
  << std::endl; // 1970年1月1日からの経過秒

  // 日単位のシステム時間に時・分を加算して、分まで扱えるシステム時間に変換。
  chrono::sys_time sm = chrono::sys_days{2020y/3/1} + 15h + 30min;
  std::cout << sm << std::endl;
}

出力例

2020-03-01
2020-02-29
2020-03-01
18322
1583020800
2020-03-01 15:30:00

前月の末日を求める (C++20)

#include <cassert>
#include <chrono>

namespace chrono = std::chrono;
using namespace std::chrono_literals;

int main()
{
  chrono::year_month_day base_date = 2020y/3/1;

  // year_month_dayオブジェクトに対して直接1日減算はできないので、
  // 前月の末日を表すyear_month_day_lastオブジェクトを作ってから、
  // year_month_dayオブジェクトに変換する
  chrono::year_month_day date{base_date.year()/(base_date.month() - chrono::months{1})/chrono::last};

  assert(date == 2020y/2/29);
}

出力

UNIX時間からyear_month_dayオブジェクトに変換する (C++20)

#include <iostream>
#include <chrono>

namespace chrono = std::chrono;

chrono::year_month_day unix_time_to_ymd(std::time_t unixtime) {
  // システム時間の時間点に変換
  auto tp = chrono::system_clock::from_time_t(unixtime);

  // 時間点を日単位に変換
  chrono::sys_days sd = chrono::floor<chrono::days>(tp);

  // 日付に変換
  return chrono::year_month_day{sd};
}

int main()
{
  // UNIX時間での現在日時を取得 
  std::time_t now = std::time(nullptr);
  chrono::year_month_day date = unix_time_to_ymd(now);

  std::cout << date << std::endl;
}

出力例

2019-12-20

生年月日から年齢を求める (C++20)

#include <iostream>
#include <chrono>
#include <stdexcept>

int calc_age(const std::chrono::year_month_day& date) {
  if (!date.ok()) {
    throw std::invalid_argument("invalid date");
  }

  namespace chrono = std::chrono;
  chrono::year_month_day now {chrono::floor<chrono::days>(chrono::system_clock::now())};
  int age = (now.year() - date.year()).count();
  if (now.month() < date.month()) {
    return age - 1;
  }
  else if (now.month() == date.month()) {
    if (now.day() < date.day()) {
      return age - 1;
    }
  }
  return age;
}

int calc_age(int year, int month, int day) {
  namespace chrono = std::chrono;
  return calc_age(chrono::year_month_day{
           chrono::year{year},
           chrono::month{static_cast<unsigned int>(month)},
           chrono::day{static_cast<unsigned int>(day)}});
}

int main()
{
  using namespace std::chrono_literals;

  std::cout << calc_age(1985y/3/1) << std::endl;
  std::cout << calc_age(1954y/10/30) << std::endl; // 1970年未満も扱える
  std::cout << calc_age(2000, 2, 29) << std::endl; // うるう年
}

出力例

34
65
19

2020年1月7日に実行した。

バージョン

言語

  • C++20

処理系

  • Clang: 8.0 (入出力ストリームなし)
  • GCC: 9.2
  • Visual C++: 2019 Update 3

参照