[Python-Dev] functions exposed by datetime (original) (raw)

Tim Peters tim@zope.com
Wed, 15 Jan 2003 15:42:13 -0500


[Manuel Garcia, VP MIS]

The more I read about "datetime", I am beginning to realize that like "mxDateTime", it is a needlessly awkward to use for people who want to cheaply turn a calendar date into a 32 bit integer, and back again. (an integer suitable for doing date arithmetic, of course)

I think you should try reading the modules' documentation next .

for example: 2/28/2004 38045 2/29/2004 38046 3/1/2004 38047 3/2/2004 38048

from datetime import date date(2004, 2, 29).toordinal() 731640 date(2004, 3, 1).toordinal() 731641 date.fromordinal(731640) datetime.date(2004, 2, 29) date.fromordinal(731641) datetime.date(2004, 3, 1)

No matter how complete "datetime" turns out to be, you will have thousands of programmers that will have to code their own company's fiscal calendar anyway. So it makes sense to have cheap access to date arithmetic logic.

You do.

(I work for a manufacturing company, our fiscal months and years always begin on a Sunday, fiscal years are exactly 52 or 53 weeks long, and the length of a given year is determined as much by the tax code as by the positions of the earth and sun.)

Sure.

And what is day zero? Who cares?

In datetime, day 1 is 1/1/1, in the proleptic Gregorian calendar. The module docs say more about that.

... Besides date arithmetic, there are other reasons to make conversion between dates and integers very cheap. 32 bit integers obviously are easy to store, hash perfectly,

So do date objects.

can be quickly put into bins with use of "bisect",

So can date objects directly.

and they make calculations that loop over every day in a month or year a simple loop over a range(x,y).

There are many ways to do this, and I expect you're making life too difficult if you keep converting to and from integers by hand. Like

x = some starting date in 2003
aweek = datetime.timedelta(weeks=1)
while x.year == 2003:
    do something with x
    x += aweek

This is cheap.

The hashing is the biggest concern. If I understand correctly, Guido said hash for datetime objects was not straightforward, because the same day can have more than one representation. I am constantly using a "date" for part of a dictionary key.

A datetime.date object is basically a 4-byte string, and is no more difficult or expensive to hash than the string "date". A datetime object is more complicated, if its tzinfo member isn't None. Then hashing has to take the time zone information into account, as different datetime objects with non-None tzinfo members can represent the same time in UTC, and so compare equal, and so must have the same hash codes.

Sourceforge is gagging right now, so I cannot confirm what is in "datetime", but I never heard any mention of cheap conversion of dates into integers.

You can browse the module docs online at python.org too, via the "development version" link on the doc page.

My current fiscal calendar code uses mktime, localtime, int(round(x + (y - z) / 86400.0)), and prayer. Currently the program is swamped by I/O, so this is good enough, and I can't justify installing "mxDateTime" on all the client machines. But I wouldn't mind using a simple, cheap built-in.

Date ordinals are cheaper under mxDateTime, because it stores datetimes internally as a pair

(day ordinal as an integer, # of seconds into the day as a double)

datetime objects store year, month, day, hour, minute, second and microsecond as distinct internal fields, for efficient field extraction and exact (no floating point rounding surprises) datetime arithmetic. Conversion to and from day ordinals requires non-trivial runtime conversion code in datetime, but it runs at C speed and I expect you'll never notice it.