MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
C++の基礎 - 時刻のソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
C++の基礎 - 時刻
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == <br><br> == 本日の経過時刻の取得 == ==== std::chrono (C++11) ==== 本日の0時0分0秒000からの経過時刻 (mS) を求めるには、<code>std::chrono</code> (C++11以降) を使用する。<br> なお、C++17以降およびLinux環境では別の手段も存在する。<br> <br> 現在時刻に関する情報は、<code>std::chrono</code>の<code>now</code>メソッドで取得できる。<br> なお、この時刻はUTC (協定世界時) であり日本時間とは異なることに注意する。<br> <syntaxhighlight lang="c++"> #include <chrono> std::chrono::system_clock::time_point tp = std::chrono::system_clock::now(); </syntaxhighlight> <br> まず、<code>time_since_epoc</code>メソッドを使用して、エポックタイムからの経過時刻を取得した後、<code>count</code>メソッドでミリ秒を取得する。<br> 取得した値から現在時刻のミリ秒の部分を得る。<br> <br> エポックタイムは、未規定ではあるが概ね1970年1月1日から始まる。<br> <u>ただし、経過時刻 (mS) は1兆を超える値になるため、32ビットのint型では格納できないことに注意する。</u><br> <syntaxhighlight lang="c++"> // エポックタイムからの経過時刻 std::chrono::milliseconds tp_msec = std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch()); // 経過時刻をミリ秒 (整数値) に変換する long long all_msec = tp_msec.count(); // 1秒未満の値を取り出す int msec = all_msec % 1000; </syntaxhighlight> <br> 時間、分、秒を取得するため、<code>time_t</code>型に変換する。<br> さらに、現地時間 (日本時間) に変換する。<br> <syntaxhighlight lang="c++"> time_t time = std::chrono::system_clock::to_time_t(tp); struct tm* t = localtime(&time); </syntaxhighlight> <br> この時、本日の経過時刻 (mS) は計算できるが、<code>std::chrono::system_clock::time_point</code>型は減算ができるため、本日の0時0分0秒000のタイムスタンプを求める。<br> <syntaxhighlight lang="c++"> // 本日0時0分0秒000のtime_pointを求める std::chrono::system_clock::time_point day_tp = tp; // 0時にする day_tp -= std::chrono::hours(t->tm_hour); // 0分にする day_tp -= std::chrono::minutes(t->tm_min); // 0秒にする day_tp -= std::chrono::seconds(t->tm_sec); // コンマ0秒にする day_tp -= std::chrono::milliseconds(msec); </syntaxhighlight> <br> <code>time_point</code>型同士で減算した後、本日の経過時刻 (mS) を求める。<br> <syntaxhighlight lang="c++"> std::chrono::milliseconds tp_msec_today = std::chrono::duration_cast<std::chrono::milliseconds>(tp - day_tp); int msec_today = tp_msec_today.count(); </syntaxhighlight> <br> 以下の例では、UTC時間、日本時間、フランス時間の3つのタイムゾーンで現在時刻と本日の経過時間を表示している。<br> <br> 以下の例は夏時間を考慮していないため、実務では、タイムゾーンライブラリ (例: Howard Hinnant's dateライブラリ等) の使用を検討すること。<br> (フランスの時差は、一般的に、UTC+1 であるが、夏時間中は UTC+2 となる)<br> <br> <syntaxhighlight lang="c++"> #include <iostream> #include <chrono> #include <ctime> #include <iomanip> // タイムゾーンごとの時差 (秒) const int JAPAN_OFFSET = 9 * 3600; // 日本時間 const int FRANCE_OFFSET = 1 * 3600; // フランス時間 (ただし、夏時間を考慮していないことに注意する) // 指定されたタイムポイントを文字列形式に変換する // オフセットを適用してタイムゾーンを調整する std::string format_time(const std::chrono::system_clock::time_point &tp, int offset = 0) { auto time = std::chrono::system_clock::to_time_t(tp) + offset; auto msec = std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch()).count() % 1000; std::tm* t = std::gmtime(&time); std::ostringstream oss; oss << std::put_time(t, "%Y-%m-%d %H:%M:%S") << '.' << std::setfill('0') << std::setw(3) << msec; return oss.str(); } // 指定されたタイムポイントの日の開始時刻 (00:00:00.000) を計算する // タイムゾーンのオフセットも考慮する std::chrono::system_clock::time_point get_day_start(const std::chrono::system_clock::time_point &tp, int offset = 0) { auto time = std::chrono::system_clock::to_time_t(tp) + offset; std::tm* t = std::gmtime(&time); return tp - std::chrono::hours(t->tm_hour) - std::chrono::minutes(t->tm_min) - std::chrono::seconds(t->tm_sec) - std::chrono::milliseconds(std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch()).count() % 1000) - std::chrono::seconds(offset); } // 指定されたタイムゾーンの現在時刻と経過時間を表示する void print_time_info(const std::string &zone_name, const std::chrono::system_clock::time_point &tp, int offset = 0) { auto day_start = get_day_start(tp, offset); auto msec_today = std::chrono::duration_cast<std::chrono::milliseconds>(tp - day_start).count(); std::cout << zone_name << ":" << std::endl; std::cout << " 現在時刻: " << format_time(tp, offset) << std::endl; std::cout << " 経過時間: " << msec_today << " ms" << std::endl; std::cout << std::endl; } int main() { auto now = std::chrono::system_clock::now(); print_time_info("UTC", now); print_time_info("日本時間", now, JAPAN_OFFSET); print_time_info("フランス時間", now, FRANCE_OFFSET); // フランス時間で return 0; } </syntaxhighlight> <br> # 出力例 UTC: 現在時刻: 2024-09-05 05:30:45.123 経過時間: 19845123 ms 日本時間: 現在時刻: 2024-09-05 14:30:45.123 経過時間: 52245123 ms フランス時間: 現在時刻: 2024-09-05 06:30:45.123 経過時間: 23445123 ms <br> <u>※注意</u><br> <u>より正確な時間を取得する場合は、タイムゾーンライブラリ (例: Howard Hinnant's dateライブラリ等) の使用を推奨する。</u><br> <br> ==== std::chrono (C++17) ==== C++17以降では、<code><chrono></code>ライブラリに大幅な拡張が加えられており、タイムゾーンやカレンダーの扱いが簡単になった。<br> 特に、<code>std::chrono::zoned_time</code>クラスの導入により、タイムゾーンを考慮した時間の扱いが可能になった。<br> 以下の例では、C++17の新機能を使用して、UTC時間、日本時間、フランス時間の3つのタイムゾーンで現在時刻と本日の経過時間を表示している。<br> <br> 処理の流れを以下に示す。 # <code>zoned_time</code>クラスを使用して、特定のタイムゾーンでの時間を表現する。 # <code>floor<days></code>を使用して、その日の開始時刻 (午前0時) を計算する。 # <code>duration_cast</code>を使用して、経過時間をミリ秒単位で計算する。 # タイムゾーンは文字列で指定する。 ("UTC", "Asia/Tokyo", "Europe/Paris")<br>これにより、夏時間なども自動的に考慮される。 # タイムゾーンが見つからない場合等はエラーとする。 <br> <syntaxhighlight lang="c++"> #include <iostream> #include <chrono> #include <iomanip> using namespace std::chrono; template<typename Clock, typename Duration> void print_time_info(const std::string &zone_name, const zoned_time<Duration> &zt) { auto now = zt.get_local_time(); auto today = floor<days>(now); auto time_since_midnight = now - today; std::cout << zone_name << ":\n"; std::cout << " 現在時刻: " << now << "\n"; std::cout << " 経過時間: " << duration_cast<milliseconds>(time_since_midnight).count() << " ms\n\n"; } int main() { try { // 現在のUTC時間を取得 auto now = system_clock::now(); // 各タイムゾーンでの時間を計算 auto utc = zoned_time<milliseconds>("UTC", now); auto tokyo = zoned_time<milliseconds>("Asia/Tokyo", now); auto paris = zoned_time<milliseconds>("Europe/Paris", now); // 各タイムゾーンの情報を表示 print_time_info("UTC", utc); print_time_info("日本時間", tokyo); print_time_info("フランス時間", paris); } catch (const std::exception &e) { std::cerr << "エラー: " << e.what() << std::endl; return -1; } return 0; } </syntaxhighlight> <br> # 出力例 UTC: 現在時刻: 2024-09-05 05:30:45.123456 経過時間: 19845123 ms 日本時間: 現在時刻: 2024-09-05 14:30:45.123456 経過時間: 52245123 ms フランス時間: 現在時刻: 2024-09-05 07:30:45.123456 経過時間: 27045123 ms <br> ==== std::chrono (C++20) ==== C++20では、<code>std::chrono::month</code>や<code>std::chrono::year</code>が追加されたため、月初めからや年頭からの経過時刻 (mS) を取得することができる。<br> また、C++20では、現地時刻用の<code>time_point</code>型、今日の時間情報を取得する<code>time_of_day</code>クラスも追加されるため、<code>time_t</code>型に変換せずに簡単に取得できる。<br> <br> C++20での主な改善点を以下に示す。<br> * カレンダーと時間帯のサポートの強化された。 * 日付の操作がより直感的になった。 * 時間帯データベースへのアクセスが改善された。 * 書式化機能が強化されて、日付と時間の出力がより柔軟になった。 <br> C++20の時間関連機能において、複雑な日付と時間の操作を含むアプリケーションの開発が大幅に簡素化された。<br> <br> <syntaxhighlight lang="c++"> #include <iostream> #include <chrono> #include <format> using namespace std::chrono; template<typename Clock, typename Duration> void print_time_info(const std::string &zone_name, const zoned_time<Duration> &zt) { auto now = zt.get_local_time(); auto today = floor<days>(now); auto time_since_midnight = now - today; auto ymd = year_month_day{today}; auto time = hh_mm_ss{floor<milliseconds>(time_since_midnight)}; std::cout << std::format("{}: \n", zone_name); std::cout << std::format(" 現在時刻: {:%Y-%m-%d %H:%M:%S}.{:03d}\n", now, time.subseconds().count()); std::cout << std::format(" 経過時間: {} ms\n\n", duration_cast<milliseconds>(time_since_midnight).count()); } int main() { try { // 現在のシステム時間を取得 auto now = system_clock::now(); // タイムゾーンオブジェクトを取得 const auto utc = locate_zone("UTC"); const auto tokyo = locate_zone("Asia/Tokyo"); const auto paris = locate_zone("Europe/Paris"); // 各タイムゾーンでの時間を計算 auto utc_time = zoned_time{utc, now}; auto tokyo_time = zoned_time{tokyo, now}; auto paris_time = zoned_time{paris, now}; // 各タイムゾーンの情報を表示 print_time_info("UTC", utc_time); print_time_info("日本時間", tokyo_time); print_time_info("フランス時間", paris_time); // 日付操作の例 auto today = floor<days>(utc_time.get_local_time()); auto this_year = year_month_day{today}.year(); auto new_years_day = sys_days{this_year/January/1}; auto days_since_new_year = floor<days>(utc_time.get_sys_time() - new_years_day); std::cout << std::format("今年の元旦から今日までの日数: {} 日\n", days_since_new_year.count()); } catch (const std::exception &e) { std::cerr << "エラー: " << e.what() << std::endl; return -1; } return 0; } </syntaxhighlight> <br> # 出力例 UTC: 現在時刻: 2024-09-05 05:30:45.123 経過時間: 19845123 ms 日本時間: 現在時刻: 2024-09-05 14:30:45.123 経過時間: 52245123 ms フランス時間: 現在時刻: 2024-09-05 07:30:45.123 経過時間: 27045123 ms 今年の元旦から今日までの日数: 249 日 <br> <u>※注意</u><br> <u>一部の機能 (特にタイムゾーン関連) は、使用する実装によっては、まだ完全にはサポートされていない可能性がある。</u><br> <br> ==== Howard Hinnant's dateライブラリ ==== Howard Hinnant's dateライブラリは強力で柔軟性が高いため、C++20の標準ライブラリと同様の機能を提供している。<br> また、C++20の標準ライブラリと非常に互換性が高く、追加の機能も使用できる。<br> <br> 特に、C++20のサポートがまだ完全でない環境やより高度なタイムゾーン機能が必要な場合に適している。<br> <br> Howard Hinnant's dateライブラリのメリットを以下に示す。<br> * C++20の標準ライブラリとよく似たインターフェースを提供しているため、将来的にC++20への移行時の変更が最小限で済む。 * 広範なプラットフォームとコンパイラでサポートされている。 * タイムゾーンデータベースの更新が容易である。 * 追加の機能 (例: タイムゾーン間の変換) が利用可能である。 <br> 以下の例では、Howard Hinnant's dateライブラリを使用して、UTC時間、日本時間、フランス時間の3つのタイムゾーンで現在時刻と本日の経過時間を表示している。<br> <br> <syntaxhighlight lang="c++"> #include <iostream> #include <iomanip> #include "date/date.h" #include "date/tz.h" using namespace date; using namespace std::chrono; template<typename Clock, typename Duration> void print_time_info(const std::string &zone_name, const zoned_time<Duration> &zt) { auto now = zt.get_local_time(); auto today = floor<days>(now); auto time_since_midnight = now - today; auto ymd = year_month_day{today}; auto time = make_time(floor<milliseconds>(time_since_midnight)); std::cout << zone_name << ": \n"; std::cout << " 現在時刻: " << ymd << ' ' << time << '\n'; std::cout << " 経過時間: " << duration_cast<milliseconds>(time_since_midnight).count() << " ms\n\n"; } int main() { try { // 現在のシステム時間を取得 auto now = system_clock::now(); // 各タイムゾーンでの時間を計算 auto utc_time = zoned_time{"UTC", now}; auto tokyo_time = zoned_time{"Asia/Tokyo", now}; auto paris_time = zoned_time{"Europe/Paris", now}; // 各タイムゾーンの情報を表示 print_time_info("UTC", utc_time); print_time_info("日本時間", tokyo_time); print_time_info("フランス時間", paris_time); // 日付操作の例 auto today = floor<days>(utc_time.get_local_time()); auto this_year = year_month_day{today}.year(); auto new_years_day = sys_days{this_year/January/1}; auto days_since_new_year = floor<days>(utc_time.get_sys_time() - new_years_day); std::cout << "今年の元旦から今日までの日数: " << days_since_new_year.count() << " 日\n"; // タイムゾーン間の変換例 auto tokyo_local = tokyo_time.get_local_time(); auto paris_local = zoned_time{"Europe/Paris", tokyo_local}; std::cout << "\n東京時間 " << tokyo_local << std::endl; std::cout << "パリ時間 " << paris_local.get_local_time() << std::endl; } catch (const std::exception &e) { std::cerr << "エラー: " << e.what() << std::endl; return -1; } return 0; } </syntaxhighlight> <br> # 出力例 UTC: 現在時刻: 2024-09-05 05:30:45.123 経過時間: 19845123 ms 日本時間: 現在時刻: 2024-09-05 14:30:45.123 経過時間: 52245123 ms フランス時間: 現在時刻: 2024-09-05 07:30:45.123 経過時間: 27045123 ms 今年の元旦から今日までの日数: 249 日 東京時間 2024-09-05 14:30:45.123 は、 パリ時間 2024-09-05 07:30:45.123 です。 <br><br> == 比較 : C++標準タイムゾーンライブラリとHoward Hinnant's dateライブラリ == C++20の標準タイムゾーンライブラリとHoward Hinnant's dateライブラリでは、互いに長所・短所があり、プロジェクトの要件により適切な選択が異なる場合がある。<br> <br> * C++20の標準タイムゾーンライブラリ ** メリット **: 標準ライブラリの一部であるため、追加のライブラリをインストールする必要がない。 **: 将来的には、全てのC++20準拠のコンパイラでサポートされる。 **: 標準化されているため、長期的なサポートが期待できる。 ** デメリット **: 現時点では、全てのコンパイラやプラットフォームで完全にサポートされているわけではない。 **: 初期の実装では、機能が制限されている可能性がある。 **: タイムゾーンデータベースの更新方法が明確でない場合がある。 <br> * Howard Hinnant's dateライブラリ ** メリット **: 長年にわたって開発されてきた成熟したライブラリである。 **: より広範な機能セットを提供している。 **: タイムゾーンデータベースの更新が容易である。 ** 短所 **: 追加のライブラリをプロジェクトに組み込む必要がある。 **: プロジェクトに外部依存関係を追加することになる。 <br> C++20の標準ライブラリを選択する場合は、長期的なプロジェクトであり標準化された解決策を求める場合や外部依存関係を最小限に抑えたい場合等がある。<br> Howard Hinnant's dateライブラリを選択する場合は、より高度なタイムゾーン機能が必要な場合やタイムゾーンデータベースの頻繁な更新が必要な場合等がある。<br> <br> ただし、長期的なプロジェクトや標準化された解決策を求める場合は、C++20の標準ライブラリの使用を推奨する。<br> 使用しているコンパイラとプラットフォームが完全にサポートしていることを確認する必要がある。<br> <br><br> __FORCETOC__ [[カテゴリ:C++]]
C++の基礎 - 時刻
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse