How can I get a high resolution time stamp as a double? - c++

I am trying to use the follow code:
std::chrono::high_resolution_clock::now();
to get a time stamp, but I need it as a double, but it isn't a support data type, auto works, but I cannot manipulate it.

Your "time stamp" is what the <chrono> library calls a time_point. A time_point is a collection of a clock, and duration. And a duration is a collection of a representation and period.
You have specified two out of these three:
clock == high_resolution_clock
representation == double
period == ?
Your period can be nano (ratio<1, 1000000000>), milli (ratio<1, 1000>), seconds (ratio<1>), minutes (ratio<60>) or any other rational relationship to seconds.
Let's say for example that you wanted a time stamp using double as the representation and seconds as the period. This would look like this:
using clock = std::chrono::high_resolution_clock;
using dsec = std::chrono::duration<double>;
using tps = std::chrono::time_point<clock, dsec>;
tps tp = clock::now();
The time_point emitted by high_resolution_clock::now() will implicitly convert to your time_point using a representation of double and a period of ratio<1>. It will hold fractional seconds since the epoch of high_resolution_clock.
In general, because your destination type has a floating point representation, all time_point source types will implicitly convert to it. To convert in the reverse direction, you would need to use std::chrono::time_point_cast<some-duration>(source-time_point).
If instead you wanted to hold double-based nanoseconds, that would look like:
using clock = std::chrono::high_resolution_clock;
using dns = std::chrono::duration<double, std::nano>;
using tpns = std::chrono::time_point<clock, dns>;
tpns tp = clock::now();
As a guideline, I recommend using either system_clock or steady_clock, but not high_resolution_clock. Use system_clock if your time_point needs to have some relationship with the civil calendar, or needs to maintain meaning across processes. Use steady_clock if your time_point is used only across short durations within the same process.
high_resolution_clock is (de-facto) always an alias to either system_clock or steady_clock. So you might as well use one of the latter, and know what you're getting.
using clock = std::chrono::system_clock;
using dsec = std::chrono::duration<double>;
using tps = std::chrono::time_point<clock, dsec>;
tps tp = clock::now();

std::chrono::high_resolution_clock::now() returns an std::time_point<std::chrono::high_resolution_clock>. Here, you can choose whether you want to express this time point in nanoseconds, microseconds, milliseconds, and so on, using a std::chrono::duration, and ultimately convert this to a double:
std::chrono::time_point<std::chrono::high_resolution_clock> tp = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::micro> dur = tp;
double micros = dur.count();
Here you can replace std::micro with whatever resolution you desire.

Related

How to cast a double into std::chrono::milliseconds

I am using boost::asio::steady_timer m_timer and if I am not mistaken, in order to call m_timer.expires_after(expiration_time_ms);, expiration_time_ms should be a std::chrono::milleseconds variable.
Nevertheless, in my case, I have the expiration time as a double. I would like to know if it is possible to cast a double into std::chrono::milliseconds
The aim is to call
void
setExpirationTime(my_casted_double) {
boost::asio::steady_timer m_timer;
m_timer.expires_after(my_casted_double)
}
One nice trick is to multiply your values with chrono literals:
using namespace std::chrono_literals;
double time = 82.0;
auto t_82ms = time * 1ms;
std::this_thread::sleep_for(t_82ms);
It also works the other way around:
double time = t_82ms / 1s; // time == 0.082
m_timer.expires_after will accept any duration which is convertible to boost::asio::steady_timer::duration it doesn't need to be std::chrono::milliseconds (and if you don't want to discard the fractional milliseconds from your duration you shouldn't be converting to std::chrono::milliseconds).
You can convert your double into a std::chrono::duration as follows:
double milliseconds = 0.1;
std::chrono::duration<double, std::milli> chrono_milliseconds{ milliseconds };
chrono_milliseconds can't however be passed automatically into expires_after as there is no automatic conversion from floating point durations to integer ones. You can fix this with a std::chrono::duration_cast:
m_timer.expires_after(
std::chrono::duration_cast<boost::asio::steady_timer::duration>(chrono_milliseconds));

Why does chrono::system_clock returns microseconds whereas clock_gettime returns nanoseconds

