Files
Obsidian-Main/20. 專注/C++/chrono.md

79 lines
5.3 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Language: C++11
## header
```cpp
#include <chrono>
```
## duration
duration 是 chrono 裡面,用來記錄時間長度的類別,他基本上是一個 template class可以自行定義他的意義chrono 也有提供一些比較常見的時間類別可以直接拿來使用下面就是內建的 duration 的型別
```cpp
typedef duration<long long, nano> nanoseconds;
typedef duration<long long, micro> microseconds;
typedef duration<long long, milli> milliseconds;
typedef duration<long long> seconds;
typedef duration<int, ratio<60> > minutes;
typedef duration<int, ratio<3600> > 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<chrono::minutes>( 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<std::chrono::microseconds>(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/)