时间chrono库详解

chrono库简介

C++ 的 chrono 库是 C++11 引入的一个用于处理时间和日期的标准库,它提供了一套丰富的工具来测量时间间隔、执行时间点的计算以及处理日期和时间。

chrono 库主要有以下几个功能:

  • 时间点:表示了一个特定的时间点,就比如当前的时间;

  • 时间段:表示一段时间的长度,如一秒,一分钟,一小时,一天等;

  • 时钟:是时间点和持续时间的来源,运行库提供了几种不同的时钟,例如系统时钟、高分辨率时钟等。

接下来分别看一下 chrono 库中三个不同的时钟:

时钟描述
system_clock表示你的电脑当前的系统时间。
steady_clock比较稳定的时钟,不随电脑性能等因素变化。
high_resolution_clock系统可用的最高精度时钟。

下面还有两个 chrono 库中常用的类:

类名描述
time_point时间点,表示一个具体时间。
duration时间段,表示一段时间。

接下来我们来看一下它们具体的用法。

chrono 库函数与用法

I.   chrono \texttt{I.\ chrono} I. chrono 的头文件以及命名空间

首先在使用 chrono 库前,我们肯定需要导入 chrono 库:

#include<chrono>

chrono 库还是 std 命名空间的一个子命名空间,所以我们在使用的时候也要在程序前面加上:

using namespace std::chrono;

接下来,我们就可以愉快的写代码了。

II.   system_clock \texttt{II.\ system\_clock} II. system_clock

system_clock 类表示系统时间,也就是说,不管你的系统是什么时间,这个类都会表示出你的系统时间。

steady_clock \texttt{steady\_clock} steady_clock 的类成员
类成员描述
duration接下来要介绍到的时间段类,是 system_clock 类的子类,表示一个时间段。
from_time_t()time_t 类导入时间。
now()用于获取当前系统时间。
period表示一个时间单位的子类。
time_point表示一个时间点的类,也是 system_clock 中的一个子类。
to_time_t()time_point 转化为 time_t 类型。
获取与输出当前时间
示例代码
#include<bits/stdc++.h>
using namespace std;
using namespace std::chrono;
int main(){
	system_clock::time_point now=system_clock::now();
	time_t tp1=system_clock::to_time_t(now);
	//I
	string str_time=ctime(&tp1);
	cout<<str_time;
	//II
	tm* tpm=localtime(&tp1);
	cout<<put_time(tpm,"%c")<<endl;
	//III
	char buf[80];
	strftime(buf,sizeof(buf),"%Y/%m/%d %H:%M:%S",tpm);
	printf("%s",buf);
	
	return 0;
}

运行结果:

Fri Feb 07 18:16:55 2025
02/07/25 18:16:55
2025/02/07 18:16:55
--------------------------------
Process exited after 0.0337 seconds with return value 0
请按任意键继续. . .
代码解析

上面的代码展示了获取系统时间方法以及三种不同的输出时间的方式,下面给出了每行代码具体的作用与解释:


system_clock::time_point now=system_clock::now();

time_point 类不能单独使用,必须作为其他类中的子类使用。system_clock::now 函数返回了一个 system_clock::time_point 类,表示当前的时间。


time_t tp1=system_clock::to_time_t(now);

system_clock_to_time_t 函数用于将一个时间点类转化为 time.h 中的 time_t 类。


string str_time=ctime(&tp1);
cout<<str_time;

ctime 函数将 time_t 类型转化为 string自带换行。它的使用方法非常简单,但是只能以固定格式输出,比较不灵活。


tm* tpm=localtime(&tp1);
cout<<put_time(tpm,"%c")<<endl;

put_time 函数输出 tm 类型的时间,格式也是固定的。

char buf[80];
strftime(buf,sizeof(buf),"%Y/%m/%d %H:%M:%S",tpm);
printf("%s\n",buf);

这个函数就比较灵活,可以以任意格式输出时间。


III.   steady_clock \texttt{III.\ steady\_clock} III. steady_clock

steady_clock 是一个“稳定的时间”,不会因为电脑算力或者其他意外的因素而改变。应该会有同学用过 windows.h 库中的 Sleep 函数用于等待一定的时间,你会发现在不同的电脑上 Sleep 的等待时间可能会不一样,因为这个函数依赖于系统的速度。

steady_clock 就很好的解决了这个问题。接下来我们来看一下如何去使用这个类。

steady_clock \texttt{steady\_clock} steady_clock 的类成员

steady_clock 类中的类成员大多与 system_clock 中的相似。

类成员描述
duration表示时间段的子类。
now()获取当前时间。
period表示时间单位的子类。
time_point表示时间点的子类。
计算经过的时间
示例代码
#include<bits/stdc++.h>
using namespace std;
using namespace std::chrono;
int main(){
	steady_clock::time_point start=steady_clock::now();
	getchar();
	steady_clock::time_point end=steady_clock::now();
	cout<<(duration_cast<milliseconds>(end-start).count()/1000.0)<<endl;
	return 0;
}

我们运行上面的程序,等一会按下任意的一个键,就会输出程序开始到我们按下键盘的秒数。


1.979

--------------------------------
Process exited after 2.012 seconds with return value 0
请按任意键继续. . .
代码解析
steady_clock::time_point start=steady_clock::now();

记录开始的时间点,使用 steady_clock::now() 函数。


getchar();

获取键盘输入。


steady_clock::time_point end=steady_clock::now();

记录结束时间点。


cout<<(duration_cast<milliseconds>(end-start).count()/1000.0)<<endl;

这一行代码是难点,我们来逐步解析。

首先,duration_cast 函数用于转换时间单位,他是一个模版函数,所以使用的语法可能有点奇怪。

