blob: 9d960a66981ff7a86561c74fbd625aac2cae8c0c [file] [view]
(date_and_time)=
# 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](https://en.wikipedia.org/wiki/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](https://en.wikipedia.org/wiki/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 DrepperNeriSchneider
algorithm (modulo 25 instead of modulo 100).
These algorithms are described in:
* [Very Fast 64-bit Date Algorithm](https://www.benjoffe.com/fast-date-64)
* [Inverse Date Algorithm](https://www.benjoffe.com/fast-date#inverse)
* [Fast Leap-Year Check](https://www.benjoffe.com/fast-leap-year#drepper-neri-schneider)
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.