[DB-SIG] Standardized Date-Time class

Jeffrey Jacobs timelord@user2.mnsinc.com
Wed, 10 Dec 1997 01:30:47 -0500 (EST)



On Tue, 9 Dec 1997, Mike Meyer wrote:

> > >  2. Support subtraction of date-times, and addition and=20
> > 
> >         I think the general idea that time is actually two concepts, Time and =
> > TimeSpan, may be the best way of looking at this, and since the way =
> > Times are stored may not necessarily be in Seconds since some standard =
> > Epoch
> 
> It's really only one concept - TimeSpan. A Time is just a TimeSpan
> since some standard Epoch. Representing the span as a number of
> seconds is easy and has some obvious advantages, but it has serious
> disadvantages as well. Since time is easier to type than timespan,
> I'll use that instead.

	Well, if we do store time as really a TimeSpan from some epoch,
then I can see your point, but from an interface point of view (and
remembering that storing an absolute time as such a TimeSpan offset is
only a suggestion for internal storage, and wouldn't necessarily have to
be the case), there is a strong difference between 61,292,782,211,360
milliseconds and Wednesday, 10 December 1997 4:50:11.360 UTC, or even 11
O'Clock and 11 Hours.  What does it mean to add 1 January to 7 September? 
Although as a general rule, times very close to 0 will probably be
TimeSpans, if I have that value stored and then forget what my variable
actually represents, my program could end up telling me it's Monday 1
January 1 AD 00:01:45.000 UTC.  Although a good programmer will not make
that mistake, it's nice knowing that the structure of the language won't
let you make the mistake anyway.  Thus, I really do feel a strong
proponent of the separation of time and span. 

> > >  6. Handle all dates in the Gregorian calendar.  (e.g. there should
> > >     not be problems storing dates from the 18th or 21st centuries.)
> >         As I said above, supporting non-Gregorian calendars may be made =
> > optional, but the Gregorian module should be loaded with the TimeModule, =
> > and therefore support of arbitrary Gregorian dates should be feasible.
> 
> Is it going to be Gregorian all the way back, or is it going to
> convert to Julian at some point in the past? That conversion is recent
> enough to effect events of historical interest, not having happened
> until this century in some countries.

	I have thought about this, and think that the only complete
solution to this problem is to create an Historical Calendar, which does
not include the 10 days from 5 to 15 October in 15?? when Pope Gregory
changed the calendar from the Julian model, and would use the Julian model
for dates before then.  However, as this makes things rather complicated,
and internally I would still suggest storing Time as a TimeSpan relative
to a *projected* Gregorian epoch, as if the Gregorian Calendar had been
used from 1 January 1 AD, support for pre-Gregorian dates would not be
built into the default Gregorian module.  However, since one could simply
load the Julian calendar and input a date using that interface, which
would then internally store it in the Gregorian TimeSpan form, the problem
becomes one of knowing what is the calendar you are inputting, which I
think in most cases will be known.
	Another problem with the idea of a Historical Calendar module is
that around 8 BC, due to problems with the Roman Government not keeping
proper track of the leap years, Caesar Augusta decreed that the years 8 BC
to 8 AD should not be leap years.  Thus, Calculating 29 February 4 AD,
although valid in the Julian and Gregorian calendar modules, would be
historically non-existent.  And certainly the Romans were measuring their 
years in years since the founding of Rome, not in years before the 
approximate birth of Christ.  (How would they know?)

> > >  9. Support for daylight-savings time.
> >         Another issue which may be important is that in the US, the rules for =
> > when DST begins I believe were changed from beginning the last Sunday in =
> > April to the current rules in 1987, so what do we calculate for the Time =
> > in mid April in the US before 1987?  Could TimeZones have more than one =
> > set of Daylight Savings rules depending on the year being calculated?
> 
> That's not the only time that they were changed in the US. And the US
> isn't the only place they've changed.

	Agreed.  This is a can of worms, and I wouldn't suggest 
supporting retro-fitted DST for every single region of the world.  
Projecting the current rules to any year, future or past should be the 
priority.  Worrying about how governments have changed how they calculate 
DST should be secondary.

> >         What I'm getting at here, is if we are going to support Universal Time =
> > from 5 billion BC to 1 billion AD or what have you, we will have to =
> > replace the C-Library TimeZone routines with something more robust.  I'm =
> > currently examining the GNU implementation of TimeZones and I may =
> > elaborate on this in a later post.
> 
> I don't know who's C library routines you're using, but the ones
> shipped as part of most Unix sytsems are pretty robust. I haven't
> checked the GNU version, but I suspect that they're based on the code
> that Sun released to the public in '87, which is what most Unix
> systems use. These include the ability to externally specify TZ tables
> that vary from year to year & locale, and manage to capture such
> oddities as Arizona not doing DST at all, and Hawaii having one day of
> DST in 1933.

	Yes.  The first implementation I examined was a commercial
implementation from a certain omnipresent software entity that will
hopefully get it's but kicked by the US Federal Government, but that's
another story.  I have been able to examine the GNU implementation of
tzset(), and realize that the full interpretation of the TZ environment
variable is more complicated than is implemented in the first version I
studied.  Basically, TZ has the following form: 

sss[+/-][hh[:mm[:ss]]][lll[+/-][hh[:mm[:ss]]][{d,Jd,Mm.w.d}[/hh[:mm[:ss]]]][,[{d,Jd,Mm.w.d}[/hh[:mm[:ss]]]]]]

{Phew!}

Where, sss = The 3-character abbreviation for the local Time Zone,

hh = hour
mm = minute
ss = second

The first [+/-][hh[:mm[:ss]]] is the offset from UTC for this Time Zone. 
If the sign is excluded, it is assumed to be negative, i.e. American Time. 

lll = The 3-character abbreviation for the Daylight Savings Time.  If lll
is not present, this Time Zone has no Daylight Savings time. 

This is followed by the offset from UTC for the DST of this Time Zone,
which is the Standard Time offset + 1 hour if it is not present.

This is optionally followed by the beginning and ending times of Daylight
Savings Time, respectively.  The first argument of the DST dates is in one
of three formats: 

d -- The number of days since 1 January of this year (1 January = 0)

Jd -- The Julian date: 1 January = J1, and 29 February = J59, regardless
of leap year.  Thus J60 always represents 1 March, and to calculate the
offset from 1 January, one must subtract 1 from Jd in Leap years and
before 1 March, and subtract 2 in standard years from 1 March on.

Mm.w.d -- The week of the change over: m is the month, w is the week (1 =
first, 4 = fourth, 5 = last), and d is the day of the week (0 = Sunday),
thus M4.1.0 would be the first Sunday in April, the default value for the
beginning of DST if none is given.  The last Sunday in October (M10.5.0)
is the default for the last day of DST. 

Finally, following the day specification is the time of day of the change
over, in the same format as the bias.  This defaults to 2 am in both
dates. 

	Thus, it should be possible to calculate the local DST using the
information in the TZ environment variable, if it exists, though it will
probably not on most Windows systems, as these tend to rely on the Win32
APIs.  Also, converting from local time to some other Time Zone should be
supported, and thus a database of known Time Zones would be a nice feature
of the new Time module, supporting both the 3-character Time Zone names as
well as the full-names, of which I have a list of 51 standard Time Zone 
settings, as I mentioned before.

		Be Seeing You,

		Jeffrey.


_______________
DB-SIG  - SIG on Tabular Databases in Python

send messages to: db-sig@python.org
administrivia to: db-sig-request@python.org
_______________