I was working with some POSIX APIs recently and needed to supply a timespec value. I primarily work with std::chrono types in C++ and was surprised that there were no (obvious) existing conversion methods. Below are a few utility functions that I came up with to handle common conversions.
Table of Contents
timespec Refresher
As a quick refresher, timespec is a type defined in the ctime header (aka time.h). The timespec type can be used to store either a time interval or absolute time. The type is a struct with two fields:
struct timespec {
time_t tv_sec;
long tv_nsec;
}
The tv_sec field represents either a general number of seconds, or seconds elapsed since 1970, and tv_nsec represents the count of nanoseconds.
Conversion Functions
A timespec can represent either an absolute time or time interval. With std::chrono, these are two separate concepts: std::chrono::duration represents an interval, while std::chrono::time_point represents an absolute time.
We need for four functions to convert between the two C++ time concepts and timespec:
timespectostd::chrono::durationstd::chrono::durationtotimespectimespectostd::chrono::timepointstd::chrono::time_pointtotimespec
timespec to std::chrono::duration
Converting from a timespec to a std::chrono::duration (nanoseconds below) is straightforward: we convert tv_sec to std::chrono::seconds and tv_nsec to std::chrono::nanoseconds, and then cast the result to our target return type, std::chrono::nanoseconds.
using namespace std::chrono; // for example brevity
constexpr nanoseconds timespecToDuration(timespec ts)
{
auto duration = seconds{ts.tv_sec}
+ nanoseconds{ts.tv_nsec};
return duration_cast<nanoseconds>(duration);
}
std::chrono::duration to timespec
Converting from std::chrono::duration to timespec is a two step process. First we capture the portion of the duration which can be represented by a round number of seconds. We subtract this count from the total duration to get the remaining nanosecond count.
Once we have the two components, we can create our timespec value.
using namespace std::chrono; // for example brevity
constexpr timespec durationToTimespec(nanoseconds dur)
{
auto secs = duration_cast<seconds>(dur);
dur -= secs;
return timespec{secs.count(), dur.count()};
}
timespec to std::chrono::timepoint
For the std::chrono::time_point examples, I’ve used the system_clock as the reference clock.
To convert a timespec value to std::chrono::time_point, we first use our timespecToDuration() function to get a std::chrono::duration. We then use a duration_cast to convert std::chrono::duration to our reference clock duration (system_clock::duration).
We can then create a std::chrono::time_point value from our std::chrono::system_clock::duration.
using namespace std::chrono; // for example brevity
constexpr time_point<system_clock, nanoseconds>
timespecToTimePoint(timespec ts)
{
return time_point<system_clock, nanoseconds>{
duration_cast<system_clock::duration>(timespecToDuration(ts))};
}
std::chrono::time_point to timespec
To convert from a std::chrono::time_point to timespec, we take a similar approach to the std::chrono::duration conversion.
First we capture the portion of the duration which can be represented by a round number of seconds. We subtract this count from the total duration to get the remaining nanosecond count.
Once we have the two components, we can create our timespec value.
using namespace std::chrono; // for example brevity
constexpr timespec timepointToTimespec(
time_point<system_clock, nanoseconds> tp)
{
auto secs = time_point_cast<seconds>(tp);
auto ns = time_point_cast<nanoseconds>(tp) -
time_point_cast<nanoseconds>(secs);
return timespec{secs.time_since_epoch().count(), ns.count()};
}
Bonus: timeval conversions
Another common time structure with POSIX systems is timeval, which is defined in the sys/time.h. This type is very similar to timespec:
struct timeval
{
time_t tv_sec;
suseconds_t tv_usec;
}
We can convert between timeval and std::chrono types in the same manner shown above, except std::chrono::microseconds is used in place of std::chrono::nanoseconds.
using namespace std::chrono; // for example brevity
constexpr microseconds timevalToDuration(timeval tv)
{
auto duration = seconds{tv.tv_sec} + microseconds{tv.tv_usec};
return duration_cast<microseconds>(duration);
}

“using std::chrono;” is wrong, it is “using namespace std::chrono;”