[Python-Dev] proposal: add basic time type to thestandardlibrary

M.-A. Lemburg mal@lemburg.com
Sun, 10 Feb 2002 19:16:05 +0100

Stephan Richter wrote:
> > > * Intervals can be added or subtracted from themselves and the types
> > > above.
> > > DateInterval
> > > TimeInterval
> > > DateTimeInterval
> > > TimeStampInterval
> >
> >Intervals are a bad idea.
> Why? They are the same as your Deltas. Interval is the more common term I
> think, therefore I chose it. Maybe having a Time/Date/DateTime{Interval} is
> too much and they should be really one. So you would have DateTimeInterval
> and TimeStampInterval for the same reasons I describe below.

As I explained my reply, most of these intervals are not needed 
as *base types*. You can easily model them on top of the two
types I have in mxDateTime. Some may not like this model because it
comes from a more mathematical point of view, but in reality it
works quite nicely and simplifies the API structure significantly.

A time interval is basically just an amount of seconds, nothing more.
There's no need to have 4 different types to wrap a single 
double ;-)
> On the other hand Java does not seem to implement intervals at all, which I
> think is a bad idea, since RDBs support it.
>  >>> import DateTime
>  >>> DateTime.parseInterval('6 mins 3 secs') # DateTime.DateTimeInterval is
> the default
> 6 minutes 3 seconds
>  >>> DateTime.parseInterval('50 secs 3 millis',
> type=DateTime.TimeStampInterval) # returns ticks
> 50.003
> I still think that many types are a good thing; it leaves the developer
> with choice. However the module should be smart and hide some of the choice
> from you, if you are a beginner. For example I imagine this to work:
>  >>> import DateTime
>  >>> date = DateTime.parseDateTime('2.1.2001')
>  >>> type(date).__name__
> Date
>  >>> time = DateTime.parseDateTime('12:00:00')
>  >>> type(time).__name__
> Time
>  >>> datetime = DateTime.parseDateTime('2.1.2001 12:00:00')
>  >>> type(datetime).__name__
> DateTime

Just think of all the possible combinations you have in operations
like '+', '-' and comparisons. You don't want to go down this 
> >You really only need two types: one referencing fixed points in
> >time and another one for storing the delta between two such
> >fixed points. Everything else can be modeled on top of those
> >two.
> Well yes, but this is a reason why I have such a hard rime to get
> mxDateTime into Zope. Your module is well suited for certain tasks, but not
> everybody wants to use mxDateTime for Date/Time manipulation. 

Uhm, where did you get the impression that I want all the world
to use mxDateTime :-? I wrote it for use in mxODBC since at the time
there was no DateTime type around which could handle dates prior
to 1970. As a result, mxDateTime was written to provide everything
you need for database interfacing. That's also the reason why there
is no time zone support in mxDateTime's base types: databases
don't have time zone support built into their date/time types
either (and for a good reason: time zones are better handled at
application level).

> So, saving
> components of a date is for some uses much better than saving ticks and
> vice versa. I also talked with Jim Fulton about it, and he agrees that
> there is a need for more than one Date/Time type. However it should be easy
> of course to convert between both, the Timestamp and the DateTime type.

That's why mxDateTime provides so many interfaces to other forms
of storing and reading date/time values, e.g. COMDate, ticks, 
doubles, tuples, strings, various scientific formats, in two 
different calendars etc.
> Here are some more examples:
>  >>> import DateTime
>  >>> date = DateTime.parseDateTime('2.1.2001')
>  >>> type(date).__name__
> Date
>  >>> stamp = DateTime.TimeStamp(date)
>  >>> type(stamp).__name__
> TimeStamp
> BTW, something I do not want to support is:
>  >>> import DateTime
>  >>> date = DateTime.DateTime('2.1.2001')
> Since putting parsing into the object itself is a big mess, as we noticed
> in the Zope 2.x DateTime implementation. I think there should be only two
> ways to initialize a DateTime object, one of which I showed above, which is
> responsible of converting TimeStamps to DateTimes (mmh, maybe that should
> be a module function as well). The other one is:
>  >>> import DateTime
>  >>> DateTime.DateTime(2001, 2, 3)
> February 3, 2001
>  >>> DateTime.DateTime('2001', '02', '03') # Of course it also supports
> strings here
> February 3, 2001
>  >>> DateTime.DateTime(2001, 2, 3, 12, 0)
> February 3, 2001 12:00:00
>  >>> DateTime.DateTime(2001, hour=12) # missing pieces will be replaced by
> 1 or 0
> January 1, 2001 12:00:00
>  >>> DateTime.DateTime(year=2001, month=2, day=3, hour=1,
>                  minute=2, second=3, millisecond=4, timezone=-6) # max
> amount of arguments
> February 3, 2001 01:02:03.004 -06:00

You really just want to support one way for the type constructor
(broken down numbers). All other possibilities can be had via 
factory functions.
> >Please have a look at mxDateTime. It has these two types and
> >much of what you described in your notes.
> I know mxDateTime very well and have even suggested before to make it the
> Zope DateTime module and even put it in the standard Python distribution.
> Here is the mail from the Zope-Coders list:
> http://lists.zope.org/pipermail/zope-coders/2001-October/000100.html. You
> can follow the thread to see some responses.
> Also, the list of notes was made from my experience working with
> mxDateTime, Zope DateTime and PostGreSQL Dates/Times. I know it was not
> complete, but it had some of the hotspots in it.
> >BTW, you wouldn't believe how complicated dealing with date
> >and time really is... ah, yes, and don't even think of ever
> >getting DST to work properly :-/
> Oh, I have seen and fixed the Zope DateTime implementation plenty and I
> have thought of the problem for 2.5 years now. The problem is that the US
> starts to use the German "." notation (as mentioned in my original mail)
> and other issues, which make it much harder. That is the reason why I want
> to build an ultra-flexible parsing engine. So you can do things like:
>  >>> import DateTime
>  >>> DateTime.parseDateTime('03/02/01', format=DateTime.ISO)
> February 1, 2003
>  >>> DateTime.parseDateTime('03/02/01', format=DateTime.US)
> March 2, 2001
>  >>> DateTime.parseDateTime('03.02.01', format=DateTime.US)
> March 2, 2001
>  >>> DateTime.parseDateTime('03/02/01', format=DateTime.GERMAN) # just in
> case Europe/Germany goes insane as well.
> February 3, 2001
> But by default:
>  >>> DateTime.parseDateTime('03/02/01')
> March 2, 2001
>  >>> DateTime.parseDateTime('03.02.01')
> February 3, 2001

You can do all this with Parser module in mxDateTime. It allows
you to specify a list of parsers to try and in which order
to try them. Chuck Esterbrook has kept me working on it for 
quite some time, so it should be very complete by now :-) 

For more specific (and strict) formats, there are two other 
modules ISO and ARPA which can handle the respective 
formats used in Internet standards.

Marc-Andre Lemburg
CEO eGenix.com Software GmbH
Company & Consulting:                           http://www.egenix.com/
Python Software:                   http://www.egenix.com/files/python/