C++时间库(四) 总结

文章目录

  1. 1. C风格的时间函数
  2. 2. Chrono库
  3. 3. Boost.Date_Time
  4. 4. 总结
  5. 5. 参考

前面三节总结了C++开发中使用的库和函数,但是它们的特点和之间的联系是什么呢,什么情况应该选择什么样的时间库呢,现在总结一下。

C风格的时间函数

C库的时间函数已经被使用了几十年,它包含了时间点和时间段两个概念。

  • time_t表示时间点
  • double difftime(time_t t1, time_t t2);计算时间段
  • time_t time(time_t*);返回当前时间

此外C库还包含将时间点与公历(使用struct tm表示)进行转换的函数。

时间点一个重要特征是应该能进行比较。要想比较两个时间需要一个共同的时间参考点(epoch)和相同的时间单位,而时间参考点(epoch)的信息,可以不用关心。

C委员会没有指定time_t的时间参考点(epoch)和时间单位。好处是平台可以容易的修改epoch的定义。如果一个程序需要导入或者导出另一个程序的时间点,首先要转换时间点到约定的epoch上,比如公历。

POSIX指定time_t时间单位为秒,过去几十年,time_t约定俗成地表示为从1970年开始的秒数,并用32位整数存储。但是这有几个问题:

  • time_t时间单位是秒,difftime计算的时间段也是秒,所以它不能处理小于1秒的情况。
  • 32位的time_t最大只能表示到2038年1月18日19时14分07秒,否则会溢出。

虽然可以使用64位的time_t来解决第二个问题,但第一个问题仍不能解决。
后来POSIX提出了struct timeb, struct timevalstruct timespec将精度提高到毫秒、微秒和纳秒。但是每一个精度都需要一个新接口和新的结构体。纳秒是尽头吗?不一定,这也意味着将来需要定义新的接口和结构体来满足要求。

Chrono库

C风格的时间函数缺乏灵活性和扩展性,为了解决这个问题,Chrono库对此进行了抽象,抽象出时间段(duration)、时间点(time_point)和时钟(clock)。

  • 时间段(duration)可以有不同的时间精度,不同精度的时间段使用同样的接口。
  • 时间点(time_point)表示参考时间点(epoch)加上或者减去一个时间段。它的时间参考点由时钟(clock)决定。
  • 时钟(clock)提供参数时间点(epoch)和时间精度。能返回当前时间点。

这种抽象,能解决上面提到的C风格的时间函数的问题,能很方便的在不同时间精度间进行转换,也可以实现新epoch的clock,在同一个clock中,time_point可以进行比较,如果知道两个clock的epoch的转换规则,两个clock中的time_point可以相互转换和比较。

system_clock可以映射时间点到C风格的时间上(time_t),即可以与time_t进行相互转换。

此外这个库没有格式化函数,需要转换成time_t或者tm,使用C风格时间函数进行格式化。

顺带说一下,这里的Chrono库是指std::chrono或者Boost.Chrono库。

Boost.Date_Time

虽然Chrono库能很好的解决时间处理问题,但是它没有比hour更高的计时单位,所以处理日期的能力不是很强,而Boost.Date_Time库关注日期和时间。它有很多用于为本地化显示而格式化日期的函数,而且有很多函数用于获取和操作日期和时间。

Chrono库与Date_Time库还有一个区别就是,对于Chrono,某一刻的时间更多的是用距离某一个参考时间点的偏移(例如从1970年1月1日开始)来表示,而Date_Time库具有公历日期,可以绝对表示某一个时间点,不需要相对某个参考时间点来表示。
这两个库可以互补,当然也有重复的地方。但是这两个库没有任何交互操作,所以不得不进行手工转换。

总结

  • 如果是新开发的程序需要处理时间,尽量使用std::chrono,如果需要对日期进行处理或者需要对时间进行合并、拆分和比较的需求时,最好选择Boost.Date_Time库,除了格式化外,尽量少使用C风格的时间函数。
  • time_t可以作为这几个库进行转换的中转类型。因为这些库都提供了对它的转换函数。

C++中的时间库就是这么扯淡,且不说时区转换的问题,光是这几个库中的类型来回倒腾转换,就能把程序猿绕晕了。真心希望这个系列的总结能将这些知识梳理清晰,使用时不再犯糊涂。

参考

  1. N2661 - A Foundation to Sleep On
  2. Boost.Chrono vs. Boost.Date_Time

版权声明

本博客 采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可

本文永久链接:http://yoursite.com/2016/01/07/C++时间库(四)/