【C++20】入門 | 時間の取得・フォーマット・計算を完全解説

目次

はじめに

C++で日付や時間を扱う際、従来はC言語由来のtime.hを使うなど、少し扱いが面倒でした。C++20では、**<chrono>**ライブラリが大幅に拡張され、タイムゾーンの扱いや日付・時刻のフォーマットが、非常に簡単かつ型安全に行えるようになりました。

この記事では、C++20の<chrono>ライブラリの主要な機能を、以下のカテゴリに分けて網羅的に解説します。

  1. 現在時刻の取得とフォーマット
  2. 経過時間 (duration) の扱い
  3. 指定時間まで待機

【前提】C++20とは?

C++20は、2020年に正式化されたC++言語のメジャーアップデート版です。この記事で紹介する機能の多くはC++20で導入されたため、利用するにはC++20に対応したコンパイラが必要です。


1. 現在時刻の取得とフォーマット

std::chrono::system_clock::now() で現在のシステム時刻を取得し、std::format (C++20) や zoned_time を使って、特定のタイムゾーンの日付や時刻として整形できます。

サンプルコード

#include <iostream>
#include <chrono>
#include <format> // std::format (C++20)

using namespace std;
using namespace std::chrono;

int main() {
    // 1. 現在のシステム時刻を取得
    system_clock::time_point now = system_clock::now();
    
    // 2. タイムゾーンを指定して表示 (日本時間)
    cout << "現在時刻 (日本): " << zoned_time{"Asia/Tokyo", now} << endl;
    
    // 3. タイムゾーンを指定して表示 (協定世界時)
    cout << "現在時刻 (UTC): " << zoned_time{"UTC", now} << endl;
    
    // 4. std::formatで、好きな書式に整形
    cout << "フォーマット (Y-m-d H:M:S): "
         << format("{:%Y-%m-%d %H:%M:%S}", zoned_time{"Asia/Tokyo", now}) << endl;

    // 5. 日付だけ、時間だけを取り出す
    auto zt = zoned_time{"Asia/Tokyo", now};
    // floor<days>で日付部分に丸める
    year_month_day ymd{floor<days>(zt.get_local_time())};
    // 時:分:秒の部分を取得
    hh_mm_ss hms{zt.get_local_time() - floor<days>(zt.get_local_time())};

    cout << "日付のみ: " << ymd << endl;
    cout << "時間のみ: " << hms << endl;

    return 0;
}

2. 経過時間 (duration) の扱い

durationは、時間の「長さ」を表現するクラスです。seconds, milliseconds などが用意されており、単位の変換や計算を型安全に行えます。

サンプルコード

#include <iostream>
#include <chrono>

using namespace std;
using namespace std::chrono;
using namespace std::chrono_literals; // "s", "ms" などのリテラルを使うために必要

int main() {
    // 1. 単位の変換
    milliseconds ms1 = seconds{5}; // 5秒は5000ミリ秒
    cout << "5秒 = " << ms1.count() << "ミリ秒" << endl;
    
    seconds s = duration_cast<seconds>(milliseconds{3800}); // 3800ミリ秒 -> 3秒 (切り捨て)
    cout << "3800ミリ秒を秒に変換 (切り捨て): " << s.count() << "秒" << endl;

    // 2. 異なる単位同士の演算
    milliseconds total_ms = seconds{2} + milliseconds{500};
    cout << "2秒 + 500ミリ秒 = " << total_ms.count() << "ミリ秒" << endl;
    
    // 3. durationリテラル (C++14)
    auto total_duration = 1min + 30s + 100ms;
    cout << "1分30秒100ミリ秒 = " 
         << duration_cast<milliseconds>(total_duration).count() << "ミリ秒" << endl;
         
    return 0;
}

解説:

  • duration_cast: millisecondsseconds に変換するなど、精度の粗い単位へ安全に変換(キャスト)するために使います。
  • リテラル: 1min30s のように、数値の後ろに単位を付けるだけで、直感的にdurationオブジェクトを生成できます。

3. 指定時間まで待機する

他のスレッドの処理を待ったり、一定間隔で処理を実行したりするために、指定した時間だけ現在のスレッドをスリープさせることができます。 (この機能は <thread> ヘッダーで提供されます)

サンプルコード

#include <iostream>
#include <chrono>
#include <thread> // this_thread::sleep_for

using namespace std;
using namespace std::chrono;

int main() {
    cout << "処理を開始します。" << endl;
    
    // 現在の時刻から5秒後の時刻を計算
    auto end_time = system_clock::now() + seconds{5};
    
    // 5秒間スリープする (より現代的な書き方)
    // this_thread::sleep_for(seconds{5});
    
    // 指定時刻になるまでビジーウェイトで待機する
    while (system_clock::now() < end_time) {
        // ループで待機
    }
    
    cout << "5秒経過したので、処理を終了します。" << endl;
    
    return 0;
}

解説: ご提示の while ループによる待機(ビジーウェイト)はCPUを消費するため、std::this_thread::sleep_for()sleep_until() を使うのが一般的で、より効率的です。


まとめ

今回は、C++20の<chrono>ライブラリを使った、現代的な時間操作の基本を解説しました。durationtime_pointといった型システムにより、単位の間違いなどをコンパイル時に防ぎつつ、タイムゾーンや書式設定といった複雑な処理を、驚くほど簡単かつ安全に記述できるようになっています。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次