Home > Net >  Converting from std::chrono:: to 32 bit seconds and nanoseconds?
Converting from std::chrono:: to 32 bit seconds and nanoseconds?

Time:03-12

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 of tp to seconds precision. One important note is that time_point_cast truncates towards zero. So this code assumes that now() is after the clock's epoch and returns a non-negative time_point. If this is not the case, then you should use C 17's floor instead. floor always truncates towards negative infinity. I chose time_point_cast over floor only because of the [c 14] tag on the question.

  • The expression tp - tp_sec is a std::chrono::duration representing the time duration since the last integral second. This duration is implicitly converted to have units of nanoseconds. This implicit conversion is typically fine as all implementations of system_clock::duration have units that are either nanoseconds or coarser (and thus implicitly convertible to) nanoseconds. If your clock tracks units of picoseconds (for example), then you will need a duration_cast<nanoseconds>(tp - tp_sec) here to truncate picoseconds to nanoseconds precision.

  • Now you have the {seconds, nanoseconds} information in {tp_sec, ns}. It's just that they are still in std::chrono types and not uint32_t as desired. You can extract the internal integral values with the member functions .time_since_epoch() and .count(), and then static_cast those resultant integral types to uint32_t. The final static_cast are optional as integral conversions can be made implicitly. However their use is considered good style.

  • Related