I'm trying to update the basic dev library of my project from C++98 to C++11.
In the dev library, there are many functions about time, such as
uint64_t getCurrentMSTime()
{
struct timeval stv;
gettimeofday(&stv, NULL);
uint64_t ms = stv.tv_sec ;
ms = ms * 1000 + stv.tv_usec / 1000;
return ms;
}
I'm trying to change it with std::chrono of C++11.
For now it seems that I have two choices, one is to return time_point, the other is to return immediately std::chrono::milliseconds::rep
std::chrono::time_point<std::chrono::system_clock> getCurrentTime1() {
return std::chrono::system_clock::now();
}
std::chrono::milliseconds::rep getCurrentTime2() {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
}
Well, I know that the first one is more flexible because it returns a time_point, which means that we can convert it into milliseconds, nanoseconds, seconds etc, whereas the second one is return only milliseconds.
But let's say that the developers use ONLY milliseconds so we can ignore the flexible issue.
In this case, which one is better?
BTW, the developers would do something like this: std::map<std::string, ???> mp;. So my code will decide the ??? part.
std::map<std::string, std::chrono::time_point<std::chrono::system_clock>> mp{std::string("abc"), getCurrentTime1()};
vs
std::map<std::string, std::milliseconds::rep> mp{std::string("abc"), getCurrentTime2()};.
Which one is better? Or are they almost the same?
I agree with the currently accepted answer that you should value type-safety, and not return an integral type. However I disagree that returning milliseconds is best.
Type safety applies to the difference between time points and time durations as well. For example it makes perfect sense to add two time durations. But it is nonsensical to add two time points, though you can subtract them yielding a time duration.
Since the meaning of getCurrentTime() is to return the current point in time, one should return a std::chrono::time_point. One can easily choose to return a time_point based on system_clock with milliseconds precision:
std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>
getCurrentTime()
{
return std::chrono::time_point_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now());
}
In C++20, there's a convenience type alias for this type to make it a little easier to spell. You could create such a type alias for yourself if you would like to get a head start on things:
std::chrono::sys_time<std::chrono::milliseconds>
getCurrentTime()
{
return std::chrono::time_point_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now());
}
Or you can create an even shorter name for use within your application, perhaps:
using MSTime = std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>;
...
MSTime
getCurrentMSTime()
{
return std::chrono::time_point_cast<MSTime::duration>(
std::chrono::system_clock::now());
}
You certainly don't want to throw away the type information that <chrono> offers. If you convert the time_point you get from the system clock into an integral value right away, you can equally well keep the legacy function as it is.
Instead, decide upfront whether you want to handle points in time relative to the epoch or not. The old function suggests that you want this, so your function should look like this;
std::chrono::milliseconds getDurationSinceEpoch()
{
return std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch());
}
But let's say that the developers use ONLY milliseconds so we can ignore the flexible issue
Don't. What you get is here is for free. Whenever this requirement changes, and some developer mixes getDurationSinceEpoch() return values with durations in whatever resolution, it becomes quite brittle. By baking the correct units into your functions, you guard against future bugs.
Last, you want your map to have this signature:
std::map<std::string, std::chrono::milliseconds>
Related
Let's say I have the following program to export an object to JSON:
struct MyChronoObject {
std::string name;
std::chrono::system_clock::time_point birthday;
MyChronoObject(const std::string name_) : name(name_) {
birthday = std::chrono::system_clock::now();
}
std::string toJSON1() {
std::string s = "{ \"name\": \"" + name + "\", \"birthday\": ";
s += std::to_string((birthday.time_since_epoch().count() / 1000000));
s += " }";
return s;
}
std::string toJSON2() {
std::string s = "{ \"name\": \"" + name + "\", \"birthday\": ";
s += std::to_string((birthday.time_since_epoch().count()));
s += " }";
return s;
}
void setBirthday(int birthday_in_seconds) {
// how do I properly cast this?
}
};
Which, for toJSON1(), has the output { "name": "Steve", "birthday": 16687719115 }
There are several problems with this code (which I will mention but will probably address them in separate threads), but first and foremost...
The number 16687747280 is not correct. It should be one digit shorter for seconds or 2 digits longer for milliseconds if I go by this: EpochConverter
Not dividing the the birthday by one million, toJSON2(), leads to a number that is one digit too long for microseconds and 2 digits too short for nanoseconds: 16687747280849928.
So which way would be correct (and most efficient) to store and convert the stored epoch time so that I can export it to something that can be used by Javascript?
Thank you in advance!
P.S.: Other questions that I have are:
How do I cast back a number that the C++ program receives from the frontend (like in setBirthday)?
Should I even store the date as chrono object if seconds are sufficient?
How do I add exactly one year so that I land on the same date (e.g. 25.1.2019 to 25.1.2020), considering things like leap years, etc.).
What about dates before 1970?
Note the default unit of std::chrono::system_clock is undefined. Instead of using birthday.time_since_epoch().count() / 1000000, you should cast the time unit to the appropriate unit for you:
std::chrono::duration_cast<std::chrono::seconds>(birthday.time_since_epoch())
.count()
This will give you the amount of second.
You might also use std::chrono::ceil<seconds>, std::chrono::floor<seconds>, std::chrono::round<seconds> for different rounding modes.
To cast from integer back to a time_point, you can do:
std::chrono::sys_time{std::chrono::seconds{birthday_in_second}};
or:
std::chrono::sys_time{std::chrono::milliseconds{birthday_in_millisecond}};
To add/subtract years, you can use:
auto now = std::chrono::system_clock::now();
auto today = std::chrono::year_month_day{std::chrono::floor<std::chrono::days>(now)};
auto today_10_years_ago = today - std::chrono::years{10};
And you can also use using namespace std::chrono::literals to write 10y instead of years{10}. *This is incorrect, see more information in the comment
Note today and today_10_years_ago are year_month_day object now. If you want a time_point with h/m/s information as well, you can do:
auto today_as_time_point = std::chrono::sys_days{today_10_years_ago};
auto time_only = today - now;
auto today_with_time_info = today_as_time_point + time_only;
Yes, the <chrono> library works with time before epoch.
By requirement, all predefined duration types up to chrono::hours are guaranteed to work in the range for at least ±292 years(in practice, many of them will still work in much larger ranges). And types greater than hour, ie. chrono::days, chrono::years are guaranteed for ±40000 years.
So if you know you are going to do something like now - years{1000}, it would be a good idea to convert now to a larger unit first.
I'm still a bit overwhelmed by the casting...
Part of the goal of the <chrono> library is to give high level access to time/date data while avoiding possible errors.
If you want to cast a more precise duration to a less precise duration, ie. from millisecond to second, you are forced to use an explicit cast or through roundings, which will avoid unintended truncation errors.
For more, you might search for Howard Hinnant's talk on the library.
... and extracting something like year out of it
Depends on your need, if your full goal was to serialize a date information, you might want to utilize std::format or {fmt} library to do it automatically:
auto now = std::chrono::system_clock::now();
std::cout << std::format("{:%Y}", now); // This will print only the year
Demo further utilizing formatting libraries. *Note {fmt} library is used as gcc haven't implemented the full std::format library.
duration.count() returns a number of ticks. Not seconds, nor microseconds, nor nanoseconds. Unless the tick period happens to be 1, 10⁻⁶, or 10⁻⁹ seconds.
You have to multiply that by the period, which is given in class attributes of your duration. Which in you case, depends on the clock type (all those are templates, and the period depend on the actual class)
One way is to cast the duration into a duration whose you know the period.
Like
std::chrono::duration_cast<std::chrono::seconds>(birthday.time_since_epoch()).count()
// Instead of birthday.time_since_epoch().count()
I want to start a clock at the beginning of my program and use its elapsed time during the program to do some calculations, so the time should be in a int, long or double format. For example i want to calculate a debounce time but when i try it like this i get errors because the chrono high resolution clock is not in an int, long or double format and therefore i can't subtract 50ms from that (my debounceDelay) or save that value to a double (my lastDebounceTime). Originally i had a working Arduino Game (Pong) with an LCD and i want to convert this into a C++ console application.
On the Arduino there was this function "millis()" that gave me the runtime in ms and this worked perfectly fine. I can't find a similar function for C++.
double lastDebounceTime = 0;
double debounceDelay = 50;
void Player1Pos() {
if ((std::chrono::high_resolution_clock::now() - lastDebounceTime) > debounceDelay) {
if ((GetKeyState('A') & 0x8000) && (Player1Position == 0)) {
Player1Position = 1;
lastDebounceTime = std::chrono::high_resolution_clock::now();
}
else if ((GetKeyState('A') & 0x8000) && (Player1Position == 1)) {
Player1Position = 0;
lastDebounceTime = std::chrono::high_resolution_clock::now();
}
}
I am very new to C++ so any help is greatly appreciated.
Thank you all!
I find the question misguided in its attempt to force the answer to use "int, long, or double". Those are not appropriate types for the task at hand. For references, see A: Cast chrono::milliseconds to uint64_t? and A: C++ chrono - get duration as float or long long. The question should have asked about obtaining the desired functionality (whatever the code block is supposed to do), rather than asking about a pre-chosen approach to the desired functionality. So that is what I will answer first.
Getting the desired result
To get the code block to compile, you just have to drop the insistence that the variables be "int, long, or double". Instead, use time-oriented types for time-oriented data. Here are the first two variables in the code block:
double lastDebounceTime = 0;
double debounceDelay = 50;
The first is supposed to represent a point in time, and the second a time duration. The C++ type for representing a point in time is std::chrono::time_point, and the C++ type for a time duration is a std::chrono::duration. Almost. Technically, these are not types, but type templates. To get actual types, some template arguments need to be supplied. Fortunately, we can get the compiler to synthesize the arguments for us.
The following code block compiles. You might note that I left out details that I consider irrelevant to the question at hand, hence that I feel should have been left out of the minimal reproducible example. Take this as an example of how to simplify code when asking questions in the future.
// Use the <chrono> library when measuring time
#include <chrono>
// Enable use of the `ms` suffix.
using namespace std::chrono_literals;
std::chrono::high_resolution_clock::time_point lastDebounceTime;
// Alternatively, if the initialization to zero is not crucial:
// auto lastDebounceTime = std::chrono::high_resolution_clock::now();
auto debounceDelay = 50ms;
void Player1Pos() {
if ((std::chrono::high_resolution_clock::now() - lastDebounceTime) > debounceDelay) {
// Do stuff
lastDebounceTime = std::chrono::high_resolution_clock::now();
}
}
Subtracting two time_points produces a duration, which can be compared to another duration. The logic works and now is type-safe.
Getting the desired approach
OK, back to the question that was actually asked. You can convert the value returned by now() to an arithmetic type (integer or floating point) with the following code. You should doubts about using this code after reading the comment that goes with it.
// Get the number of [some time units] since [some special time].
std::chrono::high_resolution_clock::now().time_since_epoch().count();
The time units involved are not specified by the standard, but are instead whatever std::chrono::high_resolution_clock::period corresponds to, not necessarily milliseconds. The special time is called the clock's epoch, which could be anything. Fortunately for your use case, the exact epoch does not matter – you just need it to be constant for each run of the program, which it is. However, the unknown units could be a problem, requiring more code to handle correctly.
I find the appropriate types easier to use than trying to get this conversion correct. Especially since it required no change to your function.
I'm using OpenCV to write a video file. For cv::VideoWriter to work correctly the call to the write() function has to happen exactly 30 times per second (for a 30fps video).
I found this code which uses the boost library to achieve this. I want to to the same but using std::chrono in my program. This is my implementation:
std::chrono::high_resolution_clock::time_point prev = std::chrono::high_resolution_clock::now();
std::chrono::high_resolution_clock::time_point current = prev;
long long difference = std::chrono::duration_cast<std::chrono::microseconds>(current-prev).count();
while(recording){
while (difference < 1000000/30){
current = std::chrono::high_resolution_clock::now();
difference = std::chrono::duration_cast<std::chrono::microseconds>(current-prev).count();
}
theVideoWriter.write(frameToRecord);
prev = prev + std::chrono::high_resolution_clock::duration(1000000000/30);
difference = std::chrono::duration_cast<std::chrono::microseconds>(current-prev).count();
}
theVideoWriter.release();
I'm not sure if thats the correct way to do this or if there is a more efficient way. Is there anything better than casting the duration to long long difference?
There is a basic tenant to working with chrono, which goes something like:
If you use count(), and/or you have conversion factors in your
chrono code, then you're trying too hard.
This is not your fault. There really is no good chrono tutorial and that is my bad, and I've recently decided I need to do something about that.
In your case, I recommend rewriting your code along the lines of the following:
First create a duration unit which represents the period of your frame rate:
using frame_period = std::chrono::duration<long long, std::ratio<1, 30>>;
Now when you say frame_period{1}, that means exactly 1/30 of a second.
The next thing to note is that chrono comparisons are always exact, as long as you stay in the chrono system. count() is a "trap door" for escaping out of the chrono system. Only escape out when you have no other choice. So...
auto prev = std::chrono::high_resolution_clock::now();
auto current = pref;
// Just get the difference, and don't worry about the units for now
auto difference = current-prev;
while(recording)
{
// Find out if the difference is less than one frame period
// This comparison will do all the conversions for you to get an exact answer
while (difference < frame_period{1})
{
current = std::chrono::high_resolution_clock::now();
// stay in "native units"...
difference = current-prev;
}
theVideoWriter.write(frameToRecord);
// This is a little tricky...
// prev + frame_period{1} creates a time_point with a complicated unit
// Use time_point_cast to convert (via truncation towards zero) back to
// the "native" duration of high_resolution_clock
using hr_duration = std::chrono::high_resolution_clock::duration;
prev = std::chrono::time_point_cast<hr_duration>(prev + frame_period{1});
// stay in "native units"...
difference = current-prev;
}
theVideoWriter.release();
The comments above are overly verbose once you get chrono. There's more comment than code above. But the above just works as you intended, with no need for "escaping out" of the chrono system.
Update
If you would want to initialize difference such that the inner loop won't be executed the first time, you could initialize it to something just over frame_period{1} instead of to 0. To do this, the utilities found here come in handy. Specifically ceil:
// round up
template <class To, class Rep, class Period>
To
ceil(const std::chrono::duration<Rep, Period>& d)
{
To t = std::chrono::duration_cast<To>(d);
if (t < d)
++t;
return t;
}
ceil is a replacement for duration_cast that will round up when the conversion is inexact, as opposed to truncate towards zero. Now you can say:
auto difference = ceil<hr_duration>(frame_period{1});
And you are guaranteed that difference >= frame_period{1}. Furthermore, it is known in practice that the duration of high_resolution_clock is nanoseconds, thus you can deduce (or test) that difference is actually initialized to 33,333,334ns, which is 2/3 of a nanosecond greater than 1/30 of a second, which equals frame_period{1}, which equals 33,333,333+1/3ns.
I'm doing a lot of calculations with times, building time objects relative to other time objects by adding seconds. The code is supposed to run on embedded devices and servers. Most documentations say about time_t that it's some arithmetic type, storing usually the time since the epoch. How safe is it to assume that time_t store a number of seconds since something? If we can assume that, then we can just use addition and subtraction rather than localtime, mktime and difftime.
So far I've solved the problem by using a constexpr bool time_tUsesSeconds, denoting whether it is safe to assume that time_t uses seconds. If it's non-portable to assume time_t is in seconds, is there a way to initialize that constant automatically?
time_t timeByAddingSeconds(time_t theTime, int timeIntervalSeconds) {
if (Time_tUsesSeconds){
return theTime + timeIntervalSeconds;
} else {
tm timeComponents = *localtime(&theTime);
timeComponents.tm_sec += timeIntervalSeconds;
return mktime(&timeComponents);
}
}
The fact that it is in seconds is stated by the POSIX specification, so, if you're coding for POSIX-compliant environments, you can rely on that.
The C++ standard also states that time_t must be an arithmetic type.
Anyway, the Unix timing system (second since the Epoch) is going to overflow in 2038. So, it's very likely that, before this date, C++ implementations will switch to other non-int data types (either a 64-bit int or a more complex datatype). Anyway, switching to a 64-bit int would break binary compatibility with previous code (since it requires bigger variables), and everything should be recompiled. Using 32-bit opaque handles would not break binary compatibility, you can change the underlying library, and everything still works, but time_t would not a time in seconds anymore, it'd be an index for an array of times in seconds. For this reason, it's suggested that you use the functions you mentioned to manipulate time_t values, and do not assume anything on time_t.
If C++11 is available, you can use std::chrono::system_clock's to_time_t and from_time_t to convert to/from std::chrono::time_point, and use chrono's arithmetic operators.
If your calculations involve the Gregorian calendar, you can use the HowardHinnant/date library, or C++20's new calendar facilities in chrono (they have essentially the same API).
There is no requirement in standard C or in standard C++ for the units that time_t represents. To work with seconds portably you need to use struct tm. You can convert between time_t and struct tm with mktime and localtime.
Rather than determine whether time_t is in seconds, since time_t is an arithmetic type, you can instead calculate a time_t value that represents one second, and work with that. This answer I wrote before explains the method and has some caveats, here's some example code (bad_time() is a custom exception class, here):
time_t get_sec_diff() {
std::tm datum_day;
datum_day.tm_sec = 0;
datum_day.tm_min = 0;
datum_day.tm_hour = 12;
datum_day.tm_mday = 2;
datum_day.tm_mon = 0;
datum_day.tm_year = 30;
datum_day.tm_isdst = -1;
const time_t datum_time = mktime(&datum_day);
if ( datum_time == -1 ) {
throw bad_time();
}
datum_day.tm_sec += 1;
const time_t next_sec_time = mktime(&datum_day);
if ( next_sec_time == -1 ) {
throw bad_time();
}
return (next_sec_time - datum_time);
}
You can call the function once and store the value in a const, and then just use it whenever you need a time_t second. I don't think it'll work in a constexpr though.
My two cents: on Windows it is in seconds over time but the time it takes for one second to increment to the next is usually 18*54.925 ms and sometimes 19*54.925. The reason for this is explained in this post.
(Answering own question)
One answer suggests that as long as one is using posix, time_t is in seconds and arithmetic on time_t should work.
A second answer calculates the time_t per second, and uses that as a factor when doing arithmetic. But there are still some assumptions about time_t made.
In the end I decided portability is more important, I don't want my code to fail silently on some embedded device. So I used a third way. It involves storing an integer denoting the time since the program starts. I.e. I define
const static time_t time0 = time(nullptr);
static tm time0Components = *localtime(&time0);
All time values used throughout the program are just integers, denoting the time difference in seconds since time0. To go from time_t to this delta seconds, I use difftime. To go back to time_t, I use something like this:
time_t getTime_t(int timeDeltaSeconds) {
tm components = time0Components;
components.tm_sec += timeDeltaSeconds;
return mktime(&components);
}
This approach allows making operations like +,- cheap, but going back to time_t is expensive. Note that the time delta values are only meaningful for the current run of the program. Note also that time0Components has to be updated when there's a time zone change.
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
}