将steady_clock::time_point(C++)转换为System::DateTime(C++/CLI)



我需要将C++std::chrono::steady_clock::time_point转换为C++/CLISystem::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 steady_clock未给出正确结果?)。

但是,我无法更改C++接口
也未能将steady_clock::time_point正确转换为例如system_clock::time_point

我提出的解决方案:
我从CCD_ 15和CCD_,则从CCD_ 17计算偏移,并最终以与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-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;
}

相关内容

  • 没有找到相关文章

最新更新