Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting from struct timespec to std::chrono::?

Tags:

c++

time

chrono

I've got a stream of struct timespec values. I'd like to convert them to a native C++11 representation, but I'm totally turned around by chrono. What is the best destination and how to get there from a struct timespec or struct timeval since that is an easy transformation and micro seconds is good enough for these timings? I presume that I want to be getting to this, right? std::chrono::system_clock::time_point

In this case, the timespec is UNIX time from a GPS. And yes, they are using a 4 byte second (converted form signed in memory and then written as unsigned) that will get nailed by 2038.

For reference, I'll be adding this to the C++ reader for gsf

like image 284
Kurt Schwehr Avatar asked Jul 14 '15 14:07

Kurt Schwehr


1 Answers

Sometimes I see timespec and timeval used as durations, and sometimes I see them used as time points. You will have to know what kind of values you are holding. In <chrono> these two concepts are different types.

A duration is an amount of time: something you would measure with a stopwatch. Example durations are 2 minutes, 3 seconds, 4 hours, and 16 years.

A time point is a specific time: 2pm Jul 14, 2015 EDT, or 6 hours since I booted up my computer. A time point has an implied epoch associated with it. An epoch is just some mutually agreed upon origin with which you're measuring time from.

If your timespec holds a duration:

timespec ts = {3, 123};  // 3 seconds + 123 nanoseconds
auto d = std::chrono::seconds{ts.seconds}
       + std::chrono::nanoseconds{ts.nanoseconds};

If your timespec holds a time point, you have to know the epoch. It is likely that the epoch is 1970-01-01 00:00:00 UTC, neglecting leap seconds (this is Unix time). If so, you can put it into a std::chrono::system_clock::time_point. This type is not guaranteed to have this epoch, but every implementation does:

using namespace std::chrono;
system_clock::time_point tp{duration_cast<system_clock::duration>(d)};

where d is computed as above.

If you have a timeval, then use microseconds where I've used nanoseconds.

You can not portably use high_resolution_clock or steady_clock time_points because different implementations have different epochs for these types.

Also if you're using timeval, in practice the duration_cast becomes unnecessary as the duration d will implicitly convert to all implementations of system_clock::duration:

using namespace std::chrono;
system_clock::time_point tp{d};

If you aren't sure if you need the duration_cast or not, try it without. If it compiles, you don't need it. If you get a compile-time error, you do need it. It is needed when converting durations and there is not an exact conversion.

like image 121
Howard Hinnant Avatar answered Oct 22 '22 05:10

Howard Hinnant