![](/img/trans.png)
[英]Convert C# DateTime to C++ std::chrono::system_clock::time_point
[英]Convert steady_clock::time_point (C++) to System::DateTime (C++/CLI)
我需要將C++ std::chrono::steady_clock::time_point
為C++/CLI System::DateTime
。
背景:
我正在用 C++/CLI 接口包裝一個 C++ 庫,供 .NET 應用程序使用。
其中一種 C++ 方法返回std::chrono::steady_clock::time_point
。 我認為從 C++/CLI 包裝器方法返回System::DateTime
是合適的。 因此需要轉換。
我知道如果我有一個system_clock::time_point
,
我本可以將它轉換為time_t
,如下所述: 如何將 std::chrono::time_point 轉換為帶有小數秒的日歷日期時間字符串? .
然后我可以使用DateTimeOffset.FromUnixTimeMilliseconds ,並從中得到一個System::DateTime
。
另一種方法可能是使用time_since_epoch
。
但是to_time_t
和time_since_epoch
都不適用於std::chrono::steady_clock
(關於time_since_epoch
參見: chrono stable_clock not give correct result? )。
但是 - 我無法更改 C++ 接口。
也沒有設法正確地將steady_clock::time_point
轉換為例如system_clock::time_point
。
我想出的解決方案:
我從std::chrono::steady_clock
和System::DateTime
獲取當前時間,然后從steady_clock::time_point
計算偏移量,最后將此偏移量反向應用到 DateTime 時間。 我以毫秒為單位計算偏移量,因為我感興趣的精度是秒,所以效果很好。
該方法如下面的代碼所示。
但是感覺有點別扭。 它對要求的精度也很敏感。
我的問題:您能建議一種更好的轉換方法嗎?
using namespace System;
#include <chrono>
System::DateTime SteadyClockTimePointToDateTime(std::chrono::steady_clock::time_point const & tCPP)
{
auto nowCPP = std::chrono::steady_clock::now();
auto nowCLI = System::DateTime::Now;
long long milliSecsSinceT = std::chrono::duration_cast<std::chrono::milliseconds>(nowCPP - tCPP).count();
System::DateTime tCLI = nowCLI - System::TimeSpan::FromMilliseconds(static_cast<double>(milliSecsSinceT));
return tCLI;
}
int main(array<System::String ^> ^args)
{
System::Console::WriteLine("System::DateTime::Now (for debug): " + System::DateTime::Now.ToString()); // print reference time for debug
auto tCPP = std::chrono::steady_clock::now(); // got the actual value from a C++ lib.
System::Threading::Thread::Sleep(100); // pass some time to simulate stuff that was executed since the time_point was received.
System::DateTime tCLI = SteadyClockTimePointToDateTime(tCPP);
System::Console::WriteLine("System::DateTime (converted): " + tCLI.ToString()); // should show a time very close to System::DateTime::Now above
return 0;
}
輸出示例:
System::DateTime::Now (for debug): 23-May-22 16:41:04
System::DateTime (converted): 23-May-22 16:41:04
注意:我添加了 C++ 標簽,因為問題不是純 C++/CLI 問題。 例如,可能有一個解決方案涉及 std::chrono 時鍾之間的轉換,這將能夠輕松地進一步轉換為 System::DateTime (如上面提到的關於DateTimeOffset.FromUnixTimeMilliseconds
)。
這種方法是合理的,但是通過一些小的更改可以使代碼更短且更易於閱讀:
template<typename Rep, typename Period>
System::TimeSpan DurationToTimeSpan(std::chrono::duration<Rep, Period> const& input)
{
auto milliSecs =
std::chrono::duration_cast<std::chrono::milliseconds>(input).count();
return System::TimeSpan::FromMilliseconds(milliSecs);
}
System::DateTime SteadyClockTimePointToDateTime(
std::chrono::steady_clock::time_point const & tCPP)
{
auto const nowCPP = std::chrono::steady_clock::now();
auto nowCLI = System::DateTime::Now;
auto tCLI = nowCLI + DurationToTimeSpan(tCPP - nowCPP);
}
所做的具體更改是:
TimeSpan
工廠函數調用的使用。 1nowCPP
和tCPP
的減法順序,以避免以后必須顛倒符號。const
添加到具有本機類型且不會更改的局部變量。 遺憾的是,.NET 類型不是 const 正確的,因為const
-ness 僅受 C++/CLI 編譯器的尊重,而不是編寫 .NET 庫的語言。count()
的返回值和AddMilliseconds
的參數之間進行顯式類型轉換。 如果對於某些平台有不同的持續時間表示並且隱式轉換不起作用,最好讓編譯器告訴維護程序員。 請注意,此函數的結果不提供“穩定時鍾”保證。 為此,應生成單個time_point
/ DateTime
對並將其保存以供以后重用。
1另一種選擇是使用AddMilliseconds
成員函數,它取代了對TimeSpan
工廠函數和重載operator-
的調用:
System::DateTime SteadyClockTimePointToDateTime(
std::chrono::steady_clock::time_point const & tCPP)
{
auto const nowCPP = std::chrono::steady_clock::now();
auto nowCLI = System::DateTime::Now;
auto const milliSecsUntilT =
std::chrono::duration_cast<std::chrono::milliseconds>(tCPP - nowCPP).count();
auto tCLI = nowCLI.AddMilliseconds(milliSecsUntilT);
return tCLI;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.