C++11中的chrono库详解

 更新时间:2023年03月18日 09:44:31   作者:你好,冯同学  
C++11提供了日期时间相关的库chrono,通过chrono库可以很方便的处理日期和时间,这篇文章主要介绍了C++11中的chrono库,需要的朋友可以参考下

前言

C++11提供了日期时间相关的库chrono,通过chrono库可以很方便的处理日期和时间。chrono库主要包含3种类型:时间间隔duration、时钟clocks和时间点time_point

1、记录时长的duration

duration为一个模板类,表示时间间隔,可以是几秒、几分钟或者几个小时的时间间隔。duration的原型如下:

template <class Rep, 
class Period = ratio<1> >
class duration;

第一模板参数Rep是一个数值类型,表示时钟数的类型;第二个模板参数是一个默认模板参数std::ratio,表示时钟周期,它的原型如下:

template <intmax_t N, 
intmax_t D = 1
> class ratio;

它表示每个时钟周期的秒数,其中第一个模板参数N代表分子,D代表分母,分母默认为1,因此,ratio代表的是一个分子除以分母的分数值。比如:

ratio<2>	//代表2秒
ratio<60>	//代表1分钟
ratio<60*60>	//代表1小时
ratio<60*60*24>	//代表1天
ratio<1, 1000>	//代表1毫秒
ratio<1, 1000000>	//代表1微秒
ratio<1, 1000000000>	//代表1纳秒

为了方便使用,标准库定义了一些常用的时间间隔,如时、分、秒、毫秒、微秒和纳秒,在chrono命名空间下,定义如下(vs2013的源码):

typedef duration<long long, nano> nanoseconds;
typedef duration<long long, micro> microseconds;
typedef duration<long long, milli> milliseconds;
typedef duration<long long> seconds;
typedef duration<int, ratio<60> > minutes;
typedef duration<int, ratio<3600> > hours;

通过定义这些常用的时间间隔类型,我们能方便的使用它们,比如线程休眠:

//休眠100毫秒
this_thread::sleep_for(std::chrono::duration<int, ratio<1, 100>>(100));
this_thread::sleep_for(std::chrono::microseconds(100));//更简单

//休眠3秒
this_thread::sleep_for(std::chrono::duration<int>(3));
this_thread::sleep_for(std::chrono::seconds(3));//更简单

chrono还提供了获取时间间隔的时钟周期数的方法count(),它的基本用法如下:

#include<iostream>
#include<chrono>
int main()
{
	std::chrono::seconds s(3);//3秒
	std::chrono::milliseconds ms = 2 * s;//6000毫秒
	std::cout << "3 s duration has " << s.count() << " ticks\n" << "6000 ms duration has " << ms.count() << " ticks\n";
}

执行结果:

在这里插入图片描述

duration在某些情况下可以进行转换,例如,当duration的Rep都为整型,且源Period要大于目标Period时或者目标duration的Rep为浮点数时可以使用传统类型转化或者隐式调用其单值构造函数,不必调用duration_cast

int main()
{
	//目标duration的Rep为double
	std::chrono::milliseconds int_milliseconds(1024);       // 1024ms
	std::chrono::microseconds int_microseconds(1024);       // 1024us
	std::chrono::duration<double> double_seconds;
	double_seconds = int_microseconds;	//1024ms = 1.024s
	double_seconds = int_milliseconds;	//1024us = 0.001024s


	//当duration的Rep都为整型,且源Period可被目标Period整除时
	int_microseconds = int_milliseconds; //ms赋值给us可以,但是us赋值给ms不可
	int_milliseconds = std::chrono::seconds(1);	//s赋值给ms可以,但是ms赋值给s不可以


	//源duration的Rep为double, 目标duration的Rep不为double,不能转换
	//std::chrono::milliseconds t1 = std::chrono::duration<double>(1024);

/*
 * 数据会发生截断时的转化
 * chrono库提供了duration之间相互转化的函数,其定义如下
 *      template <class ToDuration, class Rep, class Period>
 *      constexpr ToDuration duration_cast(const duration<Rep,Period>& d);
*/
    std::chrono::seconds t1 = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::milliseconds(1024));               // 1s = 1024ms(精度损失)
    std::chrono::seconds t2 = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::duration<double>(1.024));          // 1s = 1.024s 
}

