Convert a double to time point using std chrono library - c++

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

Related

time duration calculation since from Application start deploy/run to reach midnight 12 AM in C++

I have requirement like time period in seconds needs to be return from the function, since from Application is deployed to reach midnight 12:00 AM in GMT. since at 12:00AM some action needs to be taken in Application. I got to know what will be the time after 12 hours, but this will not give number of hours left to reach midnight 12 AM. can you help me what will be the correct solution.
#include <iostream>
#include <iomanip>
#include <ctime>
#include <chrono>
int main()
{
using namespace std::literals; // enables the usage of 24h, 1ms, 1s instead of
// e.g. std::chrono::hours(24), accordingly
const std::chrono::time_point<std::chrono::system_clock> now =
std::chrono::system_clock::now();
const std::time_t t_c = std::chrono::system_clock::to_time_t(now - 24h);
std::cout << "24 hours ago, the time was "
<< std::put_time(std::localtime(&t_c), "%F %T.\n") << std::flush;
const std::time_t t_c_12 = std::chrono::system_clock::to_time_t(now + 12h);
std::cout << "12 hours after, the time was "
<< std::put_time(std::localtime(&t_c_12), "%F %T.\n") << std::flush;
}
The answer is slightly different for C++17 and C++14 as the chrono tools continue to evolve to be easier to use.
First the C++17 solution:
#include <chrono>
#include <iostream>
using days = std::chrono::duration
<int, std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>>;
int
main()
{
using namespace std;
using namespace std::chrono;
auto now = time_point_cast<seconds>(system_clock::now());
auto tomorrow = ceil<days>(now);
cout << (tomorrow - now)/1s << '\n';
}
This prints out the number of seconds until the next 12:00am (00:00:00) UTC.
The first thing you should to do is create a custom duration days which is equal to 24 hours (or 86400 seconds if you prefer).
Next get the current time. Since you want the final answer to have a precision of seconds it makes sense to just truncate the precision of the current time to seconds up front.
The next step is to truncate the precision of now again, but to a precision of days, rounding partial days up as opposed to down. This is exactly what std::chrono::ceil does. The resulting time_point tomorrow points to the next upcoming 00:00:00 UTC, or to now if now is 00:00:00 UTC.
The difference between tomorrow and now is simply the number of seconds until the next 00:00:00 UTC.
Note that at no time is there any translation into local time since the the input (system_clock::now()1) and the output (00:00:00 UTC) are both in UTC (approximately GMT as stated in the question).
The expression (tomorrow - now)/1s simply converts the number of seconds between tomorrow and now into an integral type so that it can be printed as the number of seconds.
The C++14 solution:
In C++14, std::chrono::ceil does not yet exist. Here is how to supply it yourself:
template <class To, class Rep, class Period>
constexpr
inline
To
ceil(const std::chrono::duration<Rep, Period>& d)
{
auto t = std::chrono::duration_cast<To>(d);
if (t < d)
return t + To{1};
return t;
}
template <class To, class Clock, class FromDuration>
constexpr
inline
std::chrono::time_point<Clock, To>
ceil(const std::chrono::time_point<Clock, FromDuration>& tp)
{
using std::chrono::time_point;
return time_point<Clock, To>{ceil<To>(tp.time_since_epoch())};
}
The C++20 solution:
I know you didn't ask for this, but in C++20 you no longer need to convert to an integral type to stream durations out. You can just:
cout << tomorrow - now << '\n';
And the output will look something like:
77094s
Also in C++20 if you would prefer the output to be in another format, such as hh:mm:ss, you can:
cout << format("{:%T}", tomorrow - now) << '\n';
to instead get:
21:24:54
Also, you no longer need to define your own days duration type. std::chrono::days exists in C++20 and you can just use that.
1 In C++14 and C++17 the epoch of system_clock::now() isn't specified to be aligned with 00:00:00 UTC, but in practice, every implementation does so. In C++20 this existing practice is specified in the standard.

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;

How To Return Elapsed Time From steady_clock as a Primitive Data Type (double)

First and foremost, let me say that I just starting using this library yesterday, so my understanding of it is still fairly basic. I'm trying to capture the FPS of a vision processing program I'm creating and output it to a screen using the chrono library. In my case, I need to cast the elapsed time taken after I start a steady_clock to a double (or some other numerical typedef I could treat like a double). I looked through reference documentation and tried working with the duration_cast and time_point_cast functions, but neither of those seem to be what I'm looking for.
My question is; is there any way to simply cast the numerical value of a clock's current state in seconds to a primitive data type?
Any help would be appreciated.
Like this:
#include <chrono>
#include <iostream>
#include <thread>
int main()
{
using namespace std::literals;
// measure time now
auto start = std::chrono::system_clock::now();
// wait some time
std::this_thread::sleep_for(1s);
// measure time again
auto end = std::chrono::system_clock::now();
// define a double-precision representation of seconds
using fsecs = std::chrono::duration<double, std::chrono::seconds::period>;
// convert from clock's duration type
auto as_fseconds = std::chrono::duration_cast<fsecs>(end - start);
// display as decimal seconds
std::cout << "duration was " << as_fseconds.count() << "s\n";
}
example output:
duration was 1.00006s
You could do it using the duration::count function.
For example you could get the duration in the number of milliseconds, and then divide the count by 1000.0 to get the number of seconds as a double.

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.