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++?
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
andtime_t
are implementation-defined
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 typetime_t
. If the calendar time cannot be represented, the function returns the value(time_t)(-1)
.
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";