chrono 标准库包含在头文件 中,使用时需要包含头文件,为了方便使用,可以导入命名空间

#include <chrono>

using namespace std::chrono;

duration

关于时间的几个变量的定义

显示说明类型

using namespace std::chrono;
using days = duration<int, std::ratio_multiply<std::ratio<24>, hours::period>>;
using weeks = duration<int, std::ratio_multiply<std::ratio<7>, days::period>>;

hours hour = 12h;
minutes minute = 30min;
seconds s = 10s;
milliseconds ms = 100ms;
microseconds us = 200us;
nanoseconds ns = 300ns;

chrono 库中定义了 hours, minutes, seconds, milliseconds, microseconds, nanoseconds, 具体的定义如下:

using nano = ratio<1, 1'000'000'000>;
using micro = ratio<1, 1'000'000>;
using milli = ratio<1, 1000>;

using nanoseconds = duration<int64_t, nano>;
using microseconds = duration<int64_t, micro>;
using milliseconds = duration<int64_t, milli>;
using seconds = duration<int64_t>;
using minutes = duration<int32_t, ratio<60>>;
using hours = duration<int32_t, ratio<3600>>;

这里以秒为标准,其他的通过 duration 的第二个模板参数来建立和秒之间的关系,例如 1min = 60s, 则第二个参数则为 ratio<60, 1>。根据这个规则,可以定义其他的一些时间单位变量,例如:

using days = duration<int32_t, std::ratio_multiply<std::ratio<24>, hours::period>>;
using weeks = duration<int32_t, std::ratio_multiply<std::ratio<7>, days::period>>;
using frames = duration<int32_t, ratio<1, 60>>;

通过 auto 自动推断变量类型

auto hour = 12h;
auto minute = 30min;
auto s = 10s;
auto ms = 100ms;
auto us = 200us;
auto ns = 300ns;

如何输出时间

chrono 库重新实现了 << 操作符,因此可以直接使用该操作符对时间变量进行输出

std::cout << hour.count() << "h\n";
std::cout << minute.count() << "min\n";
std::cout << s.count() << "s\n";
std::cout << ms.count() << "ms\n";
std::cout << us.count() << "us\n";
std::cout << ns.count() << "ns\n";

时间的计算和比较

各个时间变量是可以进行算术运算和比较运算的,支持的运算符包括 +, -, >, >=, <, <=, ==, !=

seconds s1 = 10s;
seconds s2 = 200s;
seconds s3 = 200s;

std::cout << (s2 - s1).count() << "s\n"; // 190s
std::cout << (s1 + s2).count() << "s\n"; // 210s
std::cout << (6 * s1).count() << "s\n"; // 60s
std::cout << (s2 / 4).count() << "s\n"; // 50s
std::cout << std::boolalpha << (s1 < s2) << '\n'; // true
std::cout << std::boolalpha << (s3 <= s2) << '\n'; // true
std::cout << std::boolalpha << (s1 > s2) << '\n'; // false
std::cout << std::boolalpha << (s3 >= s2) << '\n'; // true
std::cout << std::boolalpha << (s3 == s2) << '\n'; // true
std::cout << std::boolalpha << (s3 != s2) << '\n'; // false

数据类型的转换

如果是没有数据截断(例如小时转分钟)的转换则会通过隐式转换的方式进行转换,如果有数据截断(例如分钟转小时会出现小数,而这部分会被截断),则会编译错误,需要进行显式类型转换。

auto hour = 12h;
auto minute = 90min;

minutes minute2 = hour + minute;
hours hour2 = hour + duration_cast<hours>(minute);

std::cout << minute2.count() << "min\n"; // 810min
std::cout << hour2.count() << "h\n"; // 13h

time_point

time_point 有两个模板参数,一个是 clock (将在后面进行介绍),一个是 duration

例如可以定义 1970 年 1 月 1 日之后的 10'000 秒的时间点为

time_point<system_clock, seconds> tp{ 10'000s };

time_point 可以相减,相减之后得到的是一个 duration。一个 time_point 加上一个 duration 会得到另一个 time_point。

auto d = tp1 - tp2;
auto tp2 = tp1 + d;

当存在数据截断时,time_point 也需要进行显示类型转换

time_point<system_clock, seconds> tp{ 5s };        // 5s
time_point<system_clock, milliseconds> tp2 = tp; // 5000ms
tp = time_point_cast<seconds>(tp2); // 5s

可以获取 time_point 到 1970 年 1 月 1 日的时间差

time_point<system_clock, seconds> tp{ 5s };        // 5s
seconds s = tp.time_since_epoch();

time_point<system_clock, milliseconds> tp{ 5000ms }; // 5000ms
milliseconds s = tp.time_since_epoch();

clocks

struct some_clock 
{
using duration = chrono::duration<int64_t, microseconds>;
using rep = duration::rep;
using period = duration::period;
using time_point = chrono::time_point<some_clock>;

static constexpr bool is_steady = false;
static time_point now() noexcept;
};

每一个 time_point 都关联一个时钟(clocks),不同类型的时钟不能相互转换。

两个常用的时钟

std::chrono::system_clock
std::chrono::steady_clock

system_clock 和日历中的时间相关,它可以让你知道是哪一天。steady_clock 通常用于计时。

每个系统时钟都能够获取一个当前时间


clck::time_point tp = clock::now();

实例

auto t0 = steady_clock::now();
f(); // 一个消耗时间的函数,可以通过该方法计算具体的时间消耗
auto t1 = steady_clock::now();
std::cout << nanoseconds{ t1 - t0 }.count() << "ns\n";

对时间加锁

std::timed_mutex mut;
if (mut.try_lock_for(500ms))
// got the lock

if (mut.try_lock_until(steady_clock::now() + 500ms))
// got the lock

自定义时间

using days = duration<int, std::ratio_multiply<std::ratio<24>, hours::period>>;
using days = duration<int, std::ratio<86400>>;

duration 用于休眠

std::this_thread::sleep_for(days{1});
std::this_thread::sleep_for(50s);

计算当前时间到 1970 年 1 月 1 日的秒数和天数

auto tp = time_point_cast<seconds>(system_clock::now()); 
cout << tp.time_since_epoch().count() << "s\n";

auto td = time_point_cast<days>(tp);
cout << td.time_since_epoch().count() << " days\n";