时间间隔之间可以做运算,计算两端时间间隔的差值的实例如下:

int main()
{
	std::chrono::minutes t1(10);
	std::chrono::seconds t2(50);
	std::chrono::seconds t3 = t1 - t2;
	cout << t3.count() << " second" << endl;
}

执行结果:

在这里插入图片描述

其中,t1代表10分钟,t2代表50秒,t3则是t1减t2,也就是600-50=550秒。通过调用t3的count()输出差值550个时钟周期,因为t3的时钟周期为1秒,所以t3表示时间间隔为550秒。

值得注意的是,duration的加减运算有一定的规则,当两个duration时钟周期不相同的时候,会先统一成一种时钟,然后再作加减运算。统一成一种时钟的规则如下:

对于ratio<x1, y1>count1和ratio<x2, y2>count2。如果x1、x2的最大公约数为x,y1、y2的最小公倍数为y,那么统一之后的ratio为ratio<x, y>

例如:

int main()
{
	std::chrono::duration<double, std::ratio<9, 7>> d1(3);
	std::chrono::duration<double, std::ratio<6, 5>> d2(1);
	auto d3 = d1 - d2;
	cout << "d3类型 : "<<typeid(d3).name() << endl;
	cout << d3.count() << endl;
}

执行结果:

在这里插入图片描述

根据前面介绍的规则,对于9/7和6/5,分子取最大公约数3,分母取最小公倍数35,所以,统一之后的duration为std::chrono::duration<double,struct std::ratio<3,35>>。然后再将原来的duration转换为统一的duration,最后计算的时钟周期数为:((9/7)/(3/35)*3)-((6/5)/(3/35)*1),结果为31

2、表示时间点的time_point

time_point表示一个时间点,用来获取从它的clock的开始所经过的duration(比如,可能是1970.1.1以来的时间间隔)和当前时间,可以做一些时间的比较和算术运算,可以喝ctime库结合起来显示时间。time_point必须用clock来计时。time_point有一个函数time_from_eproch()用来获得1970年1月1日到time_point时间经过的duration

time_point是一个类模板,原型如下:

template <class Clock, 
class Duration = typename Clock::duration>
class time_point;

template <class Clock, 
class Duration = typename Clock::duration>
class time_point;

第一个模板参数Clock用来指定所要使用的时钟(标准库中有三种时钟,system_clock,steady_clock和high_resolution_clock)
第二个模板函数参数用来表示时间的计量单位(特化的std::chrono::duration<> )

计算当前时间距离1970年1月1日有多少天

#include<iostream>
#include<chrono>
#include<ratio>
using namespace std::chrono;
int main()
{
	using days_type = duration<int, std::ratio<60 * 60 * 24>>;
	time_point<system_clock, days_type> today = time_point_cast<days_type>(system_clock::now());
	std::cout << today.time_since_epoch().count() << " days since epoch" << endl;
}

执行结果:

在这里插入图片描述

time_point还支持一些算术运算,比如两个time_point的差值时钟周期数,还可以和duration相加减。要注意不同clock的time_point是不能进行算术运算的。下面例子将展示前一天和后一天的日期:

#include<iostream>
#include<chrono>
#include<iomanip>
using namespace std::chrono;
int main()
{
	system_clock::time_point now = system_clock::now();
	std::time_t prev = system_clock::to_time_t(now - hours(24)); //返回时间戳
	std::time_t next = system_clock::to_time_t(now + hours(24)); //返回时间戳

	cout << "One day ago, the time was " << std::put_time(std::localtime(&prev), "%Y.%m.%d %H:%M:%S") << endl;
	cout << "A day later, the time is " << std::put_time(std::localtime(&next), "%Y.%m.%d %H:%M:%S") << endl;	 
}

执行结果:

在这里插入图片描述

3、获取系统时钟的clocks

