On my modern 64bit Mac, the date 1901-12-14 is the earliest accepted by the following command:
date -ju -f "%F" "1901-12-14" "+%s"
I checked the source for the macOS date
command here (Apple Open Source) and it is a failed mktime
call that gives date: nonexistent time
error for earlier dates.
I've looked over the source for mktime
here (Apple Open Source) and I think that its a integer representation issue, but I'm not sure.
How can I find or compute the accepted range of dates of the date
command (really of mktime
)?
And if I wanted to get the Unix time for a date that can't be represented by mktime
internals, what other libraries or functions can handle earlier dates?
The current macOS (OS X) implementation of mktime(3)
has a minimum supported Unix time of INT32_MIN
(-2147483648
). This is because localtime.c:2102
assumes the result will fit in a 32-bit integer if the value is less than INT32_MAX
:
/* optimization: see if the value is 31-bit (signed) */
t = (((time_t) 1) << (TYPE_BIT(int) - 1)) - 1;
bits = ((*funcp)(&t, offset, &mytm) == NULL || tmcomp(&mytm, &yourtm) < 0) ? TYPE_BIT(time_t) - 1 : TYPE_BIT(int) - 1;
Between 1901-12-14 and 1901-12-13 the Unix time dips below INT32_MIN
, requires more than 32 bits, and is still less than INT32_MAX
causing the function run out of bits
.
This is not much of an issue considering that values before the year 1900 are explicitly disallowed by localtime.c:2073
:
/* Don't go below 1900 for POLA */
if (yourtm.tm_year < 0)
return WRONG;
(POLA: Principle Of Least Astonishment)
Additionally, time_t
is not required to be signed.