std::chrono::system_clock::time_since_epoch().count() gives me a result in microseconds.
I want the current time in nanoseconds. But I can't use high_resolution_clock because on my system it is an alias on steady_clock (the monotonic clock).
I know my system is nanoseconds capable, because if I use clock_gettime(CLOCK_REALTIME, &ts) I am getting a correct nanosecond-resolution epoch time.
How can I tell std::chrono to use the nanosecond resolution? I'd like to avoid using clock_gettime and stick to the cpp wrapper.
How can I tell std::chrono to use the nanosecond resolution?
This sounds like a good use for writing your own custom clock. It is much easier than it sounds:
#include <time.h>
#include <chrono>
struct my_clock
{
using duration = std::chrono::nanoseconds;
using rep = duration::rep;
using period = duration::period;
using time_point = std::chrono::time_point<my_clock>;
static constexpr bool is_steady = false;
static time_point now()
{
timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts))
throw 1;
using sec = std::chrono::seconds;
return time_point{sec{ts.tv_sec}+duration{ts.tv_nsec}};
}
};
Just have your now() call clock_gettime with CLOCK_REALTIME. Then package up the return in a chrono::time_point with nanoseconds resolution.
Warning, I just tried this on macOS and called now() twice in a row. It printed out the same number of nanoseconds each time. And there's no way that the call is executing in under a nanosecond. So I'm getting nanosecond precision, but not nanosecond accuracy.
If you would like my_clock to participate in the C++20 std::chrono::clock_cast facility (as suggested by Nicol Bolas
in the comments below), add these two static member functions to my_clock:
template<typename Duration>
static
std::chrono::time_point<std::chrono::system_clock, Duration>
to_sys(const std::chrono::time_point<my_clock, Duration>& tp)
{
return std::chrono::time_point<std::chrono::system_clock, Duration>
{tp.time_since_epoch()};
}
template<typename Duration>
static
std::chrono::time_point<my_clock, Duration>
from_sys(const std::chrono::time_point<std::chrono::system_clock, Duration>& tp)
{
return std::chrono::time_point<my_clock, Duration>{tp.time_since_epoch()};
}
Now you can say things like:
cout << clock_cast<system_clock>(my_clock::now()) << '\n';
You will also be able to clock_cast to or from all other C++20 and custom clocks that participate in the clock_cast facility.
I am getting a correct nanosecond-resolution epoch time.
Are you? clock_gettime is required to return a time in nanoseconds, regardless of what clock you're accessing. This doesn't mean that CLOCK_REALTIME actually provides this resolution. It may internally only have microsecond resolution and expresses nanoseconds by multiplying by 1000.
By contrast, the actual resolution of a chrono clock is specified by the implementation. It is not a mandated part of the UI; it can vary from system to system and from clock to clock. So if a particular implementation's system_clock::period is in microseconds, then that is all the resolution the implementation is willing to claim to provide.
Maybe the implementation could provide more resolution, but if it could, it would probably say so. So if it doesn't, then that means the implementation doesn't feel comfortable claiming to provide more resolution.
However, if you feel that clock_gettime really does provide better resolution (rather than simply giving more digits), you can just use that. In C++20, system_clock is explicitly UNIX time. As such, if you have a time in nanoseconds, you can convert it to a time_point<system_clock, nanoseconds>:
namespace chrono = std::chrono;
...
using nano_sys = chrono::time_point<chrono::system_clock, chrono::nanoseconds>;
auto sys_tp_ns = nano_sys(chrono::nanoseconds(time_in_nanoseconds));
First of all, mind you that on GCC+libstc++ std::chrono is just a thin wrapper of syntax sugar around clock_gettime(). You are talking about the same thing here. std::chrono uses clock_gettime().
system_clock::time_point
system_clock::now() noexcept
{
timespec tp;
clock_gettime(CLOCK_REALTIME, &tp);
return time_point(duration(chrono::seconds(tp.tv_sec)
+ chrono::nanoseconds(tp.tv_nsec)));
}
Source: https://code.woboq.org/gcc/libstdc++-v3/src/c++11/chrono.cc.html
(above code was cleaned up)
So the precision is there, you just need to retrieve it in nanoseconds with
uint64_t utc_now_nanos() {
std::chrono::steady_clock::time_point tp = std::chrono::steady_clock::now();
return std::chrono::time_point_cast<std::chrono::nanoseconds>(tp).time_since_epoch().count();
}

Convert a double to time point using std chrono library

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

Time-stamping using std::chrono - How to 'filter' data based on relative time?