clocks表示当前的系统时钟,内部有time_point、duration、Rep、Period等信息,主要用来获取当前时间,以及实现time_t和time_point的相互转换。clocks包含如下3种时钟:
-system_clock:代表真实时间的挂钟时间,具体时间依赖于系统。system_clock保证提供的时间值是一个可读时间
-steady_clock:不能被“调整” 的时钟,并不一定代表真实世界的挂钟时间。保证先后调用now()得到的时间值是不会递减的
-high_resoulution_clock:高精度时钟,实际上是system_clock或者steady_clock的别名。可以通过now()来获取当前时间点,代码如下:

int main()
{
	std::chrono::system_clock::time_point t1 = std::chrono::system_clock::now();
	cout << "hello fl" << endl;
	std::chrono::system_clock::time_point t2 = std::chrono::system_clock::now();
	cout << (t2 - t1).count() << " tick count" << endl;
	return 0;
}

执行结果:

在这里插入图片描述

system_clock的to_time_t方法可以将一个time_point转换为ctime:

std::time_t now_c = std::chrono::system_clock::to_time_t(time_point);

而from_time_t方法则正好相反,它将ctime转换为time_point

steady_clock可以获取稳定可靠的时间间隔,后一次调用now()的值和前一次的差值不会因为修改了系统时间而改变,从而保证了稳定的时间间隔。steady_clock的用法和system用法一样。

到此这篇关于C++11中的chrono库详解的文章就介绍到这了,更多相关C++11中的chrono库内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 项目之C++如何实现数据库连接池

    项目之C++如何实现数据库连接池

    这篇文章主要介绍了项目之C++如何实现数据库连接池问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • C++示例分析内联函数与引用变量及函数重载的使用

    C++示例分析内联函数与引用变量及函数重载的使用

    为了消除函数调用的时空开销,C++ 提供一种提高效率的方法,即在编译时将函数调用处用函数体替换,类似于C语言中的宏展开。这种在函数调用处直接嵌入函数体的函数称为内联函数(Inline Function),又称内嵌函数或者内置函数
    2022-08-08
  • C语言实现餐厅管理系统

    C语言实现餐厅管理系统

    这篇文章主要为大家详细介绍了C语言实现餐厅管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • C语言实现简单扫雷小游戏

    C语言实现简单扫雷小游戏

    这篇文章主要为大家详细介绍了C语言实现简单扫雷小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-10-10
  • VS2019创建C++工程的的实现步骤

    VS2019创建C++工程的的实现步骤

    本文主要介绍了VS2019创建C++工程步骤,包含新建项目、编辑文件、配置源文件目录、编译链接、输出文件、设置断点调试,具有一定的参考价值,感兴趣的可以了解一下
    2024-12-12
  • C语言字符串函数介绍与模拟实现详解

    C语言字符串函数介绍与模拟实现详解

    字符串函数(String processing function)也叫字符串处理函数,指的是编程语言中用来进行字符串处理的函数,如C,pascal,Visual以及LotusScript中进行字符串拷贝,计算长度,字符查找等的函数
    2022-02-02
  • C语言实现单链表的示例详解

    C语言实现单链表的示例详解

    给需要考研的同学一个参考,单链表作为常见数据结构的一种,这里记录C语言实现单链表,文章通过代码示例介绍的非常详细,具有一顶的参考价值,需要的朋友可以参考下
    2023-09-09
  • 使用Matlab绘制七夕咕呱小青蛙

    使用Matlab绘制七夕咕呱小青蛙

    七夕节到了还不快给你的朋友安排上这只咕呱小青蛙?本文将用Matlab绘制一个可爱的咕呱小青蛙,感兴趣的小伙伴可以动手尝试一下
    2022-08-08
  • VS Code C++环境的搭建过程

    VS Code C++环境的搭建过程

    这篇文章主要介绍了VS Code C++环境的搭建,Somasegar 也告诉笔者这款编辑器也拥有对 Git 的开箱即用的支持,需要的朋友可以参考下
    2022-04-04
  • C++中新手容易犯的十种编程错误汇总

    C++中新手容易犯的十种编程错误汇总

    一段C语言代码,在编译、链接和运行的各个阶段都可能会出现问题,下面这篇文章主要给大家介绍了关于C++中新手容易犯的十种编程错误的相关资料,需要的朋友可以参考下
    2021-10-10

最新评论