C++11标准库chrono

https://blog.csdn.net/u010487568/article/details/50512770

chrono是C++11新加入的方便时间日期操作的标准库,它既是相应的头文件名称,也是std命名空间下的一个子命名空间,所有时间日期相关定义均在std::chrono命名空间下。通过这个新的标准库,可以非常方便进行时间日期相关操作。 
chrono库主要包含了三种类型:duration, time_point 和 clock。

Duration(时间间隔)

chrono库中用一个duration模板类,用来表示一段时间间隔,可以表示几秒钟、几分钟或者几个小时的时间间隔。

原型

template<typename _Rep, typename _Period = ratio<1>>
struct duration
{
typedef _Rep   rep;
...
private:
    rep  __r;  //内部维护的计数个数成员
...
};

第一个模版参数是数值类型,表示时钟个数;第二个为std::ratio,用来表示每个时钟的周期(单位为秒)。 
ratio的原型是

template<intmax_t _Num, intmax_t _Den = 1>
struct ratio;

这是一个非类型模版参数的模版类,intmax_t是定义在cstdint头文件中的内置类型。第一个参数代表分子,第二个代表分母,两者表示一个通用的比率类型。它们必须在编译期间确定为常量值。分母默认为1,因此ratio<60>代表60,ratio<1, 1000>代表0.001。为了方便使用,在ratio头文件中定义了常用比率的别名:

  typedef ratio<1,       1000000000000000000> atto;
  typedef ratio<1,          1000000000000000> femto;
  typedef ratio<1,             1000000000000> pico;
  typedef ratio<1,                1000000000> nano;
  typedef ratio<1,                   1000000> micro;
  typedef ratio<1,                      1000> milli;
  typedef ratio<1,                       100> centi;
  typedef ratio<1,                        10> deci;
  typedef ratio<                       10, 1> deca;
  typedef ratio<                      100, 1> hecto;
  typedef ratio<                     1000, 1> kilo;
  typedef ratio<                  1000000, 1> mega;
  typedef ratio<               1000000000, 1> giga;
  typedef ratio<            1000000000000, 1> tera;
  typedef ratio<         1000000000000000, 1> peta;
  typedef ratio<      1000000000000000000, 1> exa;

回到duration模板类,默认的比率为ratio<1>,也就是一个时钟数_Rep代表1秒。为了方便使用,chrono库定义了如下的常用时间单位:

    /// nanoseconds
    typedef duration<int64_t, nano>     nanoseconds;

    /// microseconds
    typedef duration<int64_t, micro>    microseconds;

    /// milliseconds
    typedef duration<int64_t, milli>    milliseconds;

    /// seconds
    typedef duration<int64_t>       seconds;

    /// minutes
    typedef duration<int, ratio< 60>>   minutes;

    /// hours
    typedef duration<int, ratio<3600>>  hours;

通过定义上述常用类型,可以非常方便的使用:

//线程休眠10秒
std::this_thread::sleep_for(std::chrono::seconds(10));

成员

duration内部维护了周期个数rep和周期period,两者结合用来表示间隔时间。

count

用来获取内部维护的rep类型的周期个数,或称为tick数。

chrono::milliseconds ms(10);
chrono::duration<double, std::ratio<1, 30>> dur(10.5);
cout << "ms: " << ms.count() << '\t'<<"dur: "<<dur.count() << endl;

上述代码输出:

ms: 10 dur : 10.5

静态成员函数

duration实例化后,对于给定的rep表示周期个数的类型,提供了min、max和zero三个静态成员函数,用来获取当前类型能表示的最小、最大周期数和0周期数代表的duration对象。

cout << chrono::seconds::max().count() << endl;
//输出结果为:9223372036854775807

运算操作

duration支持基本所有算术运算操作,而且不同单位之间的可以自动进行匹配。这是通过duration_cast模板类实现的。

chrono::mimutes t1(5);
chrono::seconds t2(30);
chrono::seconds t3 = t2 - t1;
cout << t3.count << '\t' << chrono::duration_cast<chrono::minutes>(t3).count() << endl;
//对于类型转换会进行舍入
//输出结果:270     4

Time point

chrono库中用一个time_point模板类,表示一个时间点,如生日、今天日落时刻等,通过一个相对epoch的时间间隔duration来实现,epoch就是1970-1-1时刻,对于同一个时钟来说,所有的time_point的epoch都是固定的。这个类可以与标准库ctime结合起来显示时间,ctime内部的time_t类型就是代表这个秒数。

原型

template<typename _Clock, typename _Dur = typename _Clock::duration>
struct time_point
{
typedef _Clock                      clock;
typedef _Dur                        duration;
typedef typename duration::rep              rep;
typedef typename duration::period           period;
private:
    duration __d; //维护的内部duration成员
...

};

