5

Excerpted from the cppref:

Implementations in which std::time_t is a 32-bit signed integer (many historical implementations) fail in the year 2038.

However, the documentation doesn't say how to detect whether the current implementation is 2038-safe. So, my question is:

Is it guaranteed to be 2038-safe if sizeof(std::time_t) == sizeof(std::uint64_t) in C++?

xmllmx
  • 39,765
  • 26
  • 162
  • 323
  • 3
    (from : https://en.cppreference.com/w/cpp/chrono/c/time_t) *Although not defined, this is almost always an integral value holding the number of seconds (not counting leap seconds) since 00:00, Jan 1 1970 UTC, corresponding to POSIX time.* That's not a definition I'd like to build my software on, and prefer using std::chrono. I think your real question is: can we get away with compiling to 64bit to avoid having to refactor our code? My recommendation to that is write unit tests for your time handling stuff and test it specialy for dates after and time periods spanning the 2038 problem point. – Pepijn Kramer Jan 05 '22 at 09:04
  • Do you want to be compatible across platforms? If *not*, then read the docs of the relevant platform. – j6t Jan 05 '22 at 09:23

1 Answers1

1

Practically speaking yes. In all modern implementations in major OSes time_t is the number of seconds since POSIX epoch, so if time_t is larger than int32_t then it's immune to the y2038 problem

You can also check if __USE_TIME_BITS64 is defined in 32-bit Linux and if _USE_32BIT_TIME_T is not defined in 32-bit Windows to know if it's 2038-safe


However regarding the C++ standard, things aren't as simple. time_t in C++ is defined in <ctime> which has the same content as <time.h> in C standard. And in C time_t isn't defined to have any format

3. The types declared are size_t (described in 7.19);

clock_t

and

time_t

which are real types capable of representing times;

4. The range and precision of times representable in clock_t and time_t are implementation-defined

http://port70.net/~nsz/c/c11/n1570.html#7.27.1p3

So it's permitted for some implementation to have for example double as time_t and store picoseconds from 1/1 year 16383 BCE, or even a 64-bit integer with only 32 value bits and 32 padding bits. That may be one of the reasons difftime() returns a double

To check y2038 issue portably at run time you can use mktime

The mktime function returns the specified calendar time encoded as a value of type time_t. If the calendar time cannot be represented, the function returns the value (time_t)(-1).

http://port70.net/~nsz/c/c11/n1570.html#7.27.2.3p3

struct tm time_str;
time_str.tm_year   = 2039 - 1900;
time_str.tm_mon    = 1 - 1;
time_str.tm_mday   = 1;
time_str.tm_hour   = 0;
time_str.tm_min    = 0;
time_str.tm_sec    = 1;
time_str.tm_isdst = -1;
if (mktime(&time_str) == (time_t)(-1))
    std::cout << "Not y2038 safe\n";
phuclv
  • 37,963
  • 15
  • 156
  • 475