[Zope3-dev] Can we remove ZopeLegacy for now?

Guido van Rossum guido@python.org
Fri, 15 Mar 2002 16:48:25 -0500


[Patrick O'Brien]
> Aren't the number of ways to calculate this a finite set? Maybe I'm
> just being stubborn out of ignorance. But I just can't see why the
> complexity can't be reduced to a small number of cases. Then we
> either pick the single case that we want to support (which, like you
> say, won't please everyone) or we have some way to toggle the
> calculation among the 3 or 4 cases and please everyone. If people
> deal with this issue in real life, on paper and in their heads, why
> can't we deal with it in a datatype?

tzinfo objects support all the cases you need.

> Would it help any to store the basic timezone (25 timezones that
> ignore DST, like GMT) separate from some kind of DST boolean/offset
> (assuming DST is always a one hour offset)? So we would never store
> "EDT", we would instead store "EST" with DST as True, or as GMT-5
> with DST as True. Then local time would be the basic timezone plus
> the DST. Syntactic sugar-coating could display "EST" with DST == 1
> as "EDT".

Please don't.  You are making so many simplifying assumptions here
that don't match reality that you might as well abandon timezones
altogether. :-)

> The toggle then just becomes whether or not to include/exclude an
> extra hour in certain calculations where one datetime DST is False
> and the other's DST is True. Or when a datetime plus a delta results
> in a different DST than the original.

You'd have to know the DST regulations for each jurisdiction in the
world.  If you'd been following this from the start, you'd know that's
hopeless (one particular dataset pertaining to this is 12 Mb
compressed).

> I realize I know a lot less about this issue than I should.

That's unclear.  You don't know much about it, but knowing more about
it might just drive you insane -- it seems like every anal-retentive
person in the world has a vested interest in timekeeping algorithms. :-)

> And I apologize if it is annoying.

Merely amusing. :-)

> But I feel like the clock is ticking (no pun intended) and now is
> the time to be involved, before everything is decided. I'm doing my
> best to research the issue and I'm serious about writing unit tests
> for any prototypes. If anyone can point me to more material I should
> be looking at I will be glad to do so. Thanks for listening.

You'll get three types, probably:

date       Keeps dates only, using an idealized ("proleptic")
           Gregorian calendar.

datetime   A subclass of date that adds time of day, recorded as
           "hh:mm:ss.micros", but no timezone info.  IOW, naive time.

datetimetz A subclass of datetime that adds an optional timezone info
           object.  If the tzinfo object is None, this behaves
           identical to naive datetime.

The tzinfo object should have at least the following methods:

  tz.tzoffset(dt)   given a datetime object, returns the timezone
                    offset in seconds east of UTC (negative west of
                    UTC) corresponding to that date and time

  tz.tzname(dt)     given a datetime object, returns the timezone
                    *name* to be used corresponding to that date and
                    time

Note that the dt argument is passed so that a tzinfo object can have a
different name and offset when DST is in effect, e.g. EST/EDT.
Obviously some tzinfo objects may ignore this.  Sample tzinfo classes:

class UTC:
    "UTC"
    def tzoffset(self, dt):
        return 0
    def tzname(self, dt):
        return "UTC"

class FixedOffset:
    "Fixed offset from UTC"
    def __init__(self, offset, name):
        self.__offset = offset
        self.__name = name
    def tzoffset(self, dt): return self.__offset
    def tzname(self, dt): return self.__name

import time
class LocalTime:
    "Local time as defined by the operating system"
    def _isdst(self, dt):
        t = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second,
             -1, -1, -1)
        # XXX This may fail for years < 1970 or >= 2038
        t = time.localtime(time.mktime(t))
        return t.tm_isdst > 0
    def tzoffset(self, dt):
        if self._isdst(dt):
            return -time.timezone
        else:
            return -time.altzone
    def tzname(self, dt):
        return time.tzname[self._isdst(dt)]

It would be easy enough to write classes representing specific
timezones using the rules spelled out in
http://webexhibits.org/daylightsaving/g.html

But I propose that that is up to the user.

--Guido van Rossum (home page: http://www.python.org/~guido/)