2023年08月23日(水) [長年日記]
■ [c++] std::chronoメモ
std::chronoについてメモ。C++20で色々機能が追加されており、それを前提とする。
durationは時間
durationは時間を表すクラステンプレート。テンプレートパラメータとして値の型と、値の1が何秒を表すかの比率を持つ。
テンプレートをインスタンス化したクラスとして seconds、milliseconds、years などの色々な型が用意されている。なお、yearsは31556952秒、monthsは2629746秒という「平均的な長さ」が単位になっていることに注意。
sなどのリテラル演算子も用意されており、これらを使ってオブジェクトを作ることもできる。
durationクラス間の変換は、精度が落ちなければコンストラクタや代入で行え、精度が落ちる場合はduration_cast()やfloor()などを使い分けて行う。
#include <chrono> #include <iostream> int main() { using namespace std::literals::chrono_literals; namespace ch = std::chrono; const ch::duration<int> d1{ -100 }; const ch::milliseconds d2 = d1; const auto d3 = ch::duration_cast<ch::minutes>(d1); const auto d4 = ch::floor<ch::minutes>(d1); const auto d5 = d4 + 1s; const ch::months d6{ 1 }; const ch::years d7{ 1 }; std::cout << "d1 = " << d1 << std::endl; std::cout << "d2 = " << d2 << std::endl; std::cout << "d3 = " << d3 << std::endl; std::cout << "d4 = " << d4 << std::endl; std::cout << "d5 = " << d5 << std::endl; std::cout << "d6 = " << d6 << std::endl; std::cout << "d7 = " << d7 << std::endl; }
d1 = -100s d2 = -100000ms d3 = -1min d4 = -2min d5 = -119s d6 = 1[2629746]s d7 = 1[31556952]s
time_pointは時刻
time_pointは時刻を表すクラステンプレート。テンプレートパラメータとして「時計」型と、時刻の刻み幅とするdurationを持つ。
時計型としてsystem_clockやlocal_tなどが用意されており、それらを使ってtime_pointテンプレートをインスタンス化したクラスとしてsys_secondsやlocal_daysなどが用意されている。
時刻は起点となる時刻(エポック)からの経過時間として表現されている。エポックは時計型から決まる。
特定の時刻を生成するには、/ 演算子を使ってyear_month_dayオブジェクトを作り、それをsys_daysに変換するという方法が使える。
time_pointクラス間の変換もdurationと同様で、精度が落ちなければコンストラクタや代入で行え、精度が落ちる場合はtime_point_cast()やfloor()などを使い分けて行う。
#include <iostream> int main() { using namespace std::literals::chrono_literals; namespace ch = std::chrono; const ch::time_point<ch::system_clock> t1; // system_clockのエポック const ch::sys_seconds t2{ ch::months{ 1 } }; // エポックから約一か月後 const auto t3 = ch::sys_days{ 2023y/8/15 } + 12h + 34min + 56s; const ch::time_point<ch::system_clock, ch::milliseconds> t4 = t3; const auto t5 = ch::floor<ch::days>(t3); std::cout << "t1 = " << t1 << std::endl; std::cout << "t2 = " << t2 << std::endl; std::cout << "t3 = " << t3 << std::endl; std::cout << "t4 = " << t4 << std::endl; std::cout << "t5 = " << t5 << std::endl; }
t1 = 1970-01-01 00:00:00.0000000 t2 = 1970-01-31 10:29:06 t3 = 2023-08-15 12:34:56 t4 = 2023-08-15 12:34:56.000 t5 = 2023-08-15
時計とタイムゾーン
時計は現在時刻を取得するときに使うクラス。いくつか用意されているが、通常はsystem_clockを使い、経過時間を計る際にsteady_clockを使うくらいか。
system_clock::now()が返す時刻はUTC相当のものであることに注意。システムのタイムゾーンでの時刻を取得するには、current_zone()でtime_zoneオブジェクトを取得し、そのメンバ関数to_local()を呼び出す方法が使える。
また、時刻をタイムゾーン付きで管理したい場合はzoned_timeクラステンプレートを使う。zoned_timeは時刻を表すがtime_point型ではなく、time_pointとtime_zoneのペアである。
#include <chrono> #include <iostream> int main() { namespace ch = std::chrono; const auto now1 = ch::system_clock::now(); const auto now2 = ch::current_zone()->to_local(now1); const ch::zoned_time now3{ ch::current_zone(), now1 }; std::cout << "now1 = " << now1 << std::endl; std::cout << "now2 = " << now2 << std::endl; std::cout << "now3 = " << now3 << std::endl; }
now1 = 2023-08-23 10:16:29.2074391 now2 = 2023-08-23 19:16:29.2074391 now3 = 2023-08-23 19:16:29.2074391 JST