![](/img/trans.png)
[英]unsigned long long to std::chrono::time_point and back
[英]How do I convert a std::chrono::time_point to long and back?
我需要將std::chrono::time_point
與long
類型(整數 64 位)相互轉換。 我開始使用std::chrono
...
這是我的代碼:
int main ()
{
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
auto epoch = now.time_since_epoch();
auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
long duration = value.count();
std::chrono::duration<long> dur(duration);
std::chrono::time_point<std::chrono::system_clock> dt(dur);
if (dt != now)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
此代碼編譯,但未顯示成功。
為什么dt
最后與now
不同?
該代碼缺少什么?
std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
這是auto
的好地方:
auto now = std::chrono::system_clock::now();
由於您希望以millisecond
精度進行流量,因此最好在time_point
中繼續並隱蔽它:
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
now_ms
是一個time_point
,基於system_clock
,但精度為milliseconds
,而不是system_clock
的精度。
auto epoch = now_ms.time_since_epoch();
epoch
現在有類型std::chrono::milliseconds
。 下一條語句本質上變成了無操作(僅進行復制而不進行轉換):
auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
這里:
long duration = value.count();
在您和我的代碼中, duration
包含自system_clock
紀元以來的milliseconds
數。
這個:
std::chrono::duration<long> dur(duration);
創建一個用long
表示的duration
,精度為seconds
。 這有效地將milliseconds
value
reinterpret_cast
為seconds
。 這是一個邏輯錯誤。 正確的代碼如下所示:
std::chrono::milliseconds dur(duration);
這一行:
std::chrono::time_point<std::chrono::system_clock> dt(dur);
基於system_clock
創建一個time_point
,具有將精度保持為system_clock
的本機精度(通常比毫秒更精細)的能力。 但是,運行時值將正確反映保持整數毫秒(假設我對dur
的類型進行了更正)。
即使進行了更正,此測試也會(幾乎總是)失敗:
if (dt != now)
因為dt
擁有一個整數milliseconds
,但now
擁有整數個比millisecond
更精細的刻度(例如microseconds
或nanoseconds
)。 因此,只有在system_clock::now()
返回整數milliseconds
的極少數情況下,測試才會通過。
但您可以改為:
if (dt != now_ms)
現在,您將可靠地獲得預期的結果。
把它們放在一起:
int main ()
{
auto now = std::chrono::system_clock::now();
auto now_ms = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
auto value = now_ms.time_since_epoch();
long duration = value.count();
std::chrono::milliseconds dur(duration);
std::chrono::time_point<std::chrono::system_clock> dt(dur);
if (dt != now_ms)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
就我個人而言,我發現所有std::chrono
都過於冗長,因此我將其編碼為:
int main ()
{
using namespace std::chrono;
auto now = system_clock::now();
auto now_ms = time_point_cast<milliseconds>(now);
auto value = now_ms.time_since_epoch();
long duration = value.count();
milliseconds dur(duration);
time_point<system_clock> dt(dur);
if (dt != now_ms)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
這將可靠地輸出:
Success.
最后,我建議消除臨時變量以將time_point
和整數類型之間的代碼轉換減少到最低限度。 這些轉換是危險的,因此您編寫的操作裸整數類型的代碼越少越好:
int main ()
{
using namespace std::chrono;
// Get current time with precision of milliseconds
auto now = time_point_cast<milliseconds>(system_clock::now());
// sys_milliseconds is type time_point<system_clock, milliseconds>
using sys_milliseconds = decltype(now);
// Convert time_point to signed integral type
auto integral_duration = now.time_since_epoch().count();
// Convert signed integral type to time_point
sys_milliseconds dt{milliseconds{integral_duration}};
// test
if (dt != now)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
上面的主要危險不是在返回time_point
的路上將integral_duration
解釋為milliseconds
。 減輕這種風險的一種可能方法是編寫:
sys_milliseconds dt{sys_milliseconds::duration{integral_duration}};
這將風險降低到只需確保您在退出時使用sys_milliseconds
,並在返回途中的兩個地方使用。
再舉一個例子:假設您要轉換為表示system_clock
支持的任何持續時間(微秒、10微秒或納秒)的積分。 然后您不必擔心如上所述指定毫秒。 代碼簡化為:
int main ()
{
using namespace std::chrono;
// Get current time with native precision
auto now = system_clock::now();
// Convert time_point to signed integral type
auto integral_duration = now.time_since_epoch().count();
// Convert signed integral type to time_point
system_clock::time_point dt{system_clock::duration{integral_duration}};
// test
if (dt != now)
std::cout << "Failure." << std::endl;
else
std::cout << "Success." << std::endl;
}
這可行,但是如果您在一個平台上運行一半轉換(從積分轉換為整數),而在另一個平台上運行另一半轉換(從積分轉換),您將面臨system_clock::duration
對這兩個轉換具有不同精度的風險。
我還要注意有兩種方法可以獲取時間點的毫秒數。 我不確定哪個更好,我已經對它們進行了基准測試,它們都具有相同的性能,所以我想這是一個偏好問題。 也許霍華德可以插話:
auto now = system_clock::now();
//Cast the time point to ms, then get its duration, then get the duration's count.
auto ms = time_point_cast<milliseconds>(now).time_since_epoch().count();
//Get the time point's duration, then cast to ms, then get its count.
auto ms = duration_cast<milliseconds>(tpBid.time_since_epoch()).count();
第一個在我的腦海中從左到右讀得更清楚。
作為單行:
long value_ms = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch()).count();
time_point
對象僅支持與其他time_point
或duration
對象的算術運算。
您需要將long
轉換為指定單位的duration
,然后您的代碼應該可以正常工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.