chrono库主要包含了三种类型:时间间隔Duration、时钟Clocks和时间点Time point。时钟是系统内部不断循环执行的时钟,某个一点对应的是时间点timepoint,两个时间点之间的差值是duration,这个就是三者之间的关系。通过一个例子来看一下三者的关系:
// system_clock example #include1. duration#include #include #include int main () { using std::chrono::system_clock; std::chrono::duration > one_day (1); system_clock::time_point today = system_clock::now(); system_clock::time_point tomorrow = today + one_day; std::time_t tt; tt = system_clock::to_time_t ( today ); std::cout << "today is: " << ctime(&tt); tt = system_clock::to_time_t ( tomorrow ); std::cout << "tomorrow will be: " << ctime(&tt); return 0; }
duration为一个模板类,表示时间间隔,其定义如下:template
void duration_initialization() {
std::chrono::duration> default_duration_milliseconds; // 其初始化值未定义,随生成环境而定
std::chrono::duration> duration_milliseconds(1000); // 1000 ms
std::chrono::duration double_duration_seconds(3.5); // 3.5s
std::chrono::milliseconds duration_predefine_milliseconds(1000); // 1000ms
std::chrono::microseconds t1_duration_microseseconds = duration_milliseconds; // 1000 ms
std::chrono::microseconds t2_duration_microseseconds(duration_milliseconds); // 1000 ms
using namespace std::chrono;
auto user_define_literals = 1000ms; //1000 ms
};
}
void data_access() {
using namespace std::chrono;
seconds duration_seconds(12); // 12s
std::cout << "duration represent "
<< duration_seconds.count() << "s" << std::endl; // duration represent 12s
auto max_duration_seconds = seconds::max(); // 获取seconds所能表示的最大duration
std::cout << "maximum seconds duration "
<< max_duration_seconds.count() << std::endl; // maximum seconds duration 9223372036854775807
auto min_duration_seconds = seconds::min(); // 获取seconds所能表示的最小duration
std::cout << "minimum seconds duration "
<< min_duration_seconds.count() << std::endl; // minimum seconds duration -9223372036854775808
std::cout << "INT64_MAX" << INT64_MAX << " "
<< "INT64_MIN" << INT64_MIN << std::endl; //INT64_MAX9223372036854775807 INT64_MIN-9223372036854775808
};
1.2. 数据转换
当两者duration之间都为整数并且源period可被目标period整除时,或者目标duration为浮点数时可以使用传统类型转化或者隐式调用其单值构造函数,不必调用duration_cast。
void typeConversions() {
std::chrono::milliseconds int_milliseconds(1024); // 1024ms
std::chrono::microseconds int_microseconds(1024); // 1024us
std::chrono::duration double_second = int_milliseconds; // 1.024s = 1024ms
double_second = int_microseconds; // 0.001024s = 1024us
double_second = std::chrono::duration(1024.1024); // 0.0010241024s = 1024.1024us
int_milliseconds = std::chrono::seconds(1024); // 1024000ms = 1024s
int_microseconds = int_milliseconds; // 1024000000us = 1024000ms
// 此实例按照我们常人的逻辑是可以进行的 1024102400us = 1024.1024s,这里为了保证正确性,就直接把这种转换禁止掉了
// std::chrono::microseconds t1 = std::chrono::duration(1024.1024);
// second period == 1, microseconds period == 1/1000000,显然 1/1000000 除以 1 不能整除
// std::chrono::seconds t1 = std::chrono::microseconds(1024);
std::chrono::seconds t1 = std::chrono::duration_cast(std::chrono::milliseconds(1024)); // 1s = 1024ms(精度损失)
std::chrono::seconds t2 = std::chrono::duration_cast(std::chrono::duration(1.024)); // 1s = 1.024s
}
1.3 运算符
void duration_calculation() {
//
auto t1 = std::chrono::seconds(1) + std::chrono::milliseconds(10);
std::cout << "t1 type is "<< (bool)(typeid(t1) == typeid(std::chrono::milliseconds)) << std:: endl;
std::cout << "t1 count " << t1.count() << std::endl;
auto t2 = std::chrono::duration>(1) + std::chrono::duration>(1);
std::cout << "t2 type is "<< (bool)(typeid(t2) == typeid(std::chrono::duration>)) << std:: endl;
std::cout << "t2 count " << t2.count() << std::endl;
auto t3 = std::chrono::duration>(1) + std::chrono::duration>(1);
std::cout << "t3 type is "<< (bool)(typeid(t3) == typeid(std::chrono::duration>)) << std:: endl;
std::cout << "t3 count " << t3.count() << std::endl;
}
- common_type
从前面的例子中,我们可以看到对duration之间的计算需要将其转化为common_type。chrono库为我们提供了方便地struct模板让我们能够轻松获取到两个duration的common type
void common_type() {
using commonType = std::common_type>, std::chrono::duration>>::type;
commonType t = std::chrono::duration>(1) + std::chrono::duration>(1); // 可以编译通过,说明类型一致
std::cout << "commonType type is "<< (bool)(typeid(commonType) == typeid(std::chrono::duration>)) << std:: endl;
}
2. time_point
chrono库对于一个时间点来说,其采用如下表示方法。一个起始时间epoch 和 时间长度 duration。类似于Unix中的时间表示方法。在Unix中,基础时间点为1970/1/1 00:00:00。之后所有时间点都是time秒 + 基础时间点。chrono库在这基础上的改进就是将time秒变为了duration。uration有更为丰富可变的时钟周期period,它能够表示更为精准的时间点或者粗略的时间点,这一切全部由duration进行控制。
void initialization_time_point() {
// 默认构造函数,创建一个time_poin代表时钟的起始时间(Clock'epoch)
std::chrono::time_point
// 创建一个time_point, 其time_point = Clock'epoch + duration
// 调用条件为传入duration可以转换到time_point的duration类型
std::chrono::time_point
// 创建一个time_point, 其值为从time_point 的拷贝
// 从time_point1 可以转换到 time_point2 需要要求 time_point1.duration 可以向 time_point2.duration进行转化
std::chrono::time_point
std::chrono::time_point
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
time_point 数据访问
void time_point_since_epoch() {
auto tp0 = std::chrono::time_point
auto tp1 = std::chrono::time_point
auto tp2 = tp0 - std::chrono::hours(24);
std::chrono::hours tp0_since_epoch_hours = std::chrono::duration_cast
std::chrono::hours tp1_since_epoch_hours = std::chrono::duration_cast
std::chrono::hours tp2_since_epoch_hours = std::chrono::duration_cast
std::time_t tm = std::chrono::system_clock::to_time_t(tp0);
std::cout << std::ctime(&tm); // Thu Jan 1 08:00:00 1970
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
time_point 转化规则
void time_point_type_conversions() {
// 对于任意两个时间点来说,对于其的任何操作都需要一个前提,即两个time_point构造时使用同一个clock
// 使用同一个clock意味着两个time_point参照同一个epoch
// 如果两个time_point的epoch不相等,那么我们对于其任何的计算都是无意义的
std::chrono::time_point
std::chrono::time_point
std::chrono::time_point
// tp1 == tp2; // 可以通过编译, 这里是因为系统库 using high_resolution_clock = system_clock;
// tp1 == tp3; // 编译错误
using namespace std::chrono;
std::chrono::time_point
std::chrono::time_point
tp_milliseconds = tp_seconds; // 可以
// tp_seconds = tp_milliseconds; // 不可以
tp_seconds = std::chrono::time_point_cast
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
time_point的相关计算
void time_point_calculate() {
using namespace std::chrono;
// 包含如下计算
// time_point = time_point + duration
// time_point = time_point - duration
// time_point = duration + time_point
// 其中返回的time_point的duration类型为 common_type
auto tp = time_point
if(typeid(tp) == typeid(time_point
// duration = time_point1 - time_point2
// duration类型为 common_type
auto tp1 = time_point
auto tp2 = time_point
auto dur = tp1 - tp2;
if(typeid(dur) == typeid(duration
using co_type = std::common_type
if(typeid(co_type) == typeid(time_point
}
clock由一个起始时间点epoch和时钟周期tick rate组成。chrono库为我们预定义了3个时钟类型:
- system_clock:system_clock代表系统时间,表示与操作系统时间同步的时钟。因为系统时间可以在任意时刻被更改,所以此时钟并不单调。
void clock_system_clock() {
std::chrono::system_clock::time_point np = std::chrono::system_clock::now(); // 获取当前系统时间点
if(std::chrono::system_clock::is_steady); // 判断此时钟是否单调
std::time_t tm = std::chrono::system_clock::to_time_t(np); // time_point --> time_t
std::cout << std::ctime(&tm);
using namespace std::chrono;
std::this_thread::sleep_for(10s); // 主线程睡眠10s
tm = time(nullptr);
np = std::chrono::system_clock::from_time_t(tm); // time_t --> time_point
std::time_t temp = std::chrono::system_clock::to_time_t(np); // time_point没办法打印, 只能依靠现有的C库进行,C++20有所改进
std::cout << std::ctime(&temp); //
}
- steady_clock:steady_clock仅包含now成员方法,代表一个单增时钟,其时钟的时间点不可能减少,因为物理时间只能向前移动并且每次时钟跳动间隔固定。这个时钟与系统时间无关(此事件可以为,距离上次重启系统所经历的事件),其非常适合用于计算时间间隔。
- high_resolution_clock
using high_resolution_clock = system_clock;