两个 <> 中间填的是你要转化成的时间单位,milliseconds 是库里面已经规定好的一个特定的时间单位,意为毫秒。

下面列举了一些其他的库中已规定的时间单位:

  • hours:小时;

  • minutes:分钟;

  • seconds:秒;

  • milliseconds:毫秒;

  • nanoseconds:微妙。

所以上面的 duration_cast<milliseconds>(end-start).count() 返回 end-start 时间段所代表的毫秒数。

整行代码的意思就是输出 (end-start) 经过的秒数。

IV.   high_resolution_clock \texttt{IV.\ high\_resolution\_clock} IV. high_resolution_clock

high_resolution_clock 是一个高精度的时钟,也是计算机内精度最高的时钟。其用法与 steady_clock 差不多,只是精度有所不同,所以此处也不多赘述。

V.   duration \texttt{V.\ duration} V. duration

一个表示时间段长度的类,使你可以自定义时间单位,不再局限于库中自带的 hoursminutes 时间单位。

duration \texttt{duration} duration 的类成员
类成员描述
max()获取可能的最大时间段。
min()获取可能的最小时间段。
period时间单位类。
zero()代表时间段 0 0 0
自定义时间单位

如下面的示例,我们可以自由地自定义事件单位:

duration< int > _5s(5);
duration< double,ratio<3600> > _6min(0.1);
duration< double,ratio<1,500> > _1ms(0.5);
minutes _2min(2);
milliseconds _1s(1000);

看上去很复杂,所以让我来具体讲一下如何正确地使用 duration


duration<int> _5s(5);

首先,duration 是一个模版类,上面代码中的 int 表示参数类型。

比如,要定义五秒就填 int,半秒就填doublefloat,以此类推。

上面的 _5s 是时间单位的名称,这样我们就可以像上面的 milliseconds 一样使用了。

再后面的 (5),代表了 5 5 5 个默认单位,也就是五秒。

所以,我们就定义了一个名为 _5s,代表五秒的时间单位了。


duration< double,ratio<3600> > _6min(0.1);

这里又多出了一个新的模版参数。chrono 中默认的时间单位是秒,所以这里的 ratio<3600> 就相当于是一个临时的时间单位,表示 3600 3600 3600 秒,一个小时。

上面的 _6min(0.1) 定义了一个时长为 0.1 0.1 0.1ratio<3600>,也就是六分钟的时间单位。


duration< double,ratio<1,500> > _1ms(0.5);

如果在 ratio 里填入两个参数则又是不同的意思,上面的 ratio<1,500> 代表的是 1 500 \frac{1}{500} 5001 个默认单位,也就是 1 500 \frac{1}{500} 5001 秒, 2 2 2 毫秒。

所以后面的 _1ms(0.5) 定义了 0.5 0.5 0.5ratio<1,500>,为一毫秒。


minutes _2min(2);

这里的 minutes 代表着一分钟的默认单位,所以上面代码中的 _2min 是一个代表两分钟的时间段。


milliseconds _1s(1000);

同上面一样,这里定义了一个 _1s 的时间段对象,而它代表的时间是 1000 1000 1000milliseconds,也就是一秒。

duration \texttt{duration} duration 对象的操作

有时候我们需要将几个时间段相加或进行比较,这时候我们就可以使用 duration 对象的操作了。

操作代码描述
相加duration1+duration2将两个时间段相加,返回一个新的 duration 对象
相减duration1-duration2将两个时间段相减,返回一个新的 duration 对象
相乘duration1*nn*duration1将时间段与一个实数相乘,返回一个新的 duration 对象
相除duration1/n将时间段与一个实数相除,返回一个新的 duration 对象
判断相等duration1==duration2判断两个 duration 对象是否相等。
判断不等duration1!=duration2判断两个 duration 对象是否不等。
判断是否大于duration1>duration2判断第一个 duration 对象是否大于第二个 duration 对象
判断是否小于duration1<duration2判断第一个 duration 对象是否小于第二个 duration 对象
判断是否大于等于duration1>=duration2判断第一个 duration 对象是否大于等于第二个 duration 对象
判断是否小于等于duration1<=duration2判断第一个 duration 对象是否小于等于第二个 duration 对象
时间单位的转换

如果我们现在有一个 hours 对象,想要把他转换为 seconds,则可以通过下面的代码实现:

hours _1h(1);
seconds _1s=duration_cast<seconds>(_1h);

这样 _1s 就是一个表示一秒的时间段对象了。

VI.   time_point \texttt{VI.\ time\_point} VI. time_point

一个表示时间点的类,通常作为子类出现,不能单独使用。

time_point \texttt{time\_point} time_point 的类成员
类成员描述
duration表示时间段的子类。
max()获取可能的最大时间点。
min()获取可能的最小时间点。
period时间单位类。

VII.   chrono \texttt{VII.\ chrono} VII. chrono 库在实际中的应用

依据上面的所有知识点,我们便可以使用 chrono 库写出一个简易的倒计时程序。

#include<bits/stdc++.h>
using namespace std;
using namespace std::chrono;
int main(){
	printf("请输入需要等待的秒数:\n");
	double dur;
	scanf("%lf",&dur);
	steady_clock::time_point start=steady_clock::now();
	while((duration_cast<milliseconds>(steady_clock::now()-start).count())/1000.0<=dur);
	printf("时间到!!!\n按任意键退出. . . \n");
	getchar();
	return 0;
}

总结

至此,我们已经学会了 chrono 库的基本操作。我们还需要在实际应用中慢慢提高我们使用 chrono 库的能力,这样才能让我们熟练地运用 chrono 库和理解它的本质。

参考资料

  1. CSDN [C++]C++ std::chrono库使用作者:赵闪闪168.

  2. CSDN C++11计时器: chrono库介绍作者:森明帮大于黑虎帮

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值