例えば、本日から1000日後の日付を求めたいことはよくあると思います。そんなとき、つい、月ごとの日数のテーブルを作って、閏年の判定を行って、といった処理を組み合わせて計算してしまいがちです。しかし、実際にはそんな面倒なことをする必要はありません。
mktimeを使用する方法
標準Cライブラリのmktime関数を使えば、1000日後の日付を簡単に求めることができます。ただし、time_t型の表現範囲の制約を受けるため、(最近は減りましたが)いわゆる2038年問題のような不具合に遭遇する可能性もあるので要注意です。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#include <iostream> #include <ctime> int main() { auto now = std::time(nullptr); auto t = *localtime(&now); // 1000日後 t.tm_mday += 1000; if (std::mktime(&t) != (time_t)-1) { std::cout << std::asctime(&t) << std::endl; } return 0; } |
chronoを使う方法
C++11から標準ライブラリに導入されたchronoを使う方法もあります。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include <iostream> #include <chrono> #include <ctime> int main() { auto now = std::chrono::system_clock::now(); auto p = now + std::chrono::days(1000); // 1000日後 auto t = std::chrono::system_clock::to_time_t(p); std::cout << std::ctime(&t) << std::endl; return 0; } |
上記で使っているstd::chrono::daysはC++20以降でしか使えませんので、C++17までの場合はstd::chrono::hours(24 * 1000)とする必要がありそうです。
結局std::time_t型に変換するのであれば、std::time関数とstd::mktime関数の組み合わせの方が簡単なようにも思います。
Boost.Date_Timeを使う方法
Boost C++ Libraries を使える状況であれば、Boost.Date_Time を使うこともできます。表現範囲に関しても2038年問題のようなことを心配することもありません。ちょっとコンパイル時間が長いのが難でしょうか。
0 1 2 3 4 5 6 7 8 9 10 |
#include <iostream> #include <boost/date_time/gregorian/gregorian.hpp> int main() { auto d(boost::gregorian::day_clock::local_day()); std::cout << (d + boost::gregorian::date_duration(1000)) << std::endl; return 0; } |