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);//10個tick
chrono::duration<double, std::ratio<1, 30>> dur(10.5);//10.5 tick
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::minutes t1(5);
chrono::seconds t2(30);
chrono::seconds t3 = t1 - t2;
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時間點的間隔。
成員
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。
表示當前系統時鍾,共有三種:
- system_clock:從系統獲取時鍾
- steady_clock:不能被修改的時鍾
- high_resolution_clock:高精度時鍾,實際上是system_clock或者steady_clock的別名,最小精度是納秒
system_clock
system_clock 提供三個靜態的函數,可以用於time_point提供了與C API的時間交互的良好定義。因此,可以很容易與time_t類型打交道。接口函數如下:
//get current time
static time_point now() noexcept;
//time_point conver to time_t
static time_t to_time_t (const time_point& tp) noexcept;
//convert time_t to time_oint
std::chrono::system_clock::from_time_t
static time_point from_time_t (time_t t) noexcept;
system_clock 和ctime函數使用demo:
#include <iostream>
#include <ctime>
#include <chrono>
int main ()
{
using std::chrono::system_clock;
std::chrono::duration<int,std::ratio<60*60*24> > one_day (1);
//current time
system_clock::time_point today = system_clock::now();
//tomorrow time
system_clock::time_point tomorrow = today + one_day;
//convert time type
time_t tmTomorrow = system_clock::to_time_t ( tomorrow );
//time string
std::cout << "tomorrow will be: " << ctime(&tmTomorrow);
struct tm *p;
p = localtime(&tmTomorrow); /*轉換為struct tm結構的當地時間*/
printf("%d/%d/%d ", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday);
return 0;
}
運行結果:
tomorrow will be: Sun Feb 11 09:13:07 2018
2018/2/11
steady_clock
steady_clock 專門用於計算時間差的工具,steady_clock 類只有一個靜態函數now(),用於獲取當前的時間,計算時間差的方式如下:
#include <iostream>
#include <chrono>
int main()
{
typedef std::chrono::steady_clock STEADY_CLOCK;
STEADY_CLOCK::time_point t1 = STEADY_CLOCK::now();
std::cout << "print 1000 stars" << std::endl;
for (int i=1; i<=1000; ++i)
{
std::cout << "*";
if (0 == i % 50)
{
std::cout << "\n";
}
}
std::cout << std::endl;
STEADY_CLOCK::time_point t2 = STEADY_CLOCK::now();
//毫秒
std::chrono::duration<double, std::milli> dTimeSpan = std::chrono::duration<double,std::milli>(t2-t1);
std::cout << "print start time span : " << dTimeSpan.count() << "ms\n";
}
運行結果:
print 1000 stars
****************************....
print start time span : 0.091333ms
參考資料:
http://www.cplusplus.com/reference/chrono/
http://blog.csdn.net/u010487568/article/details/50512770