I have a double value that represents an epoch time but added the accuracy of a micro second. So a number like this:
double time_us=1628517578.547;
std::chrono::time_point time(time_us);
The above code doesn't;t work as I am getting the following error:
no instance of constructor "time_point" matches the argument list
I need to do this conversion to get the millisecond of the day (number of Milliseconds that passed from the last night).
I plan to use the following code to get the required millisecond:
double sysTOH=time.hour*3600+time.min*60+time.sec+time.usec*1e-6;
What is the best way to achieve this?
std::chrono::
is a lot to write everywhere, so I'm going to assume:
using namespace std::chrono;
time_point
is not a concrete type, it is a class template:
template<class Clock, class Duration = typename Clock::duration> class time_point;
This means that you have to supply at least the first template parameter, and in your case, it is best to supply the second as well.
Your input, time_ms
, has type double
, and represents a count of seconds
. So start by creating a type that matches that description:
using ds = duration<double>;
ds
is a duration
with a rep
of double
and a period
of ratio<1>
.
Now it is handy to use a little of C++20 <chrono>
. Don't worry, if you don't have C++20, there is a free, open-source, header-only preview of it that works with C++11/14/17.
sys_time<ds> time{ds{time_ms}};
sys_time
is a type alias supplied by "date/date.h" for the type:
time_point<system_clock, duration<double>>
I.e. a time_point
based on system_clock
using your custom duration
type ds
(double-based seconds
).
One first converts the raw double
to double
-based seconds
, and then to a time_point
based on those seconds
.
Next, it is best to convert to an integral-based time_point
to find the time since midnight. Your questions uses microseconds
and milliseconds
somewhat interchangeably. So I am going to assume milliseconds
for everything. Change to microseconds
if you need to.
auto tp = round<milliseconds>(time);
This takes the double-based time_point
and converts it to an integral-based time_point
that counts milliseconds
. round
is used to avoid round-off error associated with double-based representations. round
is part of C++17 and later, but "date/date.h" will supply it for you in C++11/14.
The type of tp
is time_point<system_clock, milliseconds>
.
Next it is convenient to truncate tp
to a precision of days
:
auto td = floor<days>(tp);
floor
is part of C++17 and later, but "date/date.h" will supply it for you in C++11/14. days
is a day-precision duration
. td
is simply a count of days since the Unix epoch, and has type time_point<system_clock, days>
.
One can also think of td
as a time point to the beginning of the day. So one can subtract it from tp
to get the "time of day", or "time since midnight" UTC:
auto tod = tp - td;
tod
has type milliseconds
is the value is the number of milliseconds
since midnight UTC. If you need midnight defined by some time zone, then there's a little more work to do to take the UTC offset into account. Your question is vague on this point.
Putting it all together:
#include "date/date.h"
#include <chrono>
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
double time_ms=1628517578.547;
using ds = duration<double>;
sys_time<ds> time{ds{time_ms}};
auto tp = round<milliseconds>(time);
auto td = floor<days>(tp);
auto tod = tp - td;
std::cout << "tod = " << tod << '\n';
}
Output:
tod = 50378547ms