以前的时间日期库只能支持到秒、毫秒。并不能支持微妙纳秒,c++11带来了chrono,来提供高精度的时间日期库。头文件 < chrono >

chrono这个库主要目的是为不同的系统提供高精度的时间和时钟。为了不用每隔10年为一种时间类型重新解读,这次chrono干脆整出了两个新的概念:
duration:时间段 eg:2分钟、120秒
timepoint:时间点,时间点是由两部分组成:时间段 + 起始时间。eg:2016年新年夜(解释方式:1970/01/01 + xxx秒。 这是unix和posix系统的计时方式)

命名空间:std::chrono

一个duration对象包含两个部分:一个表示ticks的值,一个秒的单位。

std::ratio可以用来表示小数点后面的部分
ratio的英文翻译:比率、系数
用x/y秒来描述时间的单位。eg:60s表示分钟单位;1/1000s表示毫秒单位等

std::chrono::duration<int> d1(20);
std::chrono::duration<double, std::ratio<60>> d2(0.5);
std::chrono::duration<long, std::ratio<1, 1000>> d3(1);

分析一下上面的3行,duration是一个类模版,有两个模版参数,第一个表示数值ticks,第二个表示单位(可选,默认是秒)。
先分析一下第二个参数:std::ratio< 60 > 也有两个参数,第二个参数是可选的,默认为1,第一个参数表示分子,第二个表示分母。结合duration来讲,就可以任意指定秒的单位:60s(一分钟)为单位,0.001s(1毫秒),100s(百秒,这个是自定义的)。正常生活中是年月日 时分秒 毫秒 微妙 纳秒 皮秒(c++11可以支持到纳秒)。

再看看上面的例子:第一个是20秒,第二个是半分钟,第三个是1毫秒。
实际场景中绝大多数都是时分秒 一直到纳秒。c++11已经考虑到这些单位的常用性,为我们定义了6个常用的单位:
std::chrono::hours
std::chrono::minutes
std::chrono::seconds
std::chrono::milliseconds
std::chrono::microseconds
std::chrono::nanoseconds
对应上面3个定义,可以用下面的代替

std::chrono::seconds d1(20);
std::chrono::minutes d2(0.5);
std::chrono::milliseconds(1);

下面说一下duration的算术操作:
两个durtion的加减乘除
durtion和ticks的之间的加减
比较

这些算术操作需要注意他们的单位。

std::chrono::seconds d1(1); // 1秒
std::chrono::milliseconds d2(1); // 1毫秒

d1 - d2:
结果是999 单位是 毫秒
如果不用标准库提供的单位:

std::chrono::durtion<int, std::ratio<1, 5>> d1(2); // 2/5秒
std::chrono::durtion<int, std::ratio<1, 3>> d2(1); // 1/3秒

d1 + d2:
结果是11 单位是1/15秒。15就是3和5的最大公约数

大部分算术操作和比较操作都适用于duration:eg:数值1和duration就没法进行比较操作。

不同的秒单位都可以进行隐式转换

duration的默认构造函数,只指定默认单位为秒,但是ticks值是未定的,
拷贝构造函数可能发生单位的隐式转换

对于打印duration 标准库并没有提供<<操作
我们可以重载操作符<<来做到:

template <typename V, typename R>
std::ostream& operator << (std::ostream& s, const std::chrono::duration<V, R>& d)
{s << d.count() << " of " << R::num << "/" << R::den;return s;
}// 调用
std::chrono::milliseconds d2(3);
std::cout << d2 << std::endl;

需要注意的是:上面这种写法,如果adl不工作,那么上面的函数也不会工作
关于adl,以后再说。

这上面说的单位转换都是隐式的,但是有一个问题:向高精度转换是没问题的,向低精度转换有可能会丢失数据。这时可以用显示转换来避免这种情况:

std::chrono::seconds d1(55); // 55秒
std::chrono::minutes d2(d1); // error
std::chrono::minutes d3 = std::chrono::duration_cast<std::chrono::minutes>(d1); // ok

使用durtion_cast来进行显示的单位转换。
下面是一种特殊的情况,来补充上面”向高精度转换是没问题的”这点。
半分钟(0.5) 转换成30秒,秒单位是从低精度转向了高精度(分钟转秒),但是ticks的值从double转成了int,从高精度转成了低精度,这时也会发生数据丢失,隐式转换会发生错误,需要使用显示转换duration_cast。

显示转换另一个用的比较多的地方:取一个duration的时分秒,是截断一部分信息,常用在打印部分。

std::chrono::milliseconds ms(12345679);
std::chrono::hours hour = duration_cast<std::chrono::hours>(ms % std::chrono::hours(1));

利用%(取模操作)可以轻易进行取时取分取秒。

duration还有3个静态成员函数:
zeor() : 产生一个0秒的duration对象
max() min() :产生一个duration对象,里面的ticks尽可能是最大最小值。

下面说一下由duration + 起始点epoch =的时间点timepoint:
起始点epoch可以由clock产生,每个clock产生的起始点都有可能不一样,不过一般都是用1970.0.1.01这个起始点。

