Date and Time#
LLVM-libc implements the C and POSIX date and time functions (gmtime,
mktime, etc.) using high-performance algorithms and a 64-bit time_t.
This page documents the design decisions and limitations of the implementation.
Calendar Model#
LLVM-libc uses the proleptic Gregorian calendar: the modern Gregorian leap-year rules (divisible by 4, except centuries, except quad-centuries) are extended to all dates, including those before the calendar’s adoption on October 15, 1582.
This is the model required by the C and POSIX standards. It means that dates
before 1582 do not correspond to historical Julian calendar dates. For
example, gmtime will report February 29 for the year 400 CE, even though
that date was reckoned differently under the Julian calendar in use at the
time.
Leap Seconds#
POSIX §4.16 defines each day as exactly 86 400 seconds. LLVM-libc follows
this convention: leap seconds are not represented and time_t values map
to UTC times that ignore leap-second insertions.
64-bit time_t#
LLVM-libc requires a 64-bit time_t. A 32-bit time_t is not
supported. This avoids the Year 2038 problem and provides a valid
range of approximately ±2 billion years from the Unix epoch (January 1, 1970).
Algorithms#
The date conversion functions use Ben Joffe’s “Very Fast 64-bit” date
algorithm, which replaces the traditional loop-based year/month/day extraction
with multiply-shift division (four multiplications, zero hardware divisions).
The inverse (mktime) path uses the companion inverse algorithm from the
same article series. Leap-year testing uses the Drepper–Neri–Schneider
algorithm (modulo 25 instead of modulo 100).
These algorithms are described in:
128-bit intermediate arithmetic is used for the multiply-shift steps. On
64-bit targets this maps to the native __uint128_t; on 32-bit targets
LLVM-libc’s software UInt<128> implementation is used, preserving
correctness at a modest performance cost.