I want to time-tag a stream of data I produce, for which I want to use std::chrono::steady_clock.
These time-stamps are stored with the data ( as array of uint64 values?), and I will later need to process these time-stamps again.
Now, I haven't been using the std::chrono library at all so far, so I do need a bit of help on the syntax and best practices with this library.
I can get & store values using:
uint64_t timestamp = std::chrono::steady_clock::now().time_since_epoch().count();
but how do I best:
On reading the data create a timepoint from the uint64 ?
Get the ticks-per-second (uint64) value for the steady_clock?
Find a "cut-off" timepoint (as uint64) that lies a certain time (in seconds) prior a given timepoint?
Code snippets for the above would be appreciated.
I want to combine the three above essentially to do the following: Having an array of (increasing) time-stamp values (as uint64), I want to truncate it such that all data 'older' than last-time-stamp minus X seconds is thrown away.
Let's have a look at the features you might use in the cppreference documentation for chrono.
First off, you need to decide which clock you want to use. There is the steady_clock which you suggested, the high_resolution_clock and the system_clock.
high_resolution_clock is implementation dependent, so let's put this away unless we really need it. The steady_clock is guaranteed to be monotonic, but there is no guarantee of the meaning for the value you are getting. It's ideal for sorting events or measuring their intervals, but you can't get a timepoint out of it.
On the other hand, system_clock has a meaning, it's the UNIX epoch, so you can get a time value out of it, but is not guaranteed to be monotonic.
To get the period (duration of one tick) of a steady_clock, you have the period member:
auto period = std::chrono::steady_clock::period();
std::cout << "Clock period " << period.num << " / " << period.den << " seconds" << std::endl;
std::cout << "Clock period " << static_cast<double>(period.num) / period.den << " seconds" << std::endl;
Assuming you want to filter events that happened in the last few seconds using steady_clock values, you first need to compute the number of ticks in the time period you want and subtract it from now. Something along the lines of:
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t t_c = std::chrono::system_clock::to_time_t(now - std::chrono::seconds(10));
And use t_c as cutoff point.
However, do not rely on std::chrono::steady_clock::now().time_since_epoch().count(); to get something meaningful - is just a number. The epoch for the steady_clock is usually the boot time. If you need a time, you should use system_clock (keeping in mind that is not monotonous).
C++20a introduces some more clocks, which are convertible to time.
As it took me far too long to figure it out from various sources today, I'm going to post my solution here as self-answer. ( I would appreciate comments on it, in case something is not correct or could be done better.)
Getting a clock's period in seconds and ticks-per-second value
using namespace std::chrono;
auto period = system_clock::period();
double period_s = (double) period.num / period.den;
uint64 tps = period.den / period.num;
Getting a clock's timepoint (now) as uint64 value for time-stamping a data stream
using namespace std::chrono;
system_clock::time_point tp_now = system_clock::now();
uint64 nowAsTicks = tp_now.time_since_epoch().count();
Getting a clock's timepoint given a stored uint64 value
using namespace std::chrono;
uint64 givenTicks = 12345; // Whatever the value was
system_clock::time_point tp_recreated = system_clock::time_point{} + system_clock::duration(givenTicks);
uint64 recreatedTicks = tp_now.time_since_epoch().count();
Assert( givenTicks == recreatedTicks ); // has to be true now
The last ( uint64 to timepoint ) was troubling me the most. The key-insights needed were:
(On Win10) The system_clock uses a time-resolution of 100 nanoseconds. Therefore one can not directly add std::chrono::nanoseconds to its native time points. (std::chrono:system_clock_time_point)
However, because the ticks are 100's of nanoseconds, one can also not use the next higher duration unit (microseconds) as it cannot be represent as an integer value.
One could use use an explicit cast to microseconds, but that would loose the 0.1us resolution of the the tick.
The proper way is to use the system_clock's own duration and directly initialize it with the stored tick value.
In my search I found the following resources most helpful:
Lecture of Howard Hinnant on YouTube - extremely helpful. I wish I would have started here.
cppreference.com on time_point and duration and time_since_epoch
cplusplus.com on steady clock and time_point
A nice place to look as usual is the reference manual :
https://en.cppreference.com/w/cpp/chrono
In this case you are looking for :
https://en.cppreference.com/w/cpp/chrono/clock_time_conversion
Since really you are using a clock with "epoch" 1/1/70 as origin and ms as unit.
Then just use arithmetic on durations to do the cutoff things you want :
https://en.cppreference.com/w/cpp/chrono/duration
There are code examples at bottom of each linked page.

Difference between two nanosecond chrono::time_points, but in seconds?

I have a timestamp (nanoseconds since epoch):
uint64_t ts = .....;
and I'd like to check whether it is more than 5 seconds older than the current system time.
So I need to convert the timestamp to, a time_point? and then subtract this from the current time (in nanoseconds), checking whether its value is greater than chrono::duration::seconds(5)?
Got this so far:
const std::chrono::time_point tstp(std::chrono::duration_cast<std::chrono::nanoseconds>(rawNanos));
const std::chrono::time_point now = std::chrono::high_resolution_clock::now();
const bool old = now - tstp > std::chrono::seconds(5);
but struggling because of the constructor type for time_point.
You should not use high_resolution_clock for this. On some platforms high_resolution_clock counts time since the computer was booted up, not time since the Unix epoch.
Although not specified by the standard, the de facto standard is that on all platforms, system_clock counts time since the Unix epoch.
I find it handy to first declare a templated type alias that is a time_point based on system_clock, templated on duration. This makes it easy to create a time_point of any precision that counts time since the Unix epoch:
template <class D>
using sys_time = std::chrono::time_point<std::chrono::system_clock, D>;
Given that:
uint64_t ts = 1235;
using namespace std::chrono;
const bool old = system_clock::now() >
sys_time<nanoseconds>{nanoseconds{ts}} + seconds{5};
In C++14 you'll be able to write:
const bool old = system_clock::now() >
sys_time<nanoseconds>{nanoseconds{ts}} + 5s;