以下整理自:https://www.2cto.com/kf/201404/290706.html
chrono 库主要包含了三种类型:时间间隔 Duration、时钟 Clocks 和时间点 Time point
duration:
duration 表示一段时间间隔,用来记录时间长度,可以表示几秒钟、几分钟或者几个小时的时间间隔
duration 的原型是:
template<class Rep, class Period = std::ratio<1>> class duration;
第一个模板参数Rep是一个数值类型,表示时钟个数;第二个模板参数是一个默认模板参数std::ratio,它的原型是:
template<std::intmax_t Num, std::intmax_t Denom = 1> class ratio;
它表示每个时钟周期的秒数,其中第一个模板参数 Num 代表分子,Denom 代表分母,分母默认为 1,ratio 代表的是一个分子除以分母的分数值,比如 ratio<2> 代表一个时钟周期是两秒,ratio<60> 代表了一分钟,ratio<60*60> 代表一个小时,ratio<60*60*24> 代表一天。而ratio<1, 1000> 代表的则是1/1000秒即一毫秒,ratio<1, 1000000> 代表一微秒,ratio<1, 1000000000> 代表一纳秒。标准库为了方便使用,就定义了一些常用的时间间隔,如时、分、秒、毫秒、微秒和纳秒,在chrono命名空间下,它们的定义如下:
1 typedef duration <Rep, ratio<3600,1>> hours; 2 3 typedef duration <Rep, ratio<60,1>> minutes; 4 5 typedef duration <Rep, ratio<1,1>> seconds; 6 7 typedef duration <Rep, ratio<1,1000>> milliseconds; 8 9 typedef duration <Rep, ratio<1,1000000>> microseconds; 10 11 typedef duration <Rep, ratio<1,1000000000>> nanoseconds;
通过定义这些常用的时间间隔类型,我们能方便的使用它们,比如线程的休眠:
std::this_thread::sleep_for(std::chrono::seconds(3)); //休眠三秒
std::this_thread::sleep_for(std::chrono:: milliseconds (100)); //休眠100毫秒
chrono 还提供了获取时间间隔的时钟周期个数的方法 count()
count 以及 duration 的基本用法:
1 #include <iostream> 2 #include <chrono> 3 using namespace std; 4 5 int main(void) { 6 std::chrono::milliseconds ms{3};//3毫秒 7 8 std::chrono::microseconds us = 2 * ms;//6000微秒 9 10 std::chrono::duration<double, std::ratio<1, 30>> hz(3.5); 11 //hz为3.5个周期时间长度,每个周期为1/30s 12 13 cout << ms.count() << endl;//3 一个周期为1s 14 cout << us.count() << endl;//6000 一个周期为1us 15 cout << hz.count() << endl;//3.5 16 17 return 0; 18 }
时间间隔之间可以做运算,比如下面的例子中计算两端时间间隔的差值:
1 #include <iostream> 2 #include <chrono> 3 using namespace std; 4 5 int main(void) { 6 std::chrono::minutes t1(10);//10分钟 7 8 std::chrono::seconds t2( 60 );//60秒 9 10 std::chrono::seconds t3 = t1 - t2; 11 12 //t3 的时间周期为 second 13 std::cout << t3.count() << " second" << std::endl; 14 15 //通过 duration_cast 将时间周期转化为 minutes 16 cout << chrono::duration_cast<chrono::minutes>(t3).count() << " minutes" << endl; 17 18 // 输出: 19 // 540 second 20 // 9 minutes 21 22 return 0; 23 }
注意:我们还可以通过duration_cast<>() 来将当前的时钟周期转换为其它的时钟周期,如我可以把秒的时钟周期转换为分钟的时钟周期,然后通过 count 来获取转换后的分钟时间间隔
time point:
time_point 表示一个时间点,用来获取 1970.1.1 以来的秒数和当前的时间, 可以做一些时间的比较和算术运算,可以和 ctime 库结合起来显示时间。time_point 必须要 clock 来计时,time_point 有一个函数 time_from_eproch() 用来获得1970年1月1日到 time_point 时间经过的 duration。下面的例子计算当前时间距离1970年1月一日有多少天:
1 #include <iostream> 2 #include <ratio> 3 #include <chrono> 4 using namespace std; 5 6 int main(void) { 7 using namespace std::chrono; 8 typedef duration<int, std::ratio<60 * 60 * 24>> day_type; 9 10 time_point<system_clock, day_type> today = time_point_cast<day_type>(system_clock::now()); 11 cout << today.time_since_epoch().count() << " days since epoch" << endl; 12 13 // 输出: 14 // 17598 days since epoch 15 16 return 0; 17 }
time_point还支持一些算术元算,比如两个time_point的差值时钟周期数,还可以和duration相加减。下面的例子输出前一天和后一天的日期:
1 #include <iostream> 2 #include <iomanip> 3 #include <ctime> 4 #include <chrono> 5 using namespace std; 6 7 int main(void) { 8 using namespace std::chrono; 9 system_clock::time_point now = system_clock::now();//获得当前时间 10 11 std::time_t last = system_clock::to_time_t(now - std::chrono::hours(24)); 12 std::time_t next = system_clock::to_time_t(now + std::chrono::hours(24)); 13 14 return 0; 15 }
clocks
表示当前的系统时钟,内部有 time_point, duration, Rep, Period 等信息,它主要用来获取当前时间,以及实现 time_t 和 time_point 的相互转换。Clocks包含三种时钟:
system_clock:从系统获取的时钟;
steady_clock:不能被修改的时钟;
high_resolution_clock:高精度时钟,实际上是 system_clock 或者 steady_clock 的别名
可以通过 now() 来获取当前时间点:
1 #include <iostream> 2 #include <chrono> 3 #include <ratio> 4 using namespace std; 5 6 int main(void) { 7 using namespace std::chrono; 8 9 time_point<system_clock> t1 = system_clock::now(); 10 int cnt = 1e9; 11 while(--cnt); 12 time_point<system_clock> t2 = system_clock::now(); 13 14 cout << (t2 - t1).count() << endl; 15 //通过 duration_cast<>() 将周期转化为 secondse 16 cout << std::chrono::duration_cast<seconds>( t2-t1 ).count() << endl; 17 18 // 输出: 19 // 2669897000 20 // 2 21 22 return 0; 23 }
可以利用 high_resolution_clock 来实现一个类似于 boost.timer 的定时器:
1 #include <iostream> 2 #include <chrono> 3 #define ll long long 4 using namespace std; 5 using namespace std::chrono; 6 7 class Timer{ 8 public: 9 Timer() : m_begin(high_resolution_clock::now()) {} 10 //重置当前时间 11 void reset() { 12 m_begin = high_resolution_clock::now(); 13 } 14 15 //默认输出毫秒 16 ll elapsed() const { 17 return duration_cast<chrono::milliseconds>(high_resolution_clock::now() - m_begin).count(); 18 } 19 20 //微秒 21 ll elapsed_micro() const { 22 return duration_cast<chrono::microseconds>(high_resolution_clock::now() - m_begin).count(); 23 } 24 25 //纳秒 26 ll elapsed_nano() const { 27 return duration_cast<chrono::nanoseconds>(high_resolution_clock::now() - m_begin).count(); 28 } 29 30 //秒 31 ll elapsed_seconds() const { 32 return duration_cast<chrono::seconds>(high_resolution_clock::now() - m_begin).count(); 33 } 34 35 //分 36 ll elapsed_minutes() const { 37 return duration_cast<chrono::minutes>(high_resolution_clock::now() - m_begin).count(); 38 } 39 40 //时 41 ll elapsed_hours() const { 42 return duration_cast<chrono::hours>(high_resolution_clock::now() - m_begin).count(); 43 } 44 45 private: 46 time_point<high_resolution_clock> m_begin; 47 48 }; 49 50 void fun(int n) { 51 while(--n); 52 } 53 54 int main(void) { 55 Timer t;//开始记时 56 fun(1e9); 57 cout << t.elapsed_nano() << endl; 58 cout << t.elapsed_micro() << endl; 59 cout << t.elapsed() << endl; 60 cout << t.elapsed_seconds() << endl; 61 cout << t.elapsed_minutes() << endl; 62 cout << t.elapsed_hours() << endl; 63 64 // 输出: 65 // 2673899000 66 // 2673899 67 // 2674 68 // 2 69 // 0 70 // 0 71 72 return 0; 73 }