Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a Delphi EncodeDate/DecodeDate function version that can handle B.C. dates?

The Delphi functions EncodeDate/DecodeDate seem to be able to handle only dates after 1.1.0001. Are there some implementations of EncodeDate/DecodeDate that can handle B.C. tDateTime values?

like image 873
blerontin Avatar asked Jul 28 '11 09:07

blerontin


1 Answers

AFAIK TDateTime is a Windows base type, common to COM, Variants, DotNet and Delphi. Negative values can be used for dates before 1899.

But that is not so simple - since with negative values comes some trouble, as stated by this page:

The integral part is the date, the fraction is the time. Date.time. That's easy. Things get odd when the value is negative. This is on or before #12/30/1899#.

With modern dates time always runs forwards, as you would suspect. With negative historical dates time actually runs backwards! Midnight #1/1/1800# equals −36522, but noon #1/1/1800# is −36522.5 (less than midnight!) and one second before midnight is −36522.9999884259 (even less). At midnight the clock jumps forward to -36521, which equals #1/2/1800#. The decimal fraction still shows the time and the integral part is the date, but each second decrements the clock while each new day increments it, not just by 1, but by almost 2. Negative times are really counterintuitive.

To make things worse, time values for #12/30/1899# are ambigous in two ways. First, a time value without a date equals that time on #12/30/1899#. This means that 0.5 is either noon or noon on #12/30/1899#, depending on context. Zero is either midnight, #12/30/1899# or midnight #12/30/1899#. The other ambiguity is that all time values come in double for #12/30/1899#. 0.5 is noon #12/30/1899#, but -0.5 is noon #12/30/1899# as well. The integral part is the date, the fraction is the time. Another surprise is here: #12/30/1899 11:59:59 PM# - #12/29/1899 11:59:59 PM# = 2.99997685185185. Not 1, what you normally would expect for a 24-hour period. Be careful when working with historical dates.

To my knowledge, the current implementation of EncodeDate/DecodeDate will work, but you may go into troubles when working with negative or near to zero TDateTime values...

You should better use your own time format, e.g. ISO-8601 or a simple record as such:

TMyDateTime = packed record
  Year: SmallInt;
  Month: Byte;
  Day: Byte;
end;

And when computing things about duration or displaying date/time, you must be aware that "our time" is not continuous. So calculation using the TDateTime=double trick won't always work as expected. For instance, I remember that Teresa of Avila died in 1582, on October 4th, just as Catholic nations were making the switch from the Julian to the Gregorian calendar, which required the removal of October 5–14 from the calendar. :)

like image 83
Arnaud Bouchez Avatar answered Oct 07 '22 19:10

Arnaud Bouchez