Invalid universal time - why is year 1902 a limit? Can that be configured somehow?

I know it’s OS dependent thing, but I feel like many people here could help me to understand it better.

The thing is that calendar:universal_time_to_system_time({{1902,01,01}, {0,0,0}}) returns a valid result, but calendar:universal_time_to_system_time({{1901,12,31}, {23, 59,59}} (and all universal times below that) throws badarg with not a valid universal time.

Why is year 1902 a limit? Can that be configured somehow?

$ erl
Erlang/OTP 28 [erts-16.0.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1]

Eshell V16.0.2 (press Ctrl+G to abort, type help(). for help)
1> calendar:universal_time_to_system_time({{1901,12,31}, {23, 59,59}}).
-2145916801

So this is a question for your “OS”.

Sorry, but I made a mistake in the original post. It’s not universal_time_to_system_time, but universal_time_to_local_time

What may be the clue is that if calendar:universal_time_to_system_time({{1902,01,01}, {0,0,0}}) returns -2145916800 which is just slightly below minimal signed int32…

Turns out this is not OS dependent.

From the OTP sourcecode:

/* This is the earliest year we are sure to be able to handle
   on all platforms w/o problems */
#define  BASEYEAR       1902 
if (!(IN_RANGE(BASEYEAR, *year, INT_MAX - 1) &&

That’s interesting, seems like 32 bits when converting to seconds is not a limit because year can e.g. be 10000 which is out out of 32 bits when converted to seconds.

This was introduced 14 years ago with no information on why exactly that year is chosen…

I can’t guarantee info.. buut..

  • Standard Unix epoch is 1970

  • A signed 32-bit integer can hold about 136 years worth of seconds (roughly 68 years before and 68 years after 1970).

  • A 32-bit integer is a sequence of 32 ones or zeros. If it is “signed,” the first bit is used to indicate whether the number is positive or negative. This leaves 31 bits for the actual number.

    • 2^31 = 2,147,483,648

    • This means a signed 32-bit integer can count from -2,147,483,648 to +2,147,483,647.

    2. The Seconds-to-Years Conversion

    2.1 billion seconds in.. years is..

    • Seconds in a minute: 60

    • Seconds in an hour: 3,600

    • Seconds in a day: 86,400

    • Seconds in a year (average): 86,400 x 365.25 = 31,557,600

    If we divide the max capacity of our 31 bits by the seconds in a year:

    2,147,483,647 / 31,557,600 ~ 68.05 years.

  • 1970 - 68.05 = > 1901.95 , real close to 1902, easier to round up so it avoids overflows.

I won’t say that it is exactly the reason but the time aligns a little too nicely for it to be a coincidence.

1 Like