How to represent dates before epoch as a UNIX timestamp

Wolfer picture Wolfer · Jul 29, 2015 · Viewed 18.5k times · Source

It occurred to me that I'm not aware of a mechanism to store dates before 1970 jan. 1 as Unix timestamps. Since that date is the Unix "epoch" this isn't much of a surprise.

But - even though it's not designed for that - I still wish to store dates in the far past in Unix format.
I need this for reasons.

So my question is: how would one go about making unix-timestamps contain "invalid" but still working dates? Would storing a negative amount of seconds work? Can we even store negative amounts of seconds in a unix-timestamp? I mean isn't it unsigned?

Also if I'm correct then I could only store dates as far back as 1901. dec. 13 20:45:52 could this be extended any further back in history by any means?

Answer

Basil Bourque picture Basil Bourque · Jul 29, 2015

Unix Time is usually a 32-bit number of whole seconds from the first moment of 1970 in UTC, the epoch being 1 January 1970 00:00:00 UTC. That means a range of about 136 years with about half on either side of the epoch. Negative numbers are earlier, zero is the epoch, and positive are later. For a signed 32-bit integer, the values range from 1901-12-13 to 2038-01-19 03:14:07 UTC.

This is not written in stone. Well, it is written, but in a bunch of different stones. Older ones say 32-bit, newer ones 64-bit. Some specifications says that the meaning is "implementation-defined". Some Unix systems use an unsigned int to extend only into the future past the epoch, but usual practice has been a signed number. Some use a float rather than an integer. For details, see Wikipedia article on Unix Time, and this Question.

So, basically, your Question makes no sense. You have to know the context of your programming language (standard C, other C, Java, etc.), environment (POSIX-compliant), particular software library, or database store, or application.

Avoid Count-From-Epoch

Add to this lack of specificity the fact that a couple dozen other epochs have been used by various software systems, some extremely popular and common. Examples include January 1, 1601 for NTFS file system & COBOL, January 1, 1980 for various FAT file systems, January 1, 2001 for Apple Cocoa, and January 0, 1900 for Excel & Lotus 1-2-3 spreadsheets.

Further add the fact that different granularities of count have been used. Besides whole seconds, some systems use milliseconds, microseconds, or nanoseconds.

I recommend against tracking date-time as a count-from-epoch. Instead use specific data types where available in your programming language or database.

ISO 8601

When data types are not available, or when exchanging data, follow the ISO 8601 standard which defines sensible string formats for various kinds of date-time values.

  • Date
    • 2015-07-29
  • A date-time with an offset from UTC (Z is zero/Zulu for UTC) (note padding zero on offset)
    • 2015-07-29T14:59:08Z
    • 2001-02-13T12:34:56.123+05:30
  • Week (with or without day of week)
    • 2015-W31
    • 2015-W31-3
  • Ordinal date (day-of-year)
    • 2015-210
  • Interval
    • "2007-03-01T13:00:00Z/2008-05-11T15:30:00Z"
  • Duration (format of PnYnMnDTnHnMnS)
    • P3Y6M4DT12H30M5S = "period of three years, six months, four days, twelve hours, thirty minutes, and five seconds"

Search StackOverflow.com for many more Questions and Answers on these topics.