c++11的时间库chrono简化了时间、日期、时间间隔的计算的编程开发;主要体现于:
1、基于system_clock、steady_clock、high_resolution_clock的时钟(clock)的确凿时间点(time_point)的获取;
2、基于不同时间单位、不同时间点之差的时间间隔(duration)的计算;
c++11的时间库chrono均位于名字空间std::chrono下。
一、clock:
包括system_clock、steady_clock、high_resolution_clock;
1、system_clock:来源于系统时钟,全部进程使用now()方法获取到的时间都是一样的;
2、steady_clock:保证即便进程运行时修改了系统实际,再次调用now()方法,依然能获取到按之前系统时间为基准的当前时间;
3、high_resolution_clock:是system_clock和steady_clock的typedef;
二、time_point:
基于clock,可获取时间点time_point,所谓时间点是指某一个确定的时刻,如2018.4.17 17:13:15;
time_point分为两种形式出现:
1、名字空间std::chrono下的time_point:
std::chrono::time_point是一个模板类,需要指定所使用的时钟类(system_clock/steady_clock/high_resolution_clock)和精度(默认为hour级,可自行由std::ratio指定);
代码:
//std::chrono::time_point is a template class, not used usually.
std::chrono::time_point>> now_daylevel = std::chrono::time_point_cast>>(std::chrono::high_resolution_clock::now());
std::chrono::time_point>> now_hourlevel = std::chrono::time_point_cast>>(std::chrono::high_resolution_clock::now());
std::chrono::time_point>> now_minutelevel = std::chrono::time_point_cast>>(std::chrono::high_resolution_clock::now());
std::chrono::time_point>> now_secondlevel = std::chrono::time_point_cast>>(std::chrono::high_resolution_clock::now());
std::chrono::time_point now_deflevel = std::chrono::time_point_cast>>(std::chrono::high_resolution_clock::now());
上面分别获取了小时级、分钟级、秒级、默认的4种方式获取的当前时间,然后转为unixtime时间戳:
std::time_t ut_day = std::chrono::high_resolution_clock::to_time_t(now_daylevel), ut_hour = std::chrono::high_resolution_clock::to_time_t(now_hourlevel), ut_minute = std::chrono::high_resolution_clock::to_time_t(now_minutelevel), ut_second = std::chrono::high_resolution_clock::to_time_t(now_secondlevel), ut_def = std::chrono::high_resolution_clock::to_time_t(now_deflevel);
然后用ctime转化为日期时间格式:
std::cout << ut_day << std::endl;
std::cout << ctime(&ut_day) << std::endl;
std::cout << ut_hour << std::endl;
std::cout << ctime(&ut_hour) << std::endl;
std::cout << ut_minute << std::endl;
std::cout << ctime(&ut_minute) << std::endl;
std::cout << ut_second << std::endl;
std::cout << ctime(&ut_second) << std::endl;
std::cout << ut_def << std::endl;
std::cout << ctime(&ut_def) << std::endl;
观察结果:
1523923200
Tue Apr 17 08:00:00 2018------------------day
1523955600
Tue Apr 17 17:00:00 2018------------------hour
1523957460
Tue Apr 17 17:31:00 2018------------------minute
1523957497
Tue Apr 17 17:31:37 2018------------------second
1523923200
Tue Apr 17 08:00:00 2018------------------default
需要掌握的点:
1、定义一个时间点的方法
1.1、模板类std::chrono::time_point:
需要模板实例化:时钟类型(必选,system_clock/steady_clock/high_resolution_clock),精度级别(可选)
如:std::chrono::time_point
这个方式比较麻烦
1.2、std::chrono::时钟类型::time_point
包括:
std::chrono::system_clock::time_point
std::chrono::steady_clock::time_point
std::chrono::high_resolution_clock::time_point
如:std::chrono::high_resolution_clock::time_point now = std::chrono::high_resolution_clock::now();
这个方式比较简单
2、time_point到unixtime时间戳的转换:
方式:std::chrono::时钟类型::to_time_t(time_point)方法
如:
std::chrono::high_resolution_clock::time_point now = std::chrono::high_resolution_clock::now();
std::time_t ut_now = std::chrono::high_resolution_clock::to_time_t(now);
可以再通过stl的ctime,实现unixtime时间戳,到日期时间格式的转换:
std::cout << "now: " << ctime(&ut_now);
3、time_since_epoch方法
计算从1970年1月1日到现在,经历了多少天、小时、分钟、秒
4、通过duration实现增量时间的计算
通过一个时间time_point_1,加减duration,得到另一个时间time_point_2
见下面duration的介绍
三、duration
核心点:
1、duration表示一个时间段,如"100毫秒"、"一秒"、"2分钟"、"5小时"、"10天"......
2、duration以秒为基准,通过std::ratio衍生出各自自定义的时间单位,包括不限于:天、小时、分钟、秒、毫秒、微秒、纳秒,stl默认提供了:小时、分钟、秒、毫秒、微秒、纳秒;
3、duration自身可以做加减运算,如:时间段d3 = 时间段d1 - 时间段d2
4、duration可以提供duration_cast,由一种时间单位,转换为另一种时间单位,如1小时和60分钟可以互相转换
5、时刻time_point通过加减duration,可以得到另一个时刻;
1和2、duration介绍
std::ratio代表一个比例,或者说比率,它是一个模板类,定义是:
PS: intmax_t是long long
简言之,_Nx =60且_Dx = 1,那么比率为60,这可以用于代表分钟:
std::chrono::duration
std::chrono::duration
i. std::chrono::duratio表示时间间隔,基准是1秒;
ii. 模板实例化的第一个参数int,代表时间间隔的长度是用整型数表示;
iii. 模板实例化的第二个参数std::ratio<60>,代表时间间隔对秒的比率是60:1,注意ratio的_Dx默认实例化为1,即std::ratio<60>相当于std::ratio<60, 1>;60:1的比率相当于,std::chrono::duration
iv. 根据这个数据结构,构造了对象one_minute,构造参数为1,代表对象one_minute代表了一分钟的时间间隔;又构造了对象three_minute且构造参数为3,代表对象three_minute代表了3分钟的时间间隔;
如果清楚了分钟的构造原理,那么构造任意时间长度的时间间隔都可行了;
代码:
std::chrono::duration> three_second(1);
std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); std::this_thread::sleep_for(three_second); std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now();
std::time_t ut1 = std::chrono::high_resolution_clock::to_time_t(t1), ut2 = std::chrono::high_resolution_clock::to_time_t(t2);
std::cout << "t1: " << ctime(&ut1);
std::cout << "t2: " << ctime(&ut2);
上面的代码意思是,构造一个3秒的时间间隔three_minute,然后记录此时此刻的时间时刻(time_point)t1,然后令当前线程睡眠3秒,线程恢复运行后再次记录此时此刻的时间时刻(time_point)t2,然后输出t1和t2,观察t1和t2是否相差的是3秒;
前面提到了,time_point可以通过加减duration,得到不同的时刻:
std::chrono::high_resolution_clock::time_point now = std::chrono::high_resolution_clock::now();
std::chrono::duration> one_minute(1);
std::chrono::duration> one_day(1);
std::chrono::high_resolution_clock::time_point next_minute = now + one_minute;
std::chrono::high_resolution_clock::time_point last_minute = now - one_minute;
std::chrono::high_resolution_clock::time_point next_day = now + one_day;
std::chrono::high_resolution_clock::time_point last_day = now - one_day;
std::time_t ut_now = std::chrono::high_resolution_clock::to_time_t(now);
std::time_t ut_next_minute = std::chrono::high_resolution_clock::to_time_t(next_minute);
std::time_t ut_last_minute = std::chrono::high_resolution_clock::to_time_t(last_minute);
std::time_t ut_next_day = std::chrono::high_resolution_clock::to_time_t(next_day);
std::time_t ut_last_day = std::chrono::high_resolution_clock::to_time_t(last_day);
std::cout << "now: " << ctime(&ut_now);
std::cout << "next minute: " << ctime(&ut_last_minute);
std::cout << "last minute: " << ctime(&ut_next_minute);
std::cout << "next day: " << ctime(&ut_last_day);
std::cout << "last day: " << ctime(&ut_next_day);
上面的代码,首先获取了当前时刻(time_point)now,然后分别构造了时间间隔对象one_minute和one_day,分别代表一分钟和一天,然后通过当前时间分别加减one_minute和one_day,得到了上一分钟、下一分钟、昨天此时此刻、明天此时此刻的时刻(time_point);
stl已经构造了小时、分钟、秒、毫秒、微秒、纳秒的数据结构,不需要自己通过std::ratio自行构造:
typedef duration > hours;
typedef duration > minutes;
typedef duration > seconds;
typedef duration > milliseconds;
typedef duration > microseconds;
typedef duration > nanoseconds;
如下面例子,分别代表令当前线程睡眠一秒钟、1000毫秒、1微秒:
std::this_thread::sleep_for(std::chrono::seconds(1));
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::this_thread::sleep_for(std::chrono::microseconds(1));
时间间隔duration不仅可以被时刻time_point用于加减运算,duration之间也可以做加减运算,如:
std::chrono::seconds tm_span1(10);
std::chrono::minutes tm_span2(1);
std::chrono::seconds tm_span3 = tm_span2 - tm_span1;
std::cout << tm_span3.count() << std::endl;
首先按秒为单位定义了10秒tm_span1,然后以分钟为单位定义了1分钟tm_span2,两者的差值是50秒,tm_span2 - tm_span1 = 50秒赋值给以秒为单位定义的tm_span3;
注意:tm_span2 - tm_span1直接赋值给以分钟为单位定义的tm_span4,则会产生编译错误,如果要赋值需要通过duration_cast做结构转换:
std::chrono::seconds tm_span1(10);
std::chrono::minutes tm_span2(1);
std::chrono::minutes tm_span4 = std::chrono::duration_cast(tm_span2 - tm_span1);
std::cout << tm_span4.count() << std::endl;
duration的count方法,是该duration代表的时间间隔长度,除以其标称单位的结果。如上面例子的tm_span3代表的是50秒的长度,它的时间单位是1秒,所以count方法获取的结果是50。