clock定义了一个epoch(起点)和一个period(时间段)。
clock可以计算从1970.01.01到现在的毫秒数,也可以通过now接口产生一个当前时间对象。
timepoint就是clock +/- 一个duration。

下面先讲一下clock:
c++标准库定了了3中clock:

system_clock:系统时钟,提供了to_time_t()、from_time_t()接口来将timepoint和c系统时间time_t做转换。
steady_clock:不变时钟,并不是使用物理时间的增长来描述的,而是以一个固定的比率来增长。
high_resolution_clock:高精度时钟。

为什么一个叫系统时钟一个加不变时钟?
系统时钟就是电脑右下角的时钟,我们可以任意设置,eg:现在是早上10点,我们可以把系统时钟设置为下午3点,也可以设置9点。不变时钟就是针对系统时钟这种变化性设计出的另一种不可更改的时钟,意思是我们无法去调整时钟的值,只能看着她以一个不变的比率,一直增加。

c++新标准并没有为这三种时钟提供必须要的精度、起始时间、范围。
如果需要一个自定义的起始时间、或是时钟并不覆盖的一个时间点,这时,需要用到转换函数。

namespace
{template <typename C>
void print_clock()
{std::cout << " - precision: ";typedef typename C::period P;if ( std::ratio_less_equal<P, std::milli>::value ){typedef typename std::ratio_multiply<P, std::kilo> T;std::cout << std::fixed << double(T::num) / T::den << " milliseconds" << std::endl;}elsestd::cout << std::fixed << double(P::num) / P::den << " seconds" << std::endl;std::cout << " - is_steady: " << std::boolalpha << C::is_steady << std::endl << std::endl;
}}void test_cpp2()
{std::cout << "----------------- test clock----------------" << std::endl;std::cout << " system_clock/high_resolution_clock/steady_clock " << std::endl;print_clock<std::chrono::system_clock>();print_clock<std::chrono::high_resolution_clock>();print_clock<std::chrono::steady_clock>();}

运行结果是:

----------------- test clock----------------
 system_clock/high_resolution_clock/steady_clock- precision: 0.000100 milliseconds
 - is_steady: false
- precision: 0.000001 milliseconds
 - is_steady: true
- precision: 0.000001 milliseconds
 - is_steady: true

上面的代码说明
system_clock 、high_resolution_clock的精度都是100ns,steady_clock的精度是1ms。
high_resolution_clock、steady_clock的时钟都不可调整
测试环境:win10 x64 + vs2015,不同的系统检测出的可能有所不同(eg:高精度和系统时钟又可能是一样的)。

steady_clock主要用在处理两个时钟的比较和计算,如果是用system_clock来完成这件事,其中,如果时钟被改变了,那么基于system_clock的计算就会出现错误,同样的,如果计算程序执行时间,如果使用system_clock,那么得出来的结果,也算不了数,甚至执行时间为负。所以说,使用steady_clock来计算两个时钟的比较和计算是比较合适的。

上面已经说过了duration和clock,那么基于duration和clock的timepoint在下面开始分析:

namespace std { namespace chrono {template <typename Clock,typename Durtion = typename Clock:Durtion>
class time_point;               }}

说到时间点,有4个比较特殊的:
epoch:可由任意时钟的time_point默认构造产生
current time:由任意时钟的静态成员函数now()产生
minimum timepoint:有任意时钟的time_point静态成员函数min()产生
maximum timepoint:有任意时钟的time_point静态成员函数max()产生

下面两种写法是一样的意思:

std::chrono::system_clock::time_point t;
std::chrono::time_point<std::chrono::system_clock> t;

time_point 对象只有一个成员 duration,这个值可以被成员函数time_since_epoch()获取到,同时,time_point对象之间的比较或是和duration之间的算术操作,类time_point都有提供。

只有当time_point 和 durtion组合起来,才能表达出更丰富的时间点,但这其中还需要考虑很多问题:秒单位转换时的截取和四舍五入;闰年和闰秒等等。

总结:chrono描述的更多的是chrono和duration而不是日期时间库。

以上是c++新标准库对时钟和时间的描述,c标准和posix的接口,在c++程序中也是可用的,下面介绍一下time.h(在c++可写成ctime)。 命名空间是std

CLOCKS_PER_SEC : 表示1s内有多少个ticks,1个嘀嗒(ticks)占的时间是1/CLOCKS_PER_SEC。

ctime() 将一个time_t转换成一个日期字符串, mktime()将struct tm转换成time_t
而c++标准则提供了frome_time_t(),to_time_t() 来将time_point和time_t进行转换

接下来看看duration和timepoint在定时器和阻塞方面的知识:
阻塞线程:由this_thread提供的sleep_for和sleep_until
等待互斥量:try_lock_fro和try_lock_unitl
等待条件变量:wait_for和wait_until
所有以_for结尾的接口都是利用duration来实现阻塞;所有以_until都是利用timepoint来实现阻塞。

