c++11日期和時間庫:chrono

std::chrono 主要包含兩部分,std::chrono::duration 和 std::chrono::time_point,它們都是類模板,std::chrono::duration 表示時間間隔,std::chrono::time_point 表示時間中的一個點。

duration

template <class Rep, class Period = std::ratio<1>>
class duration;

duration 由 Rep 類型的計次數和計次週期組成,其中計次週期是一個編譯期有理數常量,表示從一個計次到下一個的秒數。
存儲於 duration 的數據僅有 Rep 類型的計次數。若 Rep 是浮點數,則 duration 能表示小數的計次數。 Period 被包含爲時長類型的一部分,且只在不同時長間轉換時使用。

template <std::intmax_t Num, std::intmax_t Denom = 1>
class ratio;

ratio 表示值等於 Num/Denom 的有理數,它的靜態數據成員 num 與 den 表示由 Num 與 Denom 除以其最大公約數的分子與分母。

duration 有一些便利類型定義:

類型 定義
std::chrono::nanoseconds duration</*至少 64 位的有符號整數類型*/, std::nano>
std::chrono::microseconds duration</*至少 55 位的有符號整數類型*/, std::micro>
std::chrono::milliseconds duration</*至少 45 位的有符號整數類型*/, std::milli>
std::chrono::seconds duration</*至少 35 位的有符號整數類型*/>
std::chrono::minutes duration</*至少 29 位的有符號整數類型*/, std::ratio<60>>
std::chrono::hours duration</*至少 23 位的有符號整數類型*/, std::ratio<3600>>

duration 的概要聲明:

template <class Rep, class Period = ratio<1>>
class duration {
public:
  using rep = Rep;
  using period = Period;
public:
  // 構造/複製/銷燬
  constexpr duration() = default;
  template <class Rep2>
  constexpr explicit duration(const Rep2& r);
  template <class Rep2, class Period2>
  constexpr duration(const duration<Rep2, Period2>& d);
  ~duration() = default;
  duration(const duration&) = default;
  duration& operator=(const duration&) = default;
  // 探察函數
  constexpr rep count() const;
  // 特殊值
  static constexpr duration zero();
  static constexpr duration min();
  static constexpr duration max();
};

不同時長間轉換時,如果轉換不損失精度,可以使用 std::duration 的構造函數進行轉換,否則要用以下函數進行轉換:

template <class ToDuration, class Rep, class Period>
constexpr ToDuration duration_cast(const duration<Rep, Period>& d);

duration 的一個例子:

#include <iostream>
#include <chrono>

constexpr auto year = 31556952ll; // 格里高利曆年的平均秒數

int main()
{
    using shakes = std::chrono::duration<int, std::ratio<1, 100000000>>;
    using jiffies = std::chrono::duration<int, std::centi/*std::ratio<1, 100>*/>;
    using weeks = std::chrono::duration<float, std::ratio<7*24*60*60>>;
    using nanocenturies = std::chrono::duration<float, std::ratio<100*year, 1000000000>>;

    std::chrono::seconds sec(1);

    std::cout << "1 second is:\n";

    // 無精度損失的整數尺度轉換:無轉型
    std::cout << std::chrono::microseconds(sec).count() << " microseconds\n"
              << shakes(sec).count() << " shakes\n"
              << jiffies(sec).count() << " jiffies\n";

    // 有精度損失的整數尺度轉換:需要轉型
    std::cout << std::chrono::duration_cast<std::chrono::minutes>(sec).count()
              << " minutes\n";

    // 浮點尺度轉換:無轉型
    std::cout << weeks(sec).count() << " weeks\n"
              << nanocenturies(sec).count() << " nanocenturies\n";
}

time_point

template <class Clock, class Duration = typename Clock::duration>
class time_point;

time_point 被實現成如同存儲一個 Duration 類型的自 Clock 的紀元起始開始的時間間隔的值。
Clock 必須滿足 時鐘 (Clock) 的要求,庫提供了三種 Clock:

class description
system_clock 來自系統範疇實時時鐘的掛鐘時間
steady_clock 決不會調整的單調時鐘
high_resolution_clock 擁有可用的最短嘀嗒週期的時鐘

其中 system_clock 的概要聲明:

class system_clock {
public:
  using rep = /* 見說明 */ ;
  using period = ratio</* 未指明 */, /* 未指明 */ >;
  using duration = chrono::duration<rep, period>;
  using time_point = chrono::time_point<system_clock>;
  static constexpr bool is_steady = /* 未指明 */ ;
  static time_point now() noexcept;
  // 以上是Clock必須滿足的要求
  static time_t to_time_t (const time_point& t) noexcept;
  static time_point from_time_t(time_t t) noexcept;
};

time_point 的概要聲明:

template <class Clock, class Duration = typename Clock::duration>
class time_point {
public:
  using clock = Clock;
  using duration = Duration;
  using rep = typename duration::rep;
  using period = typename duration::period;
public:
  // 構造
  constexpr time_point(); // 擁有紀元值
  constexpr explicit time_point(const duration& d); // 同 time_point() + d
  template <class Duration2>
  constexpr time_point(const time_point<clock, Duration2>& t);
  // 探察函數
  constexpr duration time_since_epoch() const;
  // 算術
  constexpr time_point& operator+=(const duration& d);
  constexpr time_point& operator-=(const duration& d);
  // 特殊值
  static constexpr time_point min();
  static constexpr time_point max();
};

time_point_cast 用於同一 clock 下一個 time point 向另一個 time point 的轉換:

template <class ToDuration, class Clock, class Duration>
constexpr time_point<Clock, ToDuration>
time_point_cast(const time_point<Clock, Duration>& t);

time_point 的一個例子:

#include <iostream>
#include <chrono>
#include <ctime>

using Ms = std::chrono::milliseconds;
using Sec = std::chrono::seconds;

template <class Duration>
using TimePoint = std::chrono::time_point<std::chrono::high_resolution_clock, Duration>;

inline void print_ms(const TimePoint<Ms>& time_point)
{
    std::cout << time_point.time_since_epoch().count() << " ms\n";
}
int main()
{
    std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
    std::time_t now_c = std::chrono::system_clock::to_time_t(now - std::chrono::hours(24));
    std::cout << "24 hours ago, the time was " << std::ctime(&now_c) << '\n';

    TimePoint<Sec> time_point_sec(Sec(4));
    // 隱式轉換,無精度損失
    TimePoint<Ms> time_point_ms(time_point_sec);
    print_ms(time_point_ms); // 4000 ms

    time_point_ms = TimePoint<Ms>(Ms(5756));
    // 顯式轉型,在精度損失可能發生時需要
    // 5756 truncated to 5000
    time_point_sec = std::chrono::time_point_cast<Sec>(time_point_ms);
    print_ms(time_point_sec); // 5000 ms
}

參考

以上主要參考自 cppreference

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章