时间工具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
之后用的东西,基本上都是在 std:chrono 这个 namespace 下。

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

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

duration

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

typedef duration nanoseconds;
typedef duration microseconds;
typedef duration milliseconds;
typedef duration seconds;
typedef duration > minutes;
typedef duration > 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( 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(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

你可能感兴趣的:(时间工具chrono)