这里有一个需要注意的地方:以_for结尾的接口用的是duration时间段来处理的,和时钟无关;而以_until结尾的接口用的是time_point来处理,这里如果将时钟修改了,那么会影响到执行的逻辑。eg:现在是下午3点,sleep_unitl(下午4点),如果此时将时间改为下午4点,那么定时器会立马结束。

但计算机的事情并没有绝对,例如上面说的_for不会收到时钟调整的影响,但是如果硬件平台不提供steady_clock,那么软件就没办法在保证计时不会被影响,所以,在这种情况下,_for接口也会被时钟调整所影响。

c++标准库之时间戳、时间段相关推荐

  1. c++ 标准库格式化时间戳(既将时间戳转字符串,字符串转时间戳)

    //时间戳转字符串 std::string Time_t2String(__time64_t stamp) { tm* stamp_tm = localtime(&stamp);std::os ...

  2. go标准库:time

    原文链接 http://ironxu.com/747 介绍Go 标准库 time 常用导出函数,结构体及其方法. import "time" time包提供显示和计算时间用的函数. ...

  3. 聊聊C++标准库,准标准库中关于时间的概念和用法

    概要 在实际C++业务开发中,经常需要使用系统API或者标准库去获取时间,计算时间的需求,其中,时间按概念又分时间段,时间点:按表达形式又分系统时间,本地时间:其实,获取到了时间,如何通过日志的方式把 ...

  4. go 常用标准库之-time

    文章目录 go 常用标准库之-time 基本使用 时间戳 时间间隔 时间操作 Add Sub Equal Before After 时间格式化 字符串格式化成时间 时区 定时任务 go 常用标准库之- ...

  5. Go语言常用标准库——log、net_http、strconv、time包

    文章目录 log 使用Logger 配置logger 标准logger的配置 flag选项 配置日志前缀 配置日志输出位置 创建logger 总结 net_http net/http介绍 HTTP协议 ...

  6. Python-time标准库知识小结

    定义 time库是python中处理时间的标准库 时间获取 time()-------获取当前时间戳,浮点数形式 ctime()-------以可读的方式返回字符串时间 gmtime()------- ...

  7. python常用标准库有哪些-Python - 常用标准库

    sys 和Python解释器关系密切的标准库 sys.__doc__中已经说明了:这个模块提供了对一些对象的访问使用或维护的解释器和交互的功能强的解释 sys.argv 变量,专门用来向Python解 ...

  8. python标准库的基本使用

    标准库是自带的: 标准库的功能:第三方库: 安装一下python: 下面来学习标准库中的三个,time.random.turtle,时间库.随机数库.图形绘制库: 先打印 print(time.loc ...

  9. 标准库time,datetime,calendar,random的使用

    标准库time(python中文处理时间的标准库) time库的载入 import time time库包括三类函数 1.时间获取:time() ,ctime() ,gmtime() 2.时间格式化: ...

最新文章

  1. 移动端网站优化也不容小觑!
  2. 对图像进行二维离散Fourier变换
  3. IE8提示JS错误(KB927917)终极解决方法
  4. python与正则表达式(part8)--compile对象及match对象的属性方法
  5. 评价的等级优良差_满意程度等级划分
  6. mysql 相同字段相减_mysql datetime 类型字段相减
  7. 对一篇单细胞RNA综述的评述:细胞和基因质控参数的选择
  8. ubuntu 16.04 搭建无线共享热点(PC 无线直连Android移动终端 调试,监控屏幕)
  9. hibernate批量上传
  10. Python猜数字游戏(包含异常处理,可自定义随机数产生范围、最大猜测次数,如果用户猜错的话可根据输入情况缩小猜测范围)
  11. 降维打击 Dimensionality reduction attack
  12. [转帖]从壹开始前后端分离【重要】║最全的部署方案 最丰富的错误分析
  13. Unity3d模型导入都需要注意哪些事项?
  14. linux中数据库的管理
  15. 三维模型(X,Y,Z)坐标,UV坐标
  16. 20个非常有用的单行Python代码
  17. [附源码]PHP计算机毕业设计-报刊征订管理系统(程序+LW)
  18. 前端可以做的SEO搜索引擎优化(摘取)
  19. 筛法求素数(C语言/C++)
  20. revit模型怎么在手机上看_模型的查看和定位-Revit基础教程

热门文章

  1. Oracle模糊查询的几种方法【推荐最后一种】
  2. su oracle 和 su - oracle的区别
  3. 小手拍拍机器人_手指操游戏
  4. 优动漫PAINT中手绘稿扫描件的杂点清理方法
  5. Mybatis中大于,小于,不等于等特殊符号的写法
  6. pdf转换成jpg格式最简单的方法分享
  7. 前端学习笔记之CSS3新特性3D转换 3.23
  8. 为什么我们要培养自己的编码规范?
  9. 双非一本网易测试实习入职感受,难以想象的“平和”
  10. 如何利用命令查看当前linux系统的桌面环境是KED 或者是GNOME