Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing dates with more-than-4-digits years

I need a way to serialize and unserialize dates that are potentially far away in the past, for instance -10000

I first look at ISO8601, but it does not seem to support years with more than four digits. (Or at least, python libraries I tried don't.)

The different solutions I can think of:

  • change the year before serializing/deserializing, give it to the parsing/formatting library, and fix it back (sounds hacky)
  • define my own format, like year:month:day:hour:minute:second (that is reinventing the wheel, since I have to handle timezones, etc.)
  • Use a UNIX timestamp without bounds or something equivalent (may overflow in some programming languages, and still the timezone stuff)
  • Store dates before -9999 (or 0) differently than those after, since there was no timezone issue/leap years/… issue at that time. (two different formats at the same place)

Do you see any other way that would be better than these ones? Or recommand one of those?

like image 798
Valentin Lorentz Avatar asked Nov 10 '14 08:11

Valentin Lorentz


2 Answers

You could take a page from the astronomy people. Sky maps they account for long period precession of Earth's spin by establishing epochs. (The sky is different if you're looking now vs 10,000 BC.)

Create a new class that has an "epoch" number and a facade pattern of your current date class. The new class contains two private fields for epoch and internal-date. Your constructor sets epoch to (year div 10000), and instantiates the internal-date with (year modulo 10000). I hope rest of the facade pattern is as obvious as I think.

like image 117
StevePoling Avatar answered Oct 23 '22 02:10

StevePoling


ISO 8601 does support dates with more than 4 digits if, and only if, they are signed. The only PHP function I know of that supports this functionality is

DateTime::setISODate($Year, $WeekOffset, $DayofWeekOffset)

Obviously it's a pain to use because it requires calculating the offsets from perfectly good day/month pairs. That said, you should be able to create BC dates by signing the year with a '-'(minus sign).

Then you'd output the date with

DateTime::format("c")

In production this would look something like:

$date= new DateTime();

$date->setISODate(-100000,$WeekOffset, $DoWOs);

echo $date->format("c");
like image 34
Jonathan Bedder Avatar answered Oct 23 '22 00:10

Jonathan Bedder