C++的chrono、ratio和ctime等头文件
推荐网站:http://www.cplusplus.com/
参考:
- http://www.cplusplus.com/
- http://www.cplusplus.com/reference/chrono/
- http://www.cplusplus.com/reference/ctime/
1. ratio头文件
ratio是用来表示比例关系的模板类
原型
(intmax_t一般为长整形,即long long)
template<intmax_t N,intmax_t D>struct ratio;
N(numerator)表示的是分子:它的范围需要控制在intmax_t的范围内
D(denominator)指的是分母:它的范围需要控制在intmax_t的范围内
ratio是compile-time constant,也就是一个编译期常量(和sizeof运算符一样),可以作为常量使用。
要注意的是:ratio类不是通过他的对象来表示的,而是这个类型本身来表示的。
#include <iostream>
#include <ratio>
int main() {
typedef std::ratio<60, 1> demo;//此时的demo就是一个ratio,不需要创建对象即可使用
std::cin.get();
return 0;
}
ratio的成员常量:
成员常量 | 描述 |
---|---|
num | (numerator)表示的是分子 |
den | (denominator)指的是分母 |
要注意的是:这里的num和den已经经过化简。所以这里的数可能和定义时传入的不同,例如:
#include <iostream>
#include <ratio>
int main() {
typedef std::ratio<100, 10> demo;
std::cout << demo::num << " : " << demo::den << std::endl;
std::cin.get();
return 0;
}
成员类型(typedef):
成员类型 | 定义 | 描述 |
---|---|---|
type | ratio | 同定义时的类型相同(但是化简了) |
#include <iostream>
#include <ratio>
#include <typeinfo>
int main() {
typedef std::ratio<100, 10> demo;
std::cout << typeid(demo::type).name() << std::endl;
std::cin.get();
return 0;
}
模板的实例:
type | definition | description |
---|---|---|
yocto | ratio<1,1000000000000000000000000> | 10-24 * |
zepto | ratio<1,1000000000000000000000> | 10-21 * |
atto | ratio<1,1000000000000000000> | 10-18 |
femto | ratio<1,1000000000000000> | 10-15 |
pico | ratio<1,1000000000000> | 10-12 |
nano | ratio<1,1000000000> | 10-9 |
micro | ratio<1,1000000> | 10-6 |
milli | ratio<1,1000> | 10-3 |
centi | ratio<1,100> | 10-2 |
deci | ratio<1,10> | 10-1 |
deca | ratio<10,1> | 101 |
hecto | ratio<100,1> | 102 |
kilo | ratio<1000,1> | 103 |
mega | ratio<1000000,1> | 106 |
giga | ratio<1000000000,1> | 109 |
tera | ratio<1000000000000,1> | 1012 |
peta | ratio<1000000000000000,1> | 1015 |
exa | ratio<1000000000000000000,1> | 1018 |
zetta | ratio<1000000000000000000000,1> | 1021 * |
yotta | ratio<1000000000000000000000000,1> | 1024 * |
注意: vc的头文件中没有yocto等(上表中带*号)的实例(受到intmax_t极值的限制)
#include <iostream>
#include <ratio>
#include <typeinfo>
int main() {
std::cout << "atto : " << std::atto::num << " : " << std::atto::den << std::endl;
std::cin.get();
return 0;
}
当然还有一些ratio的辅助性的结构体:
ratio_add
ratio_subtract
ratio_multiply
ratio_equal
#include <iostream>
#include <ratio>
#include <typeinfo>
int main() {
typedef std::ratio<2, 4>half;
typedef std::ratio<1, 3>one_third;
typedef std::ratio_add<half, one_third> sum;
std::cout << "sum = " << sum::num << " : " << sum::den << std::endl;
std::cin.get();
return 0;
}
结果是: sum = 5 : 6
2. chrono头文件
chrono是一个关于时间的库
chrono是一个头文件的名称,同时也是一个std下的子命名空间的名称。 不像其他的头文件把元素置于std命名空间下,chrono把除了common_type之外的元素都置于std::chrono的命名空间下。
在std::chrono命名空间下的元素用3个概念来解决时间问题:
序号 | 概念 | 内容 |
---|---|---|
1 | duration | 【1】duration解决的是时间的跨度问题(time spans):就像一分钟、一小时、一天等概念。【2】duration模板 使用两个子元素解决时间跨度问题:时间的度量单位(period)+单位时间的多少(count)。(比如:40分钟由 分钟作为单位,有40个这样的事件单位。即 period=1分钟 , count=40) |
2 | time_point | 【1】一个具体的时间点,如某人的生日,火车的发车时间等。【2】time_point模板使用一个duration与某个具体的时间戳epoch(Epoch指的是一个特定的时间:1970-01-01 00:00:00 UTC)的关系来表示某个时间点。 |
3 | Clocks | 【1】Clocks值得是一个把time_point与现实世界的时间相联系的framework。【2】该头文件提供了至少3个这种framework:system_clock, steady_clock and high_resolution_clock。 |
chrono中包含的类
类别 | 成员1 | 成员2 | 成员3 |
---|---|---|---|
duration&time_point | duration | time_point | |
clocks | system_clock | steady_clock | high_resolution_clock |
traits | treat_as_floating_point | duration_values | common_type (duration) |
functions | duration_cast | time_point_cast |
duration 和 time_point
1. duration
duration原型:
template<typename Rep,typename Period=std::ratio<1>>class duration
std::ratio< 1 > 和 std::ratio<1,1> 是一样的。
duration通过period和count来表示时间间隔(time span)。例如:60秒可以表示为:时间单位为 period=1 秒 , 总共有 count=60 个 period。
- 在duration的内部,保存有一个Rep类型的count成员变量(Rep就是duration模板的第一个模板参数),count可以通过调用成员函数count()获取。
- 上述的count是以period为单位的。period是通过duration模板的第二个模板参数来设置的,period是一个ratio类型。
duration类成员:
A. constructor(构造函数):
原型:
(1) duration() = default;
(2) duration (const duration& dtn);
(3) template<class Rep2, class Period2>
constexpr duration (const duration<Rep2,Period2>& dtn);
(4) template<class Rep2>
constexpr explicit duration (const Rep2& n);
(1)默认构造函数
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
int main() {
std::chrono::duration<int, std::ratio<1>>demo;//默认构造函数
std::cout << demo.count() << std::endl;
std::cin.get();
return 0;
}
运行结果:-858993460
可见,成员变量count此时是一个垃圾值。没有意义,甚至可能造成bug。
(2)(3)使用一个duration对象来初始化
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
int main() {
std::chrono::duration<int, std::ratio<1>>demo(100);
std::chrono::duration<int, std::ratio<1>>demo1(demo);//用demo来初始化demo1
std::cout << demo1.count() << std::endl;
std::cin.get();
return 0;
}
运行结果:100
(4)使用一个Rep2类型数据来初始化
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
int main() {
std::chrono::duration<int, std::ratio<1>>demo(100);//用int类型的数据来初始化
std::cout << demo.count() << std::endl;
std::cin.get();
return 0;
}
运行结果:100
用(3)(4)这两种构造函数构造duration时要注意数据溢出问题。
可以使用duration_cast来进行强制转换。(有可能发生数据溢出、精度丢失等问题)
B. destructor(析构函数)
略
C. count()
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
int main() {
std::chrono::duration<int, std::ratio<1>>demo(100);//用int类型的数据来初始化
std::cout << demo.count() << std::endl;
std::cin.get();
return 0;
}
运行结果:100
D. zero()【静态函数成员】
E. min()【静态函数成员】
F. max()【静态函数成员】
获取特殊的duration对象:0值,最大值,最小值
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
int main() {
typedef std::chrono::duration<int> type;
std::cout << type::zero().count() << std::endl;
std::cout << type::min().count() << std::endl;
std::cout << type::max().count() << std::endl;
std::cin.get();
return 0;
}
运行结果:
0
-2147483648
2147483647
G. 运算符重载(略)
duration中的类型(即typedef)
Member types | 定义 |
---|---|
rep | 模板参数列表中的第一个(representation) |
period | 模板参数列表中的第二个(ratio类型) |
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
int main() {
std::chrono::duration<int> demo(100);
std::cout << "rep : " << typeid(decltype(demo)::rep).name() << std::endl;//获取rep的类型
std::cout << "period(ratio type) : " << typeid(decltype(demo)::period).name() << std::endl;//获取period的类型
std::cout << "period(ratio) : " << decltype(demo)::period::num << " : " << decltype(demo)::period::den << std::endl;//获取period(ratio)的具体内容(即ratio的分子、分母)
std::cin.get();
return 0;
}
运行结果:
rep : int
period(ratio type) : struct std::ratio<1,1>
period(ratio) : 1 : 1
duration的实例
以hours为例:
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
int main() {
std::chrono::hours demo(2);//2 hours
std::cout << typeid(demo).name() << std::endl;//获取demo的类型,查看是否为duration类型
std::cout << "count : " << demo.count() << std::endl;//打印demo的count值
std::cout << "rep type : " << typeid(decltype(demo)::rep).name() << std::endl;//获取demo的rep类型
std::cout << "period(ratio) : " << decltype(demo)::period::num << " : " << decltype(demo)::period::den << std::endl;//获取period
std::cin.get();
return 0;
}
运行结果:
class std::chrono::duration < int,struct std::ratio< 3600,1 > >
count : 2
rep type : int
period(ratio) : 3600 : 1
2. time_point
time_point原型:
template <class Clock, class Duration = typename Clock::duration>
class time_point;
Clock:一个clock类。 如:system_clock、steady_clock 、high_resolution_clock。
Duration:一个duration类型的参数
【1】time_point表示一个具体的时间点,如某人的生日,火车的发车时间等。
【2】time_point模板使用一个duration与某个具体的时间戳epoch(Epoch指的是一个特定的时间:1970-01-01 00:00:00 UTC)的关系来表示某个时间点。
【3】默认的duration也就是Clock::duration的period默认为ratio< 1,10000000 > ,也就是微秒。
time_point类成员
- 构造函数
原型:
(1) time_point();
(2) template <class Duration2>
time_point (const time_point<clock,Duration2>& tp);
(3) explicit time_point (const duration& dtn);
(1)默认构造函数:默认时间为 Thu Jan 1 08:00:00 1970
#define _CRT_SECURE_NO_WARNINGS //关闭VC的安全检查
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
#include <ctime>
int main() {
std::chrono::time_point<std::chrono::system_clock> tp;//默认构造函数
//将tp这个时间点打印出来(涉及到ctime头文件的使用,后文将会讲述)
std::time_t time(std::chrono::system_clock::to_time_t(tp));//将time_point类型转换为time_t
std::cout << ctime(&time) << std::endl;//以c风格字符串输出时间
std::cin.get();
return 0;
}
运行结果:Thu Jan 1 08:00:00 1970
(2)拷贝构造函数
#define _CRT_SECURE_NO_WARNINGS//关闭VC的安全检查
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
#include <ctime>
int main() {
std::chrono::time_point<std::chrono::system_clock> tp;//默认构造函数
decltype(tp) tpx(tp);//用拷贝构造函数构造一个和tp一样的类型,使用decltype
//将tpx这个时间点打印出来(涉及到ctime头文件的使用,后文将会讲述)
std::time_t time(std::chrono::system_clock::to_time_t(tpx));//将time_point类型转换为time_t
std::cout << ctime(&time) << std::endl;//以c风格字符串输出时间
std::cin.get();
return 0;
}
运行结果:Thu Jan 1 08:00:00 1970
(3)构造一个距离epoch(Thu Jan 1 08:00:00 1970) 某段时长 的时间点
#define _CRT_SECURE_NO_WARNINGS//关闭VC的安全检查
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
#include <ctime>
int main() {
typedef std::chrono::duration<long long, std::ratio<60 * 60 * 24>>days_type;//一天的时长(time span)
std::chrono::time_point<std::chrono::system_clock> tp(days_type(3));//epoch时间点前进 3天的时间点
//将tp这个时间点打印出来(涉及到ctime头文件的使用,后文将会讲述)
std::time_t time(std::chrono::system_clock::to_time_t(tp));//将time_point类型转换为time_t
std::cout << ctime(&time) << std::endl;//以c风格字符串输出时间
std::cin.get();
return 0;
}
运行结果:Sun Jan 4 08:00:00 1970
上面的运行结果刚好距离Thu Jan 1 08:00:00 1970 三天的时间
析构函数(略)
time_since_epoch()
原型:
duration time_since_epoch() const;
- 返回一个time span,也就是duration类型的对象,这个对象包含的是当前时间点距离epoch的time span。
- 返回的duration使用的period和count和调用者相同。
#define _CRT_SECURE_NO_WARNINGS//关闭VC的安全检查
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
#include <ctime>
int main() {
using namespace std::chrono;//使命名空间std::chrono下的元素在当前作用域内可见
//time_point<system_clock,duration<long long,std::ratio<1,10000000>>> today(system_clock::now());//获取系统当前的时间
//上面语句简写成下面语句 【system_clock下定义有time_point类型,其构成就是上面那一句】
system_clock::time_point today(system_clock::now());//获取系统当前的时间
//打印系统当前的时间
std::time_t time(std::chrono::system_clock::to_time_t(today));
std::cout << ctime(&time) << std::endl;
//system_clock下定义有duration可以直接使用,定义等同于下面这语句
//duration<long long,std::ratio<1,10000000>>time_span;
system_clock::duration time_span(today.time_since_epoch());//获取与epoch的时间间隔
std::cout << "time since epoch " << time_span.count() << " microseconds." << std::endl;//打印时间间隔,单位微秒
std::cout << "time since epoch "
<< static_cast<double>(time_span.count())*decltype(time_span)::period::num / decltype(time_span)::period::den
<< " senconds." << std::endl;//打印时间间隔,单位转换为秒
std::cin.get();
return 0;
}
运行结果:
Sun Nov 29 18:56:37 2015
time since epoch 14487945974531967 microseconds.
time since epoch 1.44879e+09 senconds.
!!上面代码初学者看着有些混乱,但是将chrono和ctime学习完后就可以自如的运用了。
- min()
- max()
上面这两个静态函数成员就是 返回time_point的最大值和最小值,返回类型是time_point类型
- 运算符重载
time_point运算符重载比较有意思的地方是,运算符左边和右边类型的不同会导致返回值类型的不同。如图:
( tp 表示time_point类型 、 dtn 表示duration类型 )
- time_point的typedef的内置类型
用代码打印分析这些类型:(这里我们分析system_clock为我们提供time_point类型)
注意:这里就不写命名空间的全名了,但是要记得chrono大部分元素都在std::chrono命名空间下(除了common_type)。
#define _CRT_SECURE_NO_WARNINGS//关闭VC的安全检查
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
#include <ctime>
int main() {
using namespace std::chrono;//是chrono命名空间下的元素可见
system_clock::time_point tp;//使用system_clock提供的time_clock类型
std::cout << "time_point type = " << typeid(tp).name() << std::endl;//打印time_point类型
std::cout << "clock type = " << typeid(decltype(tp)::clock).name() << std::endl; //此处的decltype(tp) 相当于 system_clock::time_point
std::cout << "duration type = " << typeid(decltype(tp)::duration).name() << std::endl;
std::cout << " duration-rep-type = " << typeid(decltype(tp)::duration::rep).name() << std::endl;
std::cout << " duration-period = " << decltype(tp)::duration::period::num << " : " << decltype(tp)::duration::period::den << std::endl;
//下面的rep就是duraion的rep
std::cout << "rep = " << typeid(decltype(tp)::rep).name() << std::endl;
//下面的period就是duration的period
std::cout << "duration = " << decltype(tp)::period::num << " : " << decltype(tp)::period::den << std::endl;
std::cin.get();
return 0;
}
运行结果:
Clocks
clocks至少有3种:
system_clock
steady_clock
high_resolution_clock
1. system_clock
1.1 system_clock原型:
class system_clock;
system_clock提供了与当前时间点的访问渠道。
【1】真实时间:它提供的是一个真实的时间,可以通过该类提供的方法进行各种类型的转换
【2】可以表示epoch之前和之后的时间,因为duration的count可以是正数也可以是负数(只要不用unsigned)
【3】系统范畴:所有本系统运行的程序获取的时间和此处system_clock提供的时间是相同的。
1.2 system_clock的成员
1.2.1 now()
static time_point now() noexcept;
- 功能:获取系统当前的时间
实例代码:
#define _CRT_SECURE_NO_WARNINGS//关闭VC的安全检查
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
#include <ctime>
int main() {
using namespace std::chrono;
time_point<system_clock, duration<long long, std::ratio<1, 10000000>>>today(system_clock::now());//获取系统当前时间
//打印时间
std::time_t time(system_clock::to_time_t(today));
std::cout << ctime(&time) << std::endl;
std::cin.get();
return 0;
}
运行结果:Sun Nov 29 19:37:16 2015
1.2.2 to_time_t()
static time_t to_time_t (const time_point& tp) noexcept;
- 功能:将time_point类型转换成time_t类型
如上面一段代码所示:
std::time_t time(system_clock::to_time_t(today));
这一句的目的就是将time_point类型转换成time_t类型,然后用ctime转换成字符串打印出来。
1.2.3 from_time_t()
static time_point from_time_t (time_t t) noexcept;
- 功能:将time_t类型转换为time_point类型
实例:
#define _CRT_SECURE_NO_WARNINGS//关闭VC的安全检查
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
#include <ctime>
void printTP(const std::chrono::system_clock::time_point & tp) {
std::time_t tms(std::chrono::system_clock::to_time_t(tp));
std::cout << ctime(&tms) << std::endl;
}
int main() {
using namespace std::chrono;//使chrono下的元素可见
//std::time_t tms(std::time(NULL));//定义一个tms类型,并通过ctime中的time函数获取系统当前时间,等价于下面的代码
std::time_t tms;
//tms = std::time(NULL);//等价于下面的语句
std::time(&tms);
time_point < system_clock, duration<long long, std::ratio<1, 10000000>>>tp;
tp = system_clock::from_time_t(tms);
printTP(tp);//打印time_point表示的具体时间
std::cin.get();
return 0;
}
运行结果:Sun Nov 29 19:50:25 2015
运行结果正确,说明 from_time_t 的功能没有问题
1.2.4 常量 is_steady
a bool value specifying whether the clock always advances, and whether it does at a steady state relative to physical time. If true, this implies that the system clock may not be adjusted.
system_clock 的 is_steady 为 false
1.2.5 system_clock中的typedef
用代码说话:
#define _CRT_SECURE_NO_WARNINGS//关闭VC的安全检查
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
#include <ctime>
int main() {
using namespace std::chrono;
std::cout << "rep : " << typeid(system_clock::rep).name() << std::endl;
std::cout << "period : " << system_clock::period::num << " : " << system_clock::period::den << std::endl;
std::cout << "duration : " << typeid(system_clock::duration).name() << std::endl;
std::cout << "time_point : " << typeid(system_clock::time_point).name() << std::endl;
std::cin.get();
return 0;
}
运行结果:
所以:我们可以用system_clock::time_point直接定义一个tp可以用system_clock::duration直接定义一个duration
2. steady_clock
2.1 steady_clock的原型
class steady_clock;
- steady_clock类似于system_clock,同样提供一种与当前时间建立联系的渠道。
- 特别的是,steady_clock是为了计算时间间隔而设计的。(在演示该类的now方法中将会演示获取某个函数调用耗费的时间)
【1】稳定性1:成员now返回的时间总是晚于前一次调用时返回的时间
【2】稳定性2:时钟每次走一步(Every tick)的时间都相同
2.2 steady_clock的成员
2.2.1 now()
原型:
static time_point now() noexcept;
- 功能:返回当前时间点。(返回的时间总是晚于前一次调用时返回的时间)
实例:函数调用耗费的时间
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
#include <ctime>
long long func(long long max) {
long long sum(0);
for (long long i = 1; i <= max; i++)
sum += i;
return sum;
}
int main() {
using namespace std::chrono;
steady_clock::time_point beginning, end;
beginning = steady_clock::now();
std::cout << func(100000) << std::endl;
end = steady_clock::now();
steady_clock::duration tm_span(end - beginning);
std::cout << "It took " << tm_span.count() << " ticks." << std::endl;//时钟走的步数
std::cout << "It took "
<< static_cast<double>(tm_span.count())*steady_clock::period::num / steady_clock::period::den
<< " seconds." << std::endl;
std::cin.get();//转换为秒数
return 0;
}
运行结果:
5000050000
It took 2971362 ticks.
It took 0.00297136 seconds.
2.2.2 is_steady
is_steady的值为true
2.2.3 Member types(typedef)
类似于system_clock,这里一笔带过
3. high_resolution_clock
类似于steady_clock和system_clock的有机结合。
他的特点在于:高精度
请参考:http://www.cplusplus.com/reference/chrono/high_resolution_clock/
Traits
1. treat_as_floating_point
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
#include <ctime>
int main() {
//判断int是否为浮点类型
std::cout << std::boolalpha << std::chrono::treat_as_floating_point<int>::value << std::endl;
//判断float是否为浮点类型
std::cout << std::boolalpha << std::chrono::treat_as_floating_point<float>::value << std::endl;
//判断double是否为浮点类型
std::cout << std::boolalpha << std::chrono::treat_as_floating_point<double>::value << std::endl;
std::cin.get();
return 0;
}
运行结果:
false
true
true
这个一笔带过,不常用。
有兴趣可以参考:
http://www.cplusplus.com/reference/chrono/treat_as_floating_point/
2. duration_values
2.1 原型
template <class Rep> class duration_values;
2.2 成员函数
2.2.1 zero()
2.2.2 min()
2.2.3 max()
以上三个函数其实是duration类中zero、min、max三个函数调用的组件。也就是说,duration中的zero、min、max是通过上述三个函数获取rep参数的 0 值 ,最大值和最小值的。
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
#include <ctime>
int main() {
std::cout << std::chrono::duration_values<int>::zero() << std::endl;
std::cout << std::chrono::duration_values<int>::min() << std::endl;
std::cout << std::chrono::duration_values<int>::max() << std::endl;
std::cin.get();
return 0;
}
运行结果:
0
-2147483648
2147483647
3. common_type
emplate <class Rep1, class Period1, class Rep2, class Period2>
class common_type<chrono::duration<Rep1,Period1>,chrono::duration<Rep2,Period2>>;
参考:
http://www.cplusplus.com/reference/type_traits/common_type
common_type主要用于time_point运算符重载时用来选择适当的返回类型时使用。
此处的common_type会返回两种类型(duration类型)中精度较高的类型。
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
#include <ctime>
int main() {
using namespace std::chrono;
//实验当period相同时,common_type返回何种的类型rep
typedef duration<int, std::ratio<10, 1>>type1;
typedef duration<double, std::ratio<10, 1>>type2;
std::cout << typeid(std::common_type<type1, type2>::type).name() << std::endl;
std::cout << "\n";
//实验当rep相同时,common_type返回何种的类型period
typedef duration<int, std::ratio<10, 1>>type3;
typedef duration<int, std::ratio<1, 10>>type4;
std::cout << typeid(std::common_type<type3, type4>::type).name() << std::endl;
std::cin.get();
return 0;
}
运行结果:
class std::chrono::duration < double,struct std::ratio < 10,1 > >
class std::chrono::duration < int,struct std::ratio < 1,10 > >
如上面结果显示:
【1】当period相同时,common_type返回精度较高的rep
【2】当rep相同时,common_type返回比值较小的period(也就是单位较小的,换句话就是精度最高的)
4. Functions
4.1 duration_cast
4.1.1 duration_cast的原型
template <class ToDuration, class Rep, class Period>
constexpr ToDuration duration_cast (const duration<Rep,Period>& dtn);
- 将某种类型的duration转换为另外一种类型的duration,同时不忽略period(时间单位,如:时、分、秒等)的不同
- 该函数默认地使用精度较高的类型(参见上面的 common_type讲解),转换内部是由static_cast完成的。
- 使用该方法可能发生数据溢出或精度的丢失。(稍后演示)
实战1:(duration_cast引发进度丢失或是数据溢出是什么意思?)
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
#include <ctime>
int main() {
using namespace std::chrono;
typedef duration<int, std::ratio<60, 1>>minute_type;
typedef duration<int, std::ratio<60 * 60, 1>>hour_type;
minute_type mins(130);//130分钟
hour_type hours(duration_cast<hour_type>(mins));//130分钟转换成小时
std::cout << mins.count()<<" minutes turned out to be "
<< hours.count()
<<" hours after duration_cast."
<< std::endl;
std::cin.get();
return 0;
}
运行结果:130 minutes turned out to be 2 hours after duration_cast.
显然:130分钟是2小时10分钟,但是在duration_cast之后他的值成了2小时,发生精度丢失。
实战2:与steady_clock结合
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
#include <ctime>
void func() {
long long sum(0);
for (int i = 0; i < 100000; i++) {
sum += i;
}
}
int main() {
using namespace std::chrono;
steady_clock::time_point begin, end;
begin = steady_clock::now();
func();
end = steady_clock::now();
duration<double> time_span(duration_cast<duration<double>>(end - begin));
std::cout << "It took " << time_span.count() << " seconds." << std::endl;
std::cin.get();
return 0;
}
运行结果:It took 0.000805672 seconds.
4.2 time_point_cast
4.2.1 time_point_cast原型
emplate <class ToDuration, class Clock, class Duration>
time_point<Clock,ToDuration> time_point_cast (const time_point<Clock,Duration>& tp);
- 将某种类型的time_point转换成另一种类型的time_point,同时不会忽略二者duration中period的不同
- 由函数原型中,我们可以知道,这种转换主要发生在一个time_point的clock类型相同,但是duration类型不同的情况。
- 内部调用的是duration_cast来处理duration部分。
实战:打印当前距离epoch时间点的秒数和天数
#include <iostream>
#include <chrono>
#include <ratio>
#include <typeinfo>
#include <ctime>
int main() {
using namespace std::chrono;
typedef duration<long long>second_type;
typedef duration<long long, std::ratio<60 * 60 * 24, 1>>day_type;
system_clock::time_point tp(system_clock::now());
time_point<system_clock, second_type>tp_seconds(time_point_cast<second_type>(tp));
time_point<system_clock, day_type>tp_days(time_point_cast<day_type>(tp));
std::cout << "time since epoch : \n"
<< tp_seconds.time_since_epoch().count() << " seconds ,\n"
<< tp_days.time_since_epoch().count() << " days." << std::endl;
std::cin.get();
return 0;
}
运行结果:
time since epoch :
1448805197 seconds ,
16768 days.
2. chrono中一些实例话的类型
在std::chrono的命名空间下同样也有duration的一些实例化的类型:
3. ctime头文件
参考:http://www.cplusplus.com/reference/ctime/
3.1 ctime中定义的类型
types | 描述 |
---|---|
clock_t | Clock type (type ) |
size_t | Unsigned integral type (type ) |
time_t | Time type (type ) |
struct tm | Time structure (type ) |
3.1.1 clock_t
typedef long clock_t;
主要作为clock()函数的返回值
3.1.2 size_t
typedef unsigned int size_t;
主要作为strftime()函数的参数
3.1.3 time_t
#ifndef _CRT_NO_TIME_T
#ifdef _USE_32BIT_TIME_T
typedef __time32_t time_t;
#else
typedef __time64_t time_t;
#endif
#endif
多用于表示距离 00:00 hours, Jan 1, 1970 UTC 的秒数。
3.1.4 struct tm
struct tm
{
int tm_sec; // seconds after the minute - [0, 60] including leap second
int tm_min; // minutes after the hour - [0, 59]
int tm_hour; // hours since midnight - [0, 23]
int tm_mday; // day of the month - [1, 31]
int tm_mon; // months since January - [0, 11]
int tm_year; // years since 1900
int tm_wday; // days since Sunday - [0, 6]
int tm_yday; // days since January 1 - [0, 365]
int tm_isdst; // daylight savings time flag
};
- 用于表示时间的结果体。将时间分解成以一个的组件(时、分、秒等)。
- tm_isdst表示的是夏令时。
参考:http://baike.baidu.com/view/100246.htm- tm_year 是从1900年算起的
- 当 tm_isdst=0 时,表示不受夏令时的影响
当 tm_isdst>0 时,表示受到夏令时的影响
当 tm_isdst<0 时,表示该值无效
3.2 ctime中的宏
Macro name | 描述 |
---|---|
CLOCKS_PER_SEC | Clock ticks per second |
NULL | Null pointer |
#define CLOCKS_PER_SEC ((clock_t)1000)
#define NULL 0
- CLOCKS_PER_SEC主要用于时间单位的转换(从毫秒到秒,尤其是clock_t类型的转换)
3.3 ctime中操作时间的函数
函数 | 描述 |
---|---|
clock | Clock program (function ) |
difftime | Return difference between two times (function ) |
mktime | Convert tm structure to time_t (function ) |
time | Get current time (function ) |
3.3.1 clock()函数
clock_t clock (void);
- (1)类似于steady_clock的功能,clock主要用于计算某个操作花费的时间。
- (2)注意该函数的返回类型为clock_t , 它的计时方式是时钟的步数(clock ticks),不是秒数。
- (3)如果函数调用失败,返回的是-1
实战clock:
#define _CRT_SECURE_NO_WARNINGS//关闭VC的安全检查
#include <iostream>
#include <typeinfo>
#include <ctime>
void func() {
long long sum(0);
for (int i = 0; i < 99999999; i++)
sum += i;
}
int main() {
std::clock_t begin, end, time_span;
begin = clock();
func();
end = clock();
time_span = end - begin;
std::cout << "It took " << time_span << " ticks." << std::endl;
std::cout << "It took " << static_cast<double>(time_span) / CLOCKS_PER_SEC << " seconds." << std::endl;
std::cin.get();
return 0;
}
运行结果:
It took 710 ticks.
It took 0.71 seconds.
3.3.2 difftime()函数
double difftime (time_t end, time_t beginning);
- 计算end到beginning之间的秒数
- 返回double类型
实战:difftime函数
#include <iostream>
#include <typeinfo>
#include <ctime>
#include <Windows.h>
void func() {
long long sum(0);
for (int i = 0; i < 999999999; i++)
sum += i;
}
int main() {
std::time_t begin, end, endx;
begin = time(NULL);
func();
end = time(NULL);
std::cout << "It took " << std::difftime(end,begin) << " seconds." << std::endl;
Sleep(3510);
endx = time(NULL);
std::cout << "It took " << std::difftime(endx, end) << " seconds." << std::endl;
std::cin.get();
return 0;
}
运行结果:
It took 7 seconds.
It took 3 seconds.
3.3.3 mktime()函数
time_t mktime (struct tm * timeptr);
- 将struct tm类型转化为time_t类型。
- 该函数功能与localtime的功能相反
- 转换时,会忽略tm_wday 和tm_yday,其他的数据将会根据适当地转换
- 调用该函数可能会自动修改struct tm中的变量,前提是如果存在越界等的情况。
实战:mktime函数
#define _CRT_SECURE_NO_WARNINGS//关闭VC的安全检查
#include <iostream>
#include <typeinfo>
#include <ctime>
int main() {
//构造一个2010年10月23日10点23分6秒
tm timeinfo;
timeinfo.tm_year = 2010 - 1900;
timeinfo.tm_mon = 10 - 1;
timeinfo.tm_mday = 23;
timeinfo.tm_hour = 10;
timeinfo.tm_min = 23;
timeinfo.tm_sec = 6;
std::time_t tms(std::mktime(&timeinfo));
std::cout << ctime(&tms) << std::endl;
std::cin.get();
return 0;
}
运行结果:Sat Oct 23 10:23:06 2010
3.3.4 time()函数
time_t time (time_t* timer);
- 功能:获取当前时间
- 该函数有两种返回方式:
一种通过返回值返回当前时间(当参数为NULL时)
一种通过参数返回(当参数不为NULL时)- 返回值通常表示从 00:00 hours, Jan 1, 1970 UTC 开始的秒数。
实战:time函数
#define _CRT_SECURE_NO_WARNINGS//关闭VC的安全检查
#include <iostream>
#include <typeinfo>
#include <ctime>
int main() {
//std::time_t tms(std::time(NULL));//等价于下面的写法
std::time_t tms;
time(&tms);
std::cout << ctime(&tms) << std::endl;
std::cin.get();
return 0;
}
运行结果:Sun Nov 29 23:11:41 2015
3.4 ctime中时间格式转换函数
functions | 描述 |
---|---|
asctime | Convert tm structure to string (function ) |
ctime | Convert time_t value to string (function ) |
gmtime | Convert time_t to tm as UTC time (function ) |
localtime | Convert time_t to tm as local time (function ) |
strftime | Format time as string (function ) |
3.4.1 asctime()函数
char* asctime (const struct tm * timeptr);
- 将struct tm类型的时间转换为易懂的字符串。
- 输出格式为:Www Mmm dd hh:mm:ss yyyy (星期 月 日 时:分:秒 年)
- 返回的C字符串包括 ‘\n’ (换行符) 和 ‘\0’ (结束符) 。
- 返回的字符串为内置的静态区,不需要回收。
实战:astime函数
#define _CRT_SECURE_NO_WARNINGS//关闭VC的安全检查
#include <iostream>
#include <typeinfo>
#include <ctime>
#include <cstdio>
int main() {
//构造一个2010年10月23日10点23分6秒
tm timeinfo;
timeinfo.tm_year = 2010 - 1900;
timeinfo.tm_mon = 10 - 1;
timeinfo.tm_mday = 23;
timeinfo.tm_hour = 10;
timeinfo.tm_min = 23;
timeinfo.tm_sec = 6;
timeinfo.tm_wday = timeinfo.tm_yday = timeinfo.tm_isdst = 0;
std::cout << asctime(&timeinfo) << std::endl;//直接将struct tm转换为c-string
std::cin.get();
return 0;
}
运行结果:Sun Oct 23 10:23:06 2010
3.4.2 ctime()函数
char* ctime (const time_t * timer);
- 将time_t类型转换为易懂的字符串
- 输出格式为:Www Mmm dd hh:mm:ss yyyy (星期 月 日 时:分:秒 年)
实战:ctime函数
#define _CRT_SECURE_NO_WARNINGS//关闭VC的安全检查
#include <iostream>
#include <typeinfo>
#include <ctime>
#include <cstdio>
int main() {
std::time_t tms(std::time(NULL));
std::cout << ctime(&tms) << std::endl;//打印当前时间
std::cin.get();
return 0;
}
运行结果:Sun Nov 29 23:31:08 2015
3.4.3 ctime()函数
struct tm * gmtime (const time_t * timer);
- 将time_t类型时间转换为struct tm类型,但是该时间使用UTC(世界统一时间,世界标准时间)来表示的。
- 函数名的由来:UTC别名GMT(Greenwich MeanTime)即格林尼治标准时间。所以该函数取名为gmtime
实战:gmtime函数
#define _CRT_SECURE_NO_WARNINGS//关闭VC的安全检查
#include <iostream>
#include <typeinfo>
#include <ctime>
#include <cstdio>
const int CHINA(8);//中国在东8区,东+西-
int main() {
std::time_t tms(std::time(NULL));//保存当前时间
std::tm *timeinfo(std::gmtime(&tms));//转换为GMT时间
std::cout << "GMT = " << timeinfo->tm_hour << ":" << timeinfo->tm_min << ":" << timeinfo->tm_sec << std::endl;
std::cout << "CHINA = " << (timeinfo->tm_hour + CHINA) % 24 << ":" << timeinfo->tm_min << ":" << timeinfo->tm_sec;
std::cin.get();
return 0;
}
运行结果:
GMT = 15:42:24
CHINA = 23:42:24
3.4.4 localtime()函数
struct tm * localtime (const time_t * timer);
- 将time_t时间类型转换为struct tm类型(转换后的为地方时间,不是GMT)
实战:localtime函数
#define _CRT_SECURE_NO_WARNINGS//关闭VC的安全检查
#include <iostream>
#include <typeinfo>
#include <ctime>
#include <cstdio>
int main() {
std::time_t tms(std::time(NULL));
std::tm *timeinfo(std::localtime(&tms));//将tms转换为struct tm类型
std::cout << "Time = " << timeinfo->tm_hour << ':' << timeinfo->tm_min << ':' << timeinfo->tm_sec << std::endl;//打印时间
std::cin.get();
return 0;
}
运行结果:Time = 23:49:44
3.4.5 strftime()函数
size_t strftime (char* ptr, size_t maxsize, const char* format,
const struct tm* timeptr );
- 按照特定的格式输出字符,类似printf。
- 更详细的信息查看:
http://www.cplusplus.com/reference/ctime/strftime/