How safe is it to assume that time_t is in seconds?

I do a lot of calculations over time, creating time objects relative to other time objects, adding seconds. The code should work on embedded devices and servers. Most documents say about time_t that it is some arithmetic type, usually saving time from the era. How safe is it to assume that time_t stores a few seconds after something? If we can assume that then we can just use addition and subtraction, rather than localtime , mktime and difftime .

So far I have solved the problem using constexpr bool time_tUsesSeconds , indicating whether it can be assumed that time_t uses seconds. If it doesn't wrap to take time_t in seconds, is there a way to automatically initialize this constant?

 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); } } 
+6
source share
5 answers

The fact that it is in seconds is determined by the POSIX specification , so if you code for POSIX-compatible environments, you can rely on it.

The C ++ standard also states that time_t must be an arithmetic type.

In any case, the unix synchronization system (the second since Epoch) is about to overflow in 2038. Therefore, it is very likely that prior to this implementation date, C ++ will be switched to data types other than int (either 64b int or a more complex data type). In any case, switching to 64b int would violate binary compatibility with the previous code (since it requires large variables), and everything should be recompiled. Using 32b opaque knobs will not break binary compatibility, you can change the base library and everything still works, but time_t will no longer be in seconds, it will be an index for the array once every few seconds. For this reason, he suggested using the functions you talked about to control the values ​​of time_t, and do not take anything at time_t .

+8
source

Instead of determining if time_t in seconds, since time_t is an arithmetic type, you can calculate the value of time_t , which represents one second, and work with it. This answer, which I wrote before , explains the method and has some reservations, here is an example code example ( bad_time() is a special class of exceptions):

 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 constant, and then just use it when you need a second time_t . I do not think it will work with constexpr .

+2
source

In the C standard or standard C ++ for units that time_t represents. To work with seconds in portable mode, you need to use struct tm . You can convert between time_t and struct tm with mktime and localtime .

0
source

My two cents: on Windows, it takes seconds over time , but the time it takes for one second to increase to the next is usually 18 * 54.925 ms, and sometimes 19 * 54.925. The reason for this is explained in this post .

0
source

(Answering my own question)

One answer suggests that as long as you use posix, time_t is in seconds, and arithmetic on time_t should work.

The second answer calculates time_t per second and uses this as a factor when performing arithmetic. But there are still some assumptions about time_t .

In the end, I decided that portability was more important; I don't want my code to fail on some embedded device. Therefore, I used the third method. It includes storing an integer representing the time since the program was launched. That is, I define

  const static time_t time0 = time(nullptr); static tm time0Components = *localtime(&time0); 

All time values ​​used throughout the program are integers, indicating the time difference in seconds from time0 . To go from time_t to these delta seconds, I use difftime . To get 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 you to make operations like + , - cheap, but returning to time_t is expensive. Please note that delta-time values ​​are meaningful only for the current program launch. Please also note that time0 Components must be updated when the time zone changes.

0
source

Source: https://habr.com/ru/post/956319/


All Articles