C++11 时间工具chrono

本文根据众多互联网博客内容整理后形成,引用内容的版权归原始作者所有,仅限于学习研究使用,不得用于任何商业用途。

这篇算是简单介绍一下,C++11 的标准函式库里面,用来处理时间和日期的函式库「chrono」。这个函数库是在 C++11 才引进的,以微软的 Visual C++ 来说,要到 2012 版才开始提供;而如果使用的开发环境没有支援的话,也可以使用 Boost C++ Libraries 所提供的版本。

Chrono 这个函数库,主要是为 C++ STL 加入一个可以取得、处理时间与日期的函数库;透过这个函数库,我们可以在程序里面取得时间、并针对时间做处理、计算。而像是 STL Thread 的 sleep_for() 或 sleep_until(),也都是透过 chrono 提供的型别来做设定。

要使用这个函式库,要 include 他的 header 档,也就是加上
#include <chrono>
之后用的东西,基本上都是在 std:chrono 这个 namespace 下。

使用 chrono 时,最主要应该是下面这两种用来记录时间的类别:

  • 纪录时间点的 time_point
  • 纪录时间长度的 duration

duration

duration 是 chrono 裡面,用来记录时间长度的类别,他基本上是一个 template class,可以自行定义他的意义;chrono 也有提供一些比较常见的时间类别,可以直接拿来使用,下面就是内建的 duration 的型别:

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;

其中可以看到,第一个 template 参数是要用来储存资料的类型,第二个则是他相对于「秒」的比例。这边也使用了 ratio 这个 C++11 的另一个新的函式库的类别,他是用来记录「有理数」(可以写成分数的数)的新类别,有兴趣可以参考 cppreference 的介绍。

基本上,一般会用到时间单位这边都有定义好了,如果不合用的话,也可以自己去定义;而由于 chrono 也有把相关的计算都定义了,所以也可以直接拿来做计算,就算是时间单位不同,也不会有问题。

下面就是一个简单的例子:

std::chrono::minutes t1( 10 );
std::chrono::seconds t2( 60 );
std::chrono::seconds t3 = t1 - t2;
std::cout << t3.count() << " second" << std::endl;

其中,t1 是代表 10 分钟、 t2 是代表 60 秒,t3 则是 t1 减去 t2,也就是 600 – 60 = 540 秒。

而如果要取得一个 duration 的值的话,则是要呼叫他的 count() 这个函式;像在上面的例子裡面,就会把 t3 的值输出,所以最后会出现「540 second」。

而如果想要做强制的时间单位转换,也可以使用 duration_cast<>() 这个函式来做;下面就是一个把以秒为单位的 t3 转换成分钟后再输出。

cout << chrono::duration_cast<chrono::minutes>( t3 ).count() << endl;

time_point

相较于 duration 是用来记录时间的长度的,time_point 是用来记录一个特定时间点的资料类别。他一样是一个 template class,需要指定要使用的 clock 与时间单位(duration)。

Chrono 一般来说有提供两种 clock 可以使用,分别是:system_clock 和 steady_clock。
其中 system_clock 是直接去抓系统的时间,有可能在使用中会被被修改(参考);
而 steady_clock 则是确实地去纪录时间的流逝,所以不会出现时间倒退的状况(参考)。

一般要使用的话,大概会是下面的样子:

std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
std::cout << "Hello World\n";
std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
std::cout << "Printing took "
  << std::chrono::duration_cast<std::chrono::microseconds>(t2 - t1).count()
  << "us.\n";

通过 clock 类别所提供的 now() 这个函数,可以快速地取得现在的时间;而两者相减的话,则会产生一个型别为 duration 的结果;在上面的例子裡面,就是一开始先取得当下的时间 t1,然后输出一个字串后、再去取得一个时间 t2,之后两者相减,就可以取得中间过程所花费的时间了。在这边则是在相减后,把结果转换成以 micro second 为单位后,再做输出。

而 time_point 也可以和 duration 做计算,得出新的 time_point;例如下面的程式码,就是计算 10 个小时候的时间:

std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::chrono::system_clock::time_point nt = now + std::chrono::hours(10);

另外,chrono 也有定义 high_resolution_clock,提供更高的精确度(参考);但是实际上在 MSVC11 上,他就等同于 system_clock。

而如果要把不同定义的 time_point 做转换,则也可以使用 time_point_cast<>() 这个函式来处理,不过这边就不多加说明了。

time_point 的输出
STL 的 chrono 并没有定义 time_point 的输出方式,所以我们并不能直接透过 output stream 来输出 time_point 的资料,所以如果要把他输出成字串的话,其实还有点麻烦…

如果想要输出的话,一个方法是透过 clock 提供的 to_time_t() 这个函式,把 time_point 先把他转换成 C-style 的 time_t,然后再透过 ctime() 这类的函式做输出;下面是一个简单的范例:

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::cout << std::ctime( &now_c ) << std::endl;

而如果是使用 Boost 的版本的话,Boost 则是另外有提供 chrono_io.hpp 这个档桉,在裡面替 duration 和 time_point 定义了输出的格式,可以直接使用,相当地方便~有兴趣的话,可以参考 Boost 的官方说明

参考资料:

C++11 STL 的時間函式庫:chrono
http://en.cppreference.com/w/cpp/header/chrono
http://msdn.microsoft.com/en-us/library/hh874757.aspx
http://www.boost.org/doc/libs/1_55_0/doc/html/chrono.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容