使用chrono获取时间
chrono
自C++11以后加入了标准库,提供了精度和时间计算的接口。其中包含三种时钟system_clock
、steady_clock
和high_resolution_clock
,顾名思义,system_clock
是系统时钟,始终和系统的时间保持一致,因此在使用的过程中如果系统时间被修改了,那么使用了这个时钟的程序就会被影响。steady_clock
可以解决运行过程中系统时间被修改而被影响的问题,是一种稳定的单调时钟,所以更适合于度量时间间隔的场景。high_resolution_clock
定义上是一种高精度的时钟,其精度取决于系统环境可以达到的最小精度(不过我在windows平台上使用13.1版本的Mingw-w64测试了一下,cpu是13600kf,能显示的时间精度和系统时间是一样的,都是纳秒级别,也没体现出高精度的特点,可能是纳秒级精度已经比较高了的原因),使用到的场景似乎不多,前面两个已经够用了。
查看各个时钟的精度
1 2 3 4 5 6
| cout << "system_clock precision: "; cout << chrono::system_clock::period::num << "/" << chrono::system_clock::period::den << endl; cout << "steady_clock precision: "; cout << chrono::steady_clock::period::num << "/" << chrono::steady_clock::period::den << endl; cout << "chrono::high_resolution_clock precision: "; cout << chrono::high_resolution_clock::period::num << "/" << chrono::high_resolution_clock::period::den << endl;
|
输出结果
1 2 3
| system_clock precision: 1/1000000000 steady_clock precision: 1/1000000000 chrono::high_resolution_clock precision: 1/1000000000
|
公有静态成员函数 now
三种时钟都有公有的静态成员函数now()
,返回当前的时间点,记录了从某一时刻到当前时间的时钟周期数。
1 2 3 4 5 6
| chrono::time_point<chrono::steady_clock, chrono::nanoseconds> curTime = chrono::steady_clock::now(); cout << "time_since_epoch (steady_clock): \t\t" << curTime.time_since_epoch().count() << endl; chrono::time_point high_curTime = chrono::high_resolution_clock::now(); cout << "time_since_epoch (high_resolution_clock): \t" << high_curTime.time_since_epoch().count() << endl; chrono::time_point sys_curTime = chrono::system_clock::now(); cout << "time_since_epoch (system_clock): \t\t" << sys_curTime.time_since_epoch().count() << endl;
|
输出结果:
1 2 3
| time_since_epoch (steady_clock): 117212202374400 time_since_epoch (high_resolution_clock): 1710767518931123200 time_since_epoch (system_clock): 1710767518931709300
|
系统时间返回的是世界协调时(Unix时间),从1970年1月1日00:00:00开始的时间,不计闰秒(从C++20起是规定,之前的标准没有明确指定,不过大多也是这么实现的)。高精度时钟也取了系统时间,不过这不是一定的,因为没有明确的标准指定高精度时钟必须这么做。而稳定时钟计算了从某刻开始到当前的时钟周期。
和C时间的转换
系统时钟可以和C标准库中的时间结构进行转换,例如
1 2 3
| time_t time_c = chrono::system_clock::to_time_t(sys_curTime); cout << "system_clock::to_time_t: \t\t\t" << time_c << endl; cout << "ctime: \t\t\t\t\t\t" << ctime(&time_c) << endl;
|
输出结果:
1 2
| system_clock::to_time_t: 1710767518 ctime: Mon Mar 18 21:11:58 2024
|
顺便看一下C库中获取时间的结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| time_t now_c = time(NULL); cout << "now: " << now_c << endl; char *date = ctime(&now_c); cout << "ctime(&now): " << date << endl;
tm *utcTime = gmtime(&now_c); cout << "struct {\n" << " tm_year: " << utcTime->tm_year << " (since 1900)" << endl; cout << " tm_month: " << utcTime->tm_mon << " (since 0)" << endl; cout << " tm_yday: " << utcTime->tm_yday << endl; cout << " tm_mday: " << utcTime->tm_mday << endl; cout << " tm_wday: " << utcTime->tm_wday << endl; cout << " tm_hour: " << utcTime->tm_hour << endl; cout << " tm_minute: " << utcTime->tm_min << endl; cout << " tm_second: " << utcTime->tm_sec << endl; cout << "}tm;\n";
date = asctime(utcTime); cout << date << endl;
|
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| now: 1710767518 ctime(&now): Mon Mar 18 21:11:58 2024
struct { tm_year: 124 (since 1900) tm_month: 2 (since 0) tm_yday: 77 tm_mday: 18 tm_wday: 1 tm_hour: 13 tm_minute: 11 tm_second: 58 }tm; Mon Mar 18 13:39:03 2024
|
需要引入ctime
库,使用time(NULL)
返还了从1900年至今的秒数,C中的时间结构精度只能到秒,所以需要更高精度的话,还是要去使用chrono
库。
不过ctime
库中的tm
结构可以表示年月日时分秒,倒是挺方便。
时间运算
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 28 29 30
| chrono::hours hour(1); chrono::minutes minute(1); auto diff = hour - minute; cout << "1 hour - 1 minute = " << diff.count() << endl;
chrono::steady_clock::time_point steadyTimePoint; cout << "curTimePoint - defaultTimePoint = " << chrono::duration_cast<chrono::nanoseconds>(curTime - steadyTimePoint).count() << endl;
auto nextTimePoint = curTime + chrono::minutes{1}; cout << "当前时间点加一分钟: " << chrono::duration_cast<chrono::seconds>(nextTimePoint - steadyTimePoint).count() << endl;
chrono::minutes fourMinutes(4); chrono::seconds twoSeconds(2); cout << "4minutes + 2second = " << (fourMinutes + twoSeconds).count() << endl; cout << "4minutes - 2second = " << (fourMinutes - twoSeconds).count() << endl;
cout << "4minutes * 2 = " << (fourMinutes * 2).count() << endl; cout << "4minutes / 2second = " << (fourMinutes / twoSeconds) << endl; chrono::seconds sevenSeconds(7); cout << "4minutes % 7second = "s << (fourMinutes % sevenSeconds).count() << endl;
cout << "-----------------------------------------------------------------------------\n";
chrono::duration<int, ratio<1, 16>> sevenOfSixteen(7); chrono::duration<int, ratio<1, 8>> OneOfEight(1); cout << "7/16 - 3/8 = " << (sevenOfSixteen - OneOfEight).count() << endl; cout << "两个自定义的时间段不是倍数关系的情况下:" << endl; chrono::duration<double, ratio<1, 11>> nineOfEleven(9.0); chrono::duration<double, ratio<1, 7>> fiveOfSeven(5.0); cout << "5.0/7 - 9.0/11 = " << (fiveOfSeven - nineOfEleven).count() << endl;
|
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12
| 1 hour - 1 minute = 59 curTimePoint - defaultTimePoint = 118836333058000 当前时间点加一分钟: 118896 4minutes + 2second = 242 4minutes - 2second = 238 4minutes * 2 = 8 4minutes / 2second = 120 4minutes % 7second = 2 ----------------------------------------------------------------------------- 7/16 - 3/8 = 5 两个自定义的时间段不是倍数关系的情况下: 5.0/7 - 9.0/11 = -8
|
chrono
中时间的计算是通过ratio<>
来实现的,可以看到,1小时减去1分钟后,精度会取较小的单位,结果等于59。
chrono
内有时间点和时间段的概念,两个时间点相减可以得到两者相差的时间段,一个时间点可以加上一个时间段获取某个新的时间点,而两个时间点之间是不能相加的,这也符合日常生活中的印象。
我们还可以使用ratio<>
模板自定义一个精度,并且能够进行分数的计算,正如输出中显示的那样。