C++的chrono、ratio和ctime等头文件

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)

成员类型定义描述
typeratio同定义时的类型相同(但是化简了)

#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;
}

这里写图片描述


模板的实例:

typedefinitiondescription
yoctoratio<1,1000000000000000000000000>10-24 *
zeptoratio<1,1000000000000000000000>10-21 *
attoratio<1,1000000000000000000>10-18
femtoratio<1,1000000000000000>10-15
picoratio<1,1000000000000>10-12
nanoratio<1,1000000000>10-9
microratio<1,1000000>10-6
milliratio<1,1000>10-3
centiratio<1,100>10-2
deciratio<1,10>10-1
decaratio<10,1>101
hectoratio<100,1>102
kiloratio<1000,1>103
megaratio<1000000,1>106
gigaratio<1000000000,1>109
teraratio<1000000000000,1>1012
petaratio<1000000000000000,1>1015
exaratio<1000000000000000000,1>1018
zettaratio<1000000000000000000000,1>1021 *
yottaratio<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个概念来解决时间问题:

序号概念内容
1duration【1】duration解决的是时间的跨度问题(time spans):就像一分钟、一小时、一天等概念。【2】duration模板 使用两个子元素解决时间跨度问题:时间的度量单位(period)+单位时间的多少(count)。(比如:40分钟由 分钟作为单位,有40个这样的事件单位。即 period=1分钟 , count=40)
2time_point【1】一个具体的时间点,如某人的生日,火车的发车时间等。【2】time_point模板使用一个duration与某个具体的时间戳epoch(Epoch指的是一个特定的时间:1970-01-01 00:00:00 UTC)的关系来表示某个时间点。
3Clocks【1】Clocks值得是一个把time_point与现实世界的时间相联系的framework。【2】该头文件提供了至少3个这种framework:system_clock, steady_clock and high_resolution_clock。

chrono中包含的类

类别成员1成员2成员3
duration&time_pointdurationtime_point
clockssystem_clocksteady_clockhigh_resolution_clock
traitstreat_as_floating_pointduration_valuescommon_type (duration)
functionsduration_casttime_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. 构造函数
    原型:
(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 三天的时间


  1. 析构函数(略)


  2. 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学习完后就可以自如的运用了。


  1. min()
  2. max()

上面这两个静态函数成员就是 返回time_point的最大值和最小值,返回类型是time_point类型


  1. 运算符重载
    time_point运算符重载比较有意思的地方是,运算符左边和右边类型的不同会导致返回值类型的不同。如图:
    ( tp 表示time_point类型 、 dtn 表示duration类型 )
    这里写图片描述

  1. 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_tClock type (type )
size_tUnsigned integral type (type )
time_tTime type (type )
struct tmTime 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_SECClock ticks per second
NULLNull pointer
#define CLOCKS_PER_SEC  ((clock_t)1000)
#define NULL            0
  • CLOCKS_PER_SEC主要用于时间单位的转换(从毫秒到秒,尤其是clock_t类型的转换)

3.3 ctime中操作时间的函数

函数描述
clockClock program (function )
difftimeReturn difference between two times (function )
mktimeConvert tm structure to time_t (function )
timeGet 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描述
asctimeConvert tm structure to string (function )
ctimeConvert time_t value to string (function )
gmtimeConvert time_t to tm as UTC time (function )
localtimeConvert time_t to tm as local time (function )
strftimeFormat 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 );

转载请注明出处


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值