I have a program that uses time() and localtime() to set an internal clock, but this needs to be changed so that the internal clock is independent of the user and the "real" time. I need to be able to set any reasonable starting time, and have it count forward depending on a timer internal to the program. Any ideas on the best way to approach this? Here's the excerpt:
#define ConvertToBCD(x) ((x / 10) << 4) | (x % 10);
time_t tm;
time(&tm);
struct tm *tm_local= localtime(&tm);
tm_local->tm_year %= 100;
tm_local->tm_mon++;
timedata[0] = ConvertToBCD(tm_local->tm_year);
timedata[1] = ConvertToBCD(tm_local->tm_mon);
timedata[2] = ConvertToBCD(tm_local->tm_mday);
timedata[3] = (tm_local->tm_wday + 6) & 7;
if (!(TimeStatus & 0x02)) tm_local->tm_hour %= 12;
timedata[4] = ((tm_local->tm_hour < 12) ? 0x00 : 0x40) | ConvertToBCD(tm_local->tm_hour);
timedata[5] = ConvertToBCD(tm_local->tm_min);
timedata[6] = ConvertToBCD(tm_local->tm_sec);
A time_t, under POSIX complient systems, is just the number of seconds since the epoch, 1 Jan 1970 0:00:00.
Just add a (possibly negative) value to a time_t to change the time, ensuring that the value doesn't overflow, then use localtime as usual.
If you only need whole second resolution, then time() can be used; if you need sub-second resolution, use gettimeofday().
However, if you want to be able to control the values returned, then you will need to define yourself a surrogate for time() (or gettimeofday()). Most libraries are designed along the lines described in Plauger's The Standard C Library, and you can often provide a function called time() that behaves as you want, replacing the standard version. Alternatively, and more safely, you can revise your code to call a function of your own devising, perhaps called simulated_time(), where for production work you can have simulated_time() call the real time() (possibly via an inline function in both C99 and C++) but it can be your own version that schedules time to change as you need.
You don't need to alter your use of localtime(); it simply converts whatever time_t value you give it into a struct tm; you want it to give answers just as it always did.
The way I understand it is that you want an internal clock which gets updated according to the progress the real clock makes.
So then you would create something like this:
struct myTime
{
time_t userStart;
time_t systemStart;
time_t curTime;
};
void initTtime(struct myTime *t, time_t time)
{
t->userStart=time;
t->systemStart=time(NULL);
}
time_t getTime(struct myTime *t)
{
t->curTime = t->userStart + time(NULL)-t->systemStart;
return t->curTime;
}
so using initTime you set the current time you want to have, this gets linked to the system time at that moment in time. When you call getTime using that struct, it updates the starting point with the amount of time progressed. (Note, i haven't tested the code and you can either use the struct directly if you want).
For subsecond precision replace time() and time_t by the gettimeofday equivalent. And for conversion, ascii arting, breakdown to anything else than a second counter you can still use the unix function.
Related
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.
I fast read the C++ reference about new chrono classes but I found them a little bit complicated.
So, the question is, how to re-write this code in C++20, to get year, month, day, hour, minute, second?
Are there any changes? I ask because of this minor problem with std::localtime: It is thread-unsafe. tm will be destroyed after next call to std::localtime.
std::time_t t = std::time(nullptr);
std::tm *tm = std::localtime(&t);
int year = tm->tm_year + 1900;
int month = tm->tm_mon + 1;
int day = tm->tm_mday;
int hour = tm->tm_hour;
int minute = tm->tm_min;
int second = tm->tm_sec;
#include <chrono>
int
main()
{
using namespace std::chrono;
// Get a local time_point with system_clock::duration precision
auto now = zoned_time{current_zone(), system_clock::now()}.get_local_time();
// Get a local time_point with days precision
auto ld = floor<days>(now);
// Convert local days-precision time_point to a local {y, m, d} calendar
year_month_day ymd{ld};
// Split time since local midnight into {h, m, s, subseconds}
hh_mm_ss hms{now - ld};
// This part not recommended. Stay within the chrono type system.
int year{ymd.year()};
int month = unsigned{ymd.month()};
int day = unsigned{ymd.day()};
int hour = hms.hours().count();
int minute = hms.minutes().count();
int second = hms.seconds().count();
}
I've tried to explain what each line of code does with a comment. I'm happy to elaborate further if anything is not clear.
This is all threadsafe.
More information:
Another and perhaps even more concise way to compute now is:
auto now = current_zone()->to_local(system_clock::now());
This results in the exact same type and value for now.
I used zoned_time above because it is (in general) a higher-level abstraction than calling member functions of a time_zone directly. In both examples the type of now is a simple std::chrono::time_point that is offset from system_clock::time_point by the UTC offset associated with the time_zone at this point in time.
In contrast zoned_time carries much more information. For example it knows about:
The name of the time_zone.
The abbreviation for the time_zone at this point in time.
The UTC offset of the time_zone at this point in time, and subsequently can produce both the local time and the UTC equivalent time.
The valid range of the offset/abbreviation pair.
Therefore a zoned_time is much more flexible for jobs like formatting as it can display the abbreviation and/or the UTC offset. And a zoned_time can also be more easily used to find out the equivalent time in other time zones.
Nevertheless, all of that extra information isn't actually used in this simple example, and is thus why I'm exposing the alternative of calling the to_local() member function of time_zone directly.
For the simple case of finding the local time, both techniques have identical behavior and performance, so it comes down to a matter of readability for choosing the preferred approach.
This question is similar to the following:
convert epoch to time_t
Converting time_t to int
but I don't quite have my answer there.
If you want to get the current date/time you can call time(0) or time(NULL) like in the following standard example:
// current date/time based on current system
time_t now = time(0);
I want to define a function which will return a time_t and allows the client to pass an optional default return value in the event of an error. Further, I want to set a default on that "default" argument. This provides symmetry within a library I have with one-to-one counter parts across several languages, so I'm not looking to redesign all that.
My thought was to set the default return to the epoch. Then, a client could in theory easily evaluate that return, and decide that an epoch coming back was more than likely (if not always) an indication of it being invalid. I can think of some alternatives, but nothing clean, that also fits my existing patterns.
Is there a short and sweet way to make my function signature have a default value for this object equal to the epoch? For instance
...myfunc(...., const time_t &defVal=time(0) );
would be perfect if 0 meant the epoch rather than the current date/time!
The function std::time() returns the number of seconds since the epoch as a std::time_t. Therefore to find zero seconds after the epoch set std::time_t to zero:
std::time_t t = 0;
So you could do something like:
void myfunc(const std::time_t& defVal = 0)
What is wrong with using 0? (time_t)0 represents the epoch itself (if you want to find the actual epoch date/time, pass (time_t)0 to gmtime() or localtime()).
time_t myfunc(...., time_t defVal = 0 );
Or, you could use (time_t)-1 instead, which is not a valid time, as time() returns (time_t)-1 on error, and time_t represents a positive number of seconds since the epoch.
time_t myfunc(...., time_t defVal = (time_t)-1 );
Either way provides the user with something that is easily compared, if they don't provide their own default value.
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
}