c++timestandardsyear2038y2k

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


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++?


Solution

  • 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";