0

I am wrapping a C++ library with a C++/CLI interface, to be used by a .NET app.
One of the C++ methods return a std::chrono::steady_clock::time_point. I thought it is appropriate to returns a System::DateTime from the C++/CLI wrapper method. Thus the need to convert.

I am aware that if I had a system_clock::time_point,
I could have converted it to time_t as explained here: How to convert std::chrono::time_point to calendar datetime string with fractional seconds?.
Then I could have used DateTimeOffset.FromUnixTimeMilliseconds, and from it get a System::DateTime.
Another approach could have been to use time_since_epoch.
But neither to_time_t nor time_since_epoch are available for std::chrono::steady_clock (about time_since_epoch see: chrono steady_clock not giving correct result?).

However - I cannot change the C++ interface.
Also didn't manage to properly convert steady_clock::time_point to e.g. system_clock::time_point.

The solution I came up with:
I take current time from both std::chrono::steady_clock and System::DateTime, then calculate offset from the steady_clock::time_point, and finally apply this offset in reverse to the DateTime time. I calculate the offset in milliseconds, and since the precision I am interested in is of seconds, it works well.
This method is shown in the code below.

But it feels a bit awkward. It is also sensitive to the requested precision.

My question: can you suggest a better way to do the conversion ?

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;
}

Output example:

System::DateTime::Now (for debug): 23-May-22 16:41:04
System::DateTime (converted):      23-May-22 16:41:04

Note: I added the C++ tag because the question is not a pure C++/CLI issue. E.g. there might be a solution involving conversion between std::chrono clocks that will enable an easy further conversion to System::DateTime (as mentioned above regarding DateTimeOffset.FromUnixTimeMilliseconds).

wohlstad
  • 3,689
  • 2
  • 9
  • 24

0 Answers0