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

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;

Related

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

Initialize std::chrono::time_point variable with zero

I have a variable called last_timestamp_ which is declared as follows:
using TimePoint = std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<double>> TimePoint last_timestamp_
and I want to initialize it with zero, how do I do that? Thanks
using TimePoint = std::chrono::time_point<std::chrono::system_clock,
std::chrono::duration<double>>;
TimePoint last_timestamp_{};
It would actually work without the {} too, but imho it is better style to explicitly zero-initialize it.
You can read this two ways:
It internally sets the value of last_timestamp_ to 0.0s, or to its epoch.
It sets last_timestamp_ to 1970-01-01 00:00:00 UTC.
The reason you can say the second part is because it is a de-facto standard that all implementations track Unix Time with system_clock in C++11/14/17. For C++20 this industry practice has been officially specified.
Important note: This specification is strictly for time_points based on system_clock. One can not assume this epoch for all chrono time_points.
Presuming from the comments that your use looks like:
while (...)
{
if (std::chrono::system_clock::now() > last_timestamp_ + threshold)
{
// now() - last_timestamp_ > threshold
...
last_timestamp_ = std::chrono::system_clock::now();
}
};
Your first iteration will be true assuming threshold isn't larger than 51 years.
Just to future-proof your code, it's worth a comment:
TimePoint last_timestamp_{}; // 1970-01-01
Now if you change clocks for any reason, you know that you may have to revisit this initial value. For example on some platforms the epoch of file_clock will be far in the future, breaking this code if it switched to file_clock. C++20 offers syntax to make this initialization more explicit:
using namespace std::chrono_literals;
TimePoint last_timestamp_ = std::chrono::sys_days{1970y/1/1};
Now the comment is unnecessary.

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

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.

Get seconds since epoch in Linux

Is there cross-platform solution to get seconds since epoch, for windows i use
long long NativesGetTimeInSeconds()
{
return time (NULL);
}
But how to get on Linux?
You're already using it: std::time(0) (don't forget to #include <ctime>). However, whether std::time actually returns the time since epoch isn't specified in the standard (C11, referenced by the C++ standard):
7.27.2.4 The time function
Synopsis
#include <time.h>
time_t time(time_t *timer);
Description
The time function determines the current calendar time. The encoding of the value is unspecified. [emphasis mine]
For C++, C++11 and later provide time_since_epoch. However, before C++20 the epoch of std::chrono::system_clock was unspecified and therefore possibly non-portable in previous standards.
Still, on Linux the std::chrono::system_clock will usually use Unix Time even in C++11, C++14 and C++17, so you can use the following code:
#include <chrono>
// make the decltype slightly easier to the eye
using seconds_t = std::chrono::seconds;
// return the same type as seconds.count() below does.
// note: C++14 makes this a lot easier.
decltype(seconds_t().count()) get_seconds_since_epoch()
{
// get the current time
const auto now = std::chrono::system_clock::now();
// transform the time into a duration since the epoch
const auto epoch = now.time_since_epoch();
// cast the duration into seconds
const auto seconds = std::chrono::duration_cast<std::chrono::seconds>(epoch);
// return the number of seconds
return seconds.count();
}
In C.
time(NULL);
In C++.
std::time(0);
And the return value of time is : time_t not long long
The native Linux function for getting time is gettimeofday() [there are some other flavours too], but that gets you the time in seconds and nanoseconds, which is more than you need, so I would suggest that you continue to use time(). [Of course, time() is implemented by calling gettimeofday() somewhere down the line - but I don't see the benefit of having two different pieces of code that does exactly the same thing - and if you wanted that, you'd be using GetSystemTime() or some such on Windows [not sure that's the right name, it's been a while since I programmed on Windows]
The Simple, Portable, and Proper Approach
#include <ctime>
long CurrentTimeInSeconds()
{
return (long)std::time(0); //Returns UTC in Seconds
}