簡體   English   中英

將 stable_clock::time_point (C++) 轉換為 System::DateTime (C++/CLI)

[英]Convert steady_clock::time_point (C++) to System::DateTime (C++/CLI)

我需要將C++ std::chrono::steady_clock::time_pointC++/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_ttime_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_clockSystem::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);
}

所做的具體更改是:

  1. 在另一個輔助函數中隱藏持續時間轉換和TimeSpan工廠函數調用的使用。 1
  2. 顛倒nowCPPtCPP的減法順序,以避免以后必須顛倒符號。
  3. const添加到具有本機類型且不會更改的局部變量。 遺憾的是,.NET 類型不是 const 正確的,因為const -ness 僅受 C++/CLI 編譯器的尊重,而不是編寫 .NET 庫的語言。
  4. 避免在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM