--- tags: cpp11 aliases: date: 2025-02-10 time: 17:38:00 description: --- ## header ```cpp #include  ``` ## duration duration 是 chrono 裡面,用來記錄時間長度的類別,他基本上是一個 template class,可以自行定義他的意義;chrono 也有提供一些比較常見的時間類別,可以直接拿來使用,下面就是內建的 duration 的型別: ```cpp typedef duration nanoseconds; typedef duration microseconds; typedef duration milliseconds; typedef duration seconds; typedef duration > minutes; typedef duration > hours; ``` 其中可以看到,第一個 template 參數是要用來儲存資料的型別,第二個則是他相對於「秒」的比例。這邊也使用了 ratio 這個 C++11 的另一個新的函式庫的類別,他是用來記錄「有理數」(可以寫成分數的數)的新類別,有興趣可以參考 [cppreference 的介紹](http://en.cppreference.com/w/cpp/numeric/ratio/ratio)。 基本上,一般會用到時間單位這邊都有定義好了,如果不合用的話,也可以自己去定義;而由於 chrono 也有把相關的計算都定義了,所以也可以直接拿來做計算,就算是時間單位不同,也不會有問題。 下面就是一個簡單的例子: ```cpp std::chrono::minutes t1( 10 ); std::chrono::seconds t2( 60 ); std::chrono::seconds t3 = t1 - t2; std::cout << t3.count() << " second" << std::endl; ``` 其中,t1 是代表 10 分鐘、 t2 是代表 60 秒,t3 則是 t1 減去 t2,也就是 600 – 60 = 540 秒。 而如果要取得一個 duration 的值的話,則是要呼叫他的 count() 這個函式;像在上面的例子裡面,就會把 t3 的值輸出,所以最後會出現「540 second」。 而如果想要做強制的時間單位轉換,也可以使用 duration_cast<>() 這個函式來做;下面就是一個把以秒為單位的 t3 轉換成分鐘後再輸出。 ```cpp cout << chrono::duration_cast( t3 ).count() << endl; ``` ## time_point 相較於 duration 是用來紀錄時間的長度的,time_point 是用來記錄一個特定時間點的資料類別。他一樣是一個 template class,需要指定要使用的 clock 與時間單位(duration)。 Chrono 一般來說有提供兩種 clock 可以使用,分別是:system_clock 和 steady_clock。其中 system_clock 是直接去抓系統的時間,有可能在使用中會被被修改([參考](http://en.cppreference.com/w/cpp/chrono/system_clock));而 steady_clock 則是確實地去紀錄時間的流逝,所以不會出現時間倒退的狀況([參考](http://en.cppreference.com/w/cpp/chrono/steady_clock))。 一般要使用的話,大概會是下面的樣子: ```cpp std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now(); std::cout << "Hello World\n"; std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now(); std::cout << "Printing took " << std::chrono::duration_cast(t2 - t1).count() << "us.\n"; ``` 透過 clock 類別所提供的 now() 這個函式,可以快速地取得現在的時間;而兩者相減的話,則會產生一個型別為 duration 的結果;在上面的例子裡面,就是一開始先取得當下的時間 t1,然後輸出一個字串後、再去取得一個時間 t2,之後兩者相減,就可以取得中間過程所花費的時間了。在這邊則是在相減後,把結果轉換成以 micro second 為單位後,再做輸出。 而 time_point 也可以和 duration 做計算,得出新的 time_point;例如下面的程式碼,就是計算 10 個小時候的時間: ```cpp std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); std::chrono::system_clock::time_point nt = now + std::chrono::hours(10); ``` 另外,chrono 也有定義 high_resolution_clock,提供更高的精確度([參考](http://en.cppreference.com/w/cpp/chrono/high_resolution_clock));但是實際上在 MSVC11 上,他就等同於 system_clock。 而如果要把不同定義的 time_point 做轉換,則也可以使用 time_point_cast<>() 這個函式來處理,不過這邊就不多加說明了。 ## time_point 的輸出 STL 的 chrono 並沒有定義 time_point 的輸出方式,所以我們並不能直接透過 output stream 來輸出 time_point 的資料,所以如果要把他輸出成字串的話,其實還有點麻煩… 如果想要輸出的話,一個方法是透過 clock 提供的 to_time_t() 這個函式,把 time_point 先把他轉換成 C-style 的 time_t,然後再透過 ctime() 這類的函式做輸出;下面是一個簡單的範例: ```cpp std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); std::time_t now_c = std::chrono::system_clock::to_time_t( now ); std::cout << std::ctime( &now_c ) << std::endl; ``` 而如果是使用 Boost 的版本的話,Boost 則是另外有提供 chrono_io.hpp 這個檔案,在裡面替 duration 和 time_point 定義了輸出的格式,可以直接使用,相當地方便~有興趣的話,可以參考 [Boost 的官方說明](http://www.boost.org/doc/libs/1_55_0/doc/html/chrono/users_guide.html#chrono.users_guide.tutorial.i_o)。 # 參考來源 - [C++11 STL 的時間函式庫:chrono – Heresy's Space](https://kheresy.wordpress.com/2013/12/27/c-stl-chrono/)