This could be the inverse of Converting from struct timespec to std::chrono::?
I am getting my time as
const std::Chrono::CRealTimeClock::time_point RealTimeClockTime = std::Chrono::CRealTimeClock::now();
and I have to convert it to a struct timespec
.
Actually, I don't, if there is an altrerntive; what I have to do is get the number of seconds since the epoch and the number of nanoseconds since the last last second.
I chose struct timespec
becuase
struct timespec
{
time_t tv_sec; // Seconds - >= 0
long tv_nsec; // Nanoseconds - [0, 999999999]
};
The catch is that I need to shoehorn the seconds and nonseconds into uint32_t
.
I am aware theat there is a danger of loss of precision, but reckon that we don't care too much about the nanoseconds while the year 208 problem gives me cause for concern.
However, I have to bang out some code now and we can update it later if necessary. The code has to meet another manufacturer's specification and it is likely to take weeks or months to get this problem resolved and use uint64_t
.
So, how can I, right now, obtain 32 bit values of second and nanosecond from std::Chrono::CRealTimeClock::now()
?
CodePudding user response:
I'm going to ignore std::Chrono::CRealTimeClock::now()
and just pretend you wrote std::chrono::system_clock::now()
. Hopefully that will give you the tools to deal with whatever clock you actually have.
Assume:
#include <cstdint>
struct my_timespec
{
std::uint32_t tv_sec; // Seconds - >= 0
std::uint32_t tv_nsec; // Nanoseconds - [0, 999999999]
};
Now you can write:
#include <chrono>
my_timespec
now()
{
using namespace std;
using namespace std::chrono;
auto tp = system_clock::now();
auto tp_sec = time_point_cast<seconds>(tp);
nanoseconds ns = tp - tp_sec;
return {static_cast<uint32_t>(tp_sec.time_since_epoch().count()),
static_cast<uint32_t>(ns.count())};
}
Explanation:
I've used function-local using directives to reduce code verbosity and increase readability. If you prefer you can use using declarations instead to bring individual names into scope, or you can explicitly qualify everything.
The first job is to get
now()
from whatever clock you're using.Next use
std::chrono::time_point_cast
to truncate the precision oftp
toseconds
precision. One important note is thattime_point_cast
truncates towards zero. So this code assumes thatnow()
is after the clock's epoch and returns a non-negativetime_point
. If this is not the case, then you should use C 17'sfloor
instead.floor
always truncates towards negative infinity. I chosetime_point_cast
overfloor
only because of the [c 14] tag on the question.The expression
tp - tp_sec
is astd::chrono::duration
representing the time duration since the last integral second. This duration is implicitly converted to have units ofnanoseconds
. This implicit conversion is typically fine as all implementations ofsystem_clock::duration
have units that are eithernanoseconds
or coarser (and thus implicitly convertible to)nanoseconds
. If your clock tracks units ofpicoseconds
(for example), then you will need aduration_cast<nanoseconds>(tp - tp_sec)
here to truncatepicoseconds
tonanoseconds
precision.Now you have the
{seconds, nanoseconds}
information in{tp_sec, ns}
. It's just that they are still instd::chrono
types and notuint32_t
as desired. You can extract the internal integral values with the member functions.time_since_epoch()
and.count()
, and thenstatic_cast
those resultant integral types touint32_t
. The finalstatic_cast
are optional as integral conversions can be made implicitly. However their use is considered good style.