64-bit time symbol handling (The GNU C Library)

#### D.3.1 64-bit time symbol handling in the GNU C Library ¶

With respect to time handling, GNU C Library configurations fall in two classes depending on the value of `__TIMESIZE`:

``__TIMESIZE == 32``

  These dual-time configurations have both 32-bit and 64-bit time support. 32-bit time support provides type `time_t` and cannot handle dates beyond Y2038. 64-bit time support provides type `__time64_t` and can handle dates beyond Y2038.

  In these configurations, time-related types have two declarations, a 64-bit one, and a 32-bit one; and time-related functions generally have two definitions: a 64-bit one, and a 32-bit one which is a wrapper around the former. Therefore, for every `time_t`-related symbol, there is a corresponding `__time64_t`-related symbol, the name of which is usually the 32-bit symbol’s name with `__` (a double underscore) prepended and `64` appended. For instance, the 64-bit-time counterpart of `clock_gettime` is `__clock_gettime64`.

``__TIMESIZE == 64``

  These single-time configurations only have a 64-bit `time_t` and related functions, which can handle dates beyond 2038-01-19 03:14:07 (aka Y2038).

  In these configurations, time-related types only have a 64-bit declaration; and time-related functions only have one 64-bit definition. However, for every `time_t`-related symbol, there is a corresponding `__time64_t`-related macro, the name of which is derived as in the dual-time configuration case, and which expands to the symbol’s name. For instance, the macro `__clock_gettime64` expands to `clock_gettime`.

  When `__TIMESIZE` is set to 64, the GNU C Library will also define the `__USE_TIME_BITS64` macro. It is used by the Linux kernel ABI to set the expected `time_t` size used on some syscalls.

  These macros are purely internal to the GNU C Library and exist only so that a single definition of the 64-bit time functions can be used on both single-time and dual-time configurations, and so that glibc code can freely call the 64-bit functions internally in all configurations.

Note: at this point, 64-bit time support in dual-time configurations is work-in-progress, so for these configurations, the public API only makes the 32-bit time support available. In a later change, the public API will allow user code to choose the time size for a given compilation unit.

64-bit variants of time-related types or functions are defined for all configurations and use 64-bit-time symbol names (for dual-time configurations) or macros (for single-time configurations).

32-bit variants of time-related types or functions are defined only for dual-time configurations.

Here is an example with `localtime`:

Function `localtime` is declared in `time/time.h` as

    extern struct tm *localtime (const time_t *__timer) __THROW;
    libc_hidden_proto (localtime)

For single-time configurations, `__localtime64` is a macro which evaluates to `localtime`; for dual-time configurations, `__localtime64` is a function similar to `localtime` except it uses Y2038-proof types:

    #if __TIMESIZE == 64
    # define __localtime64 localtime
    #else
    extern struct tm *__localtime64 (const __time64_t *__timer) __THROW;
    libc_hidden_proto (__localtime64)
    #endif

(note: type `time_t` is replaced with `__time64_t` because `time_t` is not Y2038-proof, but `struct tm` is not replaced because it is already Y2038-proof.)

The 64-bit-time implementation of `localtime` is written as follows and is compiled for both dual-time and single-time configuration classes.

    struct tm *
    __localtime64 (const __time64_t *t)
    {
      return __tz_convert (*t, 1, &_tmbuf);
    }
    libc_hidden_def (__localtime64)

The 32-bit-time implementation is a wrapper and is only compiled for dual-time configurations:

    #if __TIMESIZE != 64

    struct tm *
    localtime (const time_t *t)
    {
      __time64_t t64 = *t;
      return __localtime64 (&t64);
    }
    libc_hidden_def (localtime)

    #endif