[DB-SIG] Re: ANN: DateTime type, version 0.1

M.-A. Lemburg lemburg@uni-duesseldorf.de
Sun, 14 Dec 1997 23:48:36 +0100


Magnus Lycka wrote:
> 
> At 22:40 1997-12-13 +0100, M.-A. Lemburg wrote:
> >t1 = maketime(1997,12,12)
> >t2 = maketime(1998,2,1)
> >d = DateTimeDelta(month=+2)
> 
> As I've written before one could also imagine this being the
> same class with an attribute indicating if the time is relative
> or not. Although that might not be a good idea since a absolute
> time can be expressed as a number relative to epoch, while +2
> months are sometimes the same as 2592000 seconds, and sometimes
> something else... Hm, two classes is probably better, they are
> after all more different than one having an epoch to relate to,
> and the other just lacking that reference.

Exactly.

> >(The two categories mutually exclude each other, e.g. if you use
> > month=+2,day=+2 you can't use absdate=+30)
> 
> I'm not sure I follow you here. What's the difference of day=+40
> and absdate=+40? Why should absdate be different from day?

You're right, absdate and date should work in the same way, just
as seconds and abstime should.

> Why not
> just add the bigger things first? 1900,1,1 + (year=+20,month=+30,
> day=+40) => 1922,8,10
> You might have a problem with which order you add things anyways,
> even if 'days' is small, so you have to make up your mind here.

Good point, order should be fixed in that way. The keywords
probably make things too complicated, so we could just provide
some convenient constructors:
- DateTimeDelta(year,month,day,hour,minute,second) [the real thing]
- DateDelta(year,month,day) (time part is 0)
- TimeDelta(hour,minute,second) (date part is 0)
All deltas are then applied from left to right.

> Not funny, but it's not our fault that the months have different lenghts.
> The way I see it absdate=+X (if I have understood what you meant by that
> term) is just the same as (year=0,month=0,day=+X). I think the user can
> handle year = month = 0 if that's what she wants.
> 
> >Questions:
> >- What is the outcome of maketime(1997,12,31) + d ? Since february
> >  doesn't have 31 days the new date is not well defined. I guess
> >  an exception should be raised to indicate this.
> 
> This is obviously something a lot of people have run into lots of
> times. Banks, authorities etc. Is there not any standard for handling
> this? I imagine this is something you want to handle differently in
> different occasions. Sometimes you will probably want it to be Feb 28,
> and sometimes Mar 3. This probably depends on whether you are paying or
> receiving money ;-) if it's an economical system for instance... I guess
> subclassing with the handling of this in the subclass is acceptable.
> 
> Another option would be to have some extra attribute in DateTimeDelta
> for longer or shorter spans. But maybe it's better to have a simpler and
> cleaner system and subclass to handle such things.

Simple and clean is always better :-)

> BTW, can anyone say something about how much an extra level of subclassing
> affects performance in Python? Since there is late binding, I imagine an
> extra level (or several) of subclassing will have a performance cost. Is
> this significant? (I understand this is not a clear yes/no question, but
> maybe someone can say something enlightening on that issue.)

It's no big deal if you don't do too much extensions (calling base
class methods in overridden methods). I usually apply the following
functions to my classes:

def freeze(thisclass):

    """ Add all known attributes of base classes to thisclass's
        attribute dictionary
        - does not overwrite attributes
    """
    dict = thisclass.__dict__
    if dict.has_key('__frozen__'):
        return
    dict.update(frozen(thisclass))
    dict['__frozen__'] = 1

def frozen(classinst):

    """ Return a dictionary that contains all known attributes
        of classinst
        - uses cached versions if available
    """
    dict = {}
    bases = list(classinst.__bases__)
    bases.reverse()
    for c in bases:
        otherdict = c.__dict__
        if not otherdict.has_key('__frozen__'):
            frozendict = frozen(c)
        else:
            frozendict = otherdict
        dict.update(frozendict)
    dict.update(classinst.__dict__)
    return dict

Once a class is frozen this way, it won't see any changes in
its base classes -- but since I don't use this Python feature
(on a regular basis) this doesn't bother me.

> >- What should t2 - t1 result in ? There are two options:
> >  a) it returns a relative result like DateTimeDelta(year=+1,month=-10,
> >     day=-11)
> >  b) it returns an absolute difference, DateTimeDelta(absdate=+51)
> >  I think arithmetic should always use option b). Option a) could
> >  be returned by a special reldifftime() function.
> >- Is there a need for addition of deltas ?
> >- Would having seperate types for the two flavors (relative and
> >  absolute) be a better approach. [actually while writing this, I
> >  tend to think so].
> 
> Hm... My thought was initially that for instance
> >>> t1 = maketime(1997,12,12,12,45,50)
> >>> t2 = maketime(1997,12,12,09,32,55)
> >>> diff = t2 - t1 # 11575 seconds
> would come out like
> >>> print diff
> 3 hours 12 minutes 55 seconds
> rather than 3,13,-5 or 11575. Naturally this fails when we come to
> months... :-( I suppose b) is the right way to do it.

Ah yes, I haven't though about that yet: how should deltas be
stringified ? strftime() is probably not usable since I don't
think it handles negative dates/times.

Two other things:

While fixing mxODBC to use the new type I stumbled into a
dynamic linking problem: it seems that the DateTime type
must be statically linked to the interpreter, since
all other modules using it must reference the same type
object to be able to recognize it.

Also, how should TIMEs be treated ? I am currently using
a DateTime(1,TIME in seconds) instance, but that prevents
calcualtions like:

today = maketime(1997,12,13)
c.execute("select time from timetable where date=?",(today,))
time = c.fetchone()[0]

print today + time
[TypeException]

Daytime is obviously a relative term, so it should probably
also be handled as (positive) DateTimeDelta (not having any
date part of course).

-- 
Marc-Andre Lemburg

PS: I consider all this as brainstorming, so feel free to
comment or propose other ways :-)


_______________
DB-SIG  - SIG on Tabular Databases in Python

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