第一个参数为当前计时使用的时钟,可选为“system_colck”、“steady_colck”、“high_resolution_clock”或者是自定义的时钟类;第二个参数为时间间隔,默认为使用的时钟相同的间隔。 
内部维护了一个duration私有成员,通过制定的时钟,来确定距离epoch时间点的间隔。

构造函数

默认为时间点0,重载了使用duration对象构造,另外还有一个复制构造模版函数。

constexpr time_point() : __d(duration::zero())
{ }
constexpr explicit time_point(const duration& __dur)
: __d(__dur)
{ }

// conversions
template<typename _Dur2>
constexpr time_point(const time_point<clock, _Dur2>& __t)
: __d(__t.time_since_epoch())
{ }

成员

time_point提供了与C API的时间交互的良好定义。因此,可以很容易与time_t类型打交道,提供了唯一的成员函数time_since_epoch,用来返回距离epoch的duration对象,从而就可以使用相关ctime函数进行处理了。

chrono::time_point<system_clock> tp = chrono::system_clock::now();
cout << tp.time_since_epoch().count() << endl;

//输出为:1452672734311762303
//system_clock的ratio为nano

运算

与duration类似,time_point也提供了静态成员min和max,以及算术运算操作,这些都是通过内部维护的duration成员进行的,duration成员的各种操作由前面所述的提供保障,time_point就只需要通过time_since_epoch获取私有duration成员进行调用即可。还提供了与duration直接进行”+=”和“-=”的运算操作,对于普通的算术运算,如果有一个操作数类型为duration,则是在time_point类型操作数内部维护的duration成员上进行操作,则返回类型为time_point;当两者均为time_point类型时,返回类型为二者维护的duration成员之差,从而返回类型也为duration。

chrono::seconds t(60);
chrono::time_point<chrono::system_clock> tp(t);
cout << tp.time_since_epoch().count() << endl;
tp += t;
cout << tp.time_since_epoch().count() << endl;
cout << (tp - t).time_since_epoch().count() << endl;//返回类型为time_point,需要先获取内部的duration对象后调用count

chrono::time_point<chrono::system_clock> tp1(t);
cout << (tp - tp1).count() << endl; //返回类型为duration,直接调用count

typedef chrono::duration<long, ratio<3600 * 24>> days;
chrono::time_point<chrono::system_clock> now = chrono::system_clock::now();
auto td = chrono::time_point_cast<days>(now);
cout << td.time_since_epoch().count() << " days" << endl;

输出为:

60,000,000,000 
120,000,000,000 
60,000,000,000 
60,000,000,000 
16813 days

Clocks

表示当前系统时钟,共有三种: 
system_clock:从系统获取时钟 
steady_clock:不能被修改的时钟 
high_resolution_clock:高精度时钟,实际上是system_clock或者steady_clock的别名

gcc4.8版本内的chrono文件中可以看到:

/**
 *  @brief Highest-resolution clock
 *
 *  This is the clock "with the shortest tick period." Alias to
 *  std::system_clock until higher-than-nanosecond definitions
 *  become feasible.
 */
using high_resolution_clock = system_clock;

system_clock默认使用的就是nanosecond作为最小单位。下面着重介绍system_clock

定义

struct system_clock
{
  typedef chrono::nanoseconds                   duration;
  typedef duration::rep                     rep;
  typedef duration::period                  period;
  typedef chrono::time_point<system_clock, duration>    time_point;

  static_assert(system_clock::duration::min()
  < system_clock::duration::zero(),
  "a clock's minimum duration cannot be less than its epoch");

  static constexpr bool is_steady = false;

  static time_point
  now() noexcept;

  // Map to C API
  static std::time_t
  to_time_t(const time_point& __t) noexcept
  {
return std::time_t(duration_cast<chrono::seconds>
  (__t.time_since_epoch()).count());
  }

  static time_point
  from_time_t(std::time_t __t) noexcept
  {
typedef chrono::time_point<system_clock, seconds>   __from;
return time_point_cast<system_clock::duration>
    (__from(chrono::seconds(__t)));
  }
};

从定义可以看出,这是一个非常简单的类,内部维护了nanoseconds作为duration作为最小时间单位。仅提供了三个static函数,可以非常方便的获取系统时间点time_point,以及与time_t类型的相互转换,为于ctime交互提供了保证。

auto tp = chrono::system_clock::now();
time_t nowt = chrono::system_clock::to_time_t(tp);
cout << nowt << endl;
cout << ctime(&nowt) << endl;
cout << put_time(localtime(&nowt), "%Y-%m-%d") << endl;
  •  

1452684162 
Wed Jan 13 19:22:42 2016 
2016-01-13

对于steady_clock也是类似,但只提供了now这个static函数,没有到time_t的转换接口。 
对于其他特殊需求,可以定义自己的clock类,然后传给time_point作为第一个模版参数从而进行自定义的世界操作。

猜你喜欢

转载自blog.csdn.net/jisuanji198509/article/details/81806540
今日推荐