携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情
chrono 库中提供了一个表示时间点的类 time_point,该类的定义如下:
// 定义于头文件 <chrono>
template<class Clock, class Duration = typename Clock::duration>
class time_point;
它被实现成如同存储一个 Duration 类型的自 Clock 的纪元起始开始的时间间隔的值,通过这个类最终可以得到时间中的某一个时间点。
- Clock:此时间点在此时钟上计量
- Duration:用于计量从纪元起时间的 std::chrono::duration 类型
time_point的实现很简单,使用Duration类型的成员变量存储时间;仔细想想也是,时间点也是从0时刻开始经过一定时间间隔的某一个时刻。
构造函数
// 1. 构造一个以新纪元(epoch,即:1970.1.1)作为值的对象,需要和时钟类一起使用,不能单独使用该无参构造函数
time_point();
// 2. 构造一个对象,表示一个时间点,其中d的持续时间从epoch开始,需要和时钟类一起使用,不能单独使用该构造函数
explicit time_point( const duration& d );
// 3. 拷贝构造函数,构造与t相同时间点的对象,使用的时候需要指定模板参数
template< class Duration2 >
time_point( const time_point<Clock,Duration2>& t );
在这个类中除了构造函数还提供了另外一个 time_since_epoch() 函数,用来获得 1970 年 1 月 1 日到 time_point 对象中记录的时间经过的时间间隔(duration),函数原型如下:
duration time_since_epoch() const;
除此之外,时间点 time_point 对象和时间段对象 duration 之间还支持直接进行算术运算(即加减运算),时间点对象之间可以进行逻辑运算,如下示例,其中 end 和 start 是 time_point 类型的对象, 两个相减得到的 是 duration 类型的对象。
#include <chrono>
#include <ctime>
#include <iomanip>
#include <iostream>
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::put_time(std::localtime(&now_c), "%F %T") << '\n';
std::chrono::steady_clock::time_point start =
std::chrono::steady_clock::now();
std::cout << "Hello World\n";
std::chrono::steady_clock::time_point end =
std::chrono::steady_clock::now();
std::cout << "Printing took "
<< std::chrono::duration_cast<std::chrono::microseconds>(end -
start)
.count()
<< "us.\n";
}
time_point_cast
time_point_cast 也是 chrono 库提供的一个模板函数,这个函数不属于 time_point 类。函数的作用是对时间点进行转换,因为不同的时间点对象内部的时钟周期 Period,和周期次数的类型 Rep 可能也是不同的,一般情况下它们之间可以进行隐式类型转换,也可以通过该函数显示的进行转换,函数原型如下:
template <class ToDuration, class Clock, class Duration>
time_point<Clock, ToDuration> time_point_cast(const time_point<Clock, Duration> &t);
示例如下:
#include <chrono>
#include <iostream>
using namespace std;
using Clock = chrono::high_resolution_clock;
using Ms = chrono::milliseconds;
using Sec = chrono::seconds;
template<class Duration>
using TimePoint = chrono::time_point<Clock, Duration>;
void print_ms(const TimePoint<Ms>& time_point)
{
std::cout << time_point.time_since_epoch().count() << " ms\n";
}
int main()
{
TimePoint<Sec> time_point_sec(Sec(6));
// 无精度损失, 可以进行隐式类型转换
TimePoint<Ms> time_point_ms(time_point_sec);
print_ms(time_point_ms); // 6000 ms
time_point_ms = TimePoint<Ms>(Ms(6789));
// error,会损失精度,不允许进行隐式的类型转换
// TimePoint<Sec> sec(time_point_ms);
// 显示类型转换,会损失精度。6789 truncated to 6000
time_point_sec = std::chrono::time_point_cast<Sec>(time_point_ms);
print_ms(time_point_sec); // 6000 ms
}
注意事项:关于时间点的转换如果没有没有精度的损失可以直接进行隐式类型转换,如果会损失精度只能通过显示类型转换,也就是调用 time_point_cast 函数来完成该操作。
C++ chrono这部分内容算是学习完了,分了3篇文章。后面有时间再把这三部分内容整合起来封装一个我们常用的Datetime类吧。