I need to convert C++ std::chrono::steady_clock::time_point
to C++/CLI System::DateTime
.
Background:
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
).