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

Guido van Rossum guido@python.org
Sat, 16 Mar 2002 14:18:06 -0500


[Tim]
> Still, I don't imagine there's a DST situation in the world messier
> than Indiana's:
> 
>     [from http://www.mccsc.edu/time.html]
> 
>     76 counties (including state capital Indianapolis) are in the
>     Eastern Time Zone but do not change to Daylight time in April;
>     instead they remain on Standard Time all year long;
> 
>     11 counties -- six near Chicago, IL, and five near Evansville, IN,
>     are in the Central Time Zone and use both Central Standard and
>     Central Daylight;
> 
>     five other counties -- two near Cincinnati, OH, and three near
>     Louisville, KY -- are in the Eastern Time Zone but use both Eastern
>     Standard and Eastern Daylight
> 
> And I don't imagine anyone is going to write a tzinfo object any
> better at sorting out that mess than a struct tmx either: in some
> places in Indiana, "the time" depends on where you are, when you
> ask, which year you're asking about, and who you ask.  In addition,
> it appears US law and Indiana law disagree about the answers even
> so.

I don't see the mess, unless you make the mistake of thinking of
Indiana as one timezone.  Of course it isn't!  There are three
different timezones (using the definition of timezone as "a group of
clocks that show the same time, by agreement"): US/Eastern,
US/Central, and EST.

> > Tzinfo objects can solve these problems because you can write a
> > tzinfo object that implements any jurisdiction's timezone and DST
> > rules and history.
> 
> I see nothing to stop you from doing the same via routines
> manipulating a struct tmx, but with the latter's advantage of
> allowing to explicitly break out the three distinct customary
> adjustments to UTC (time zone, DST fiddling, and leap second
> fiddling).  The language itself says little about how these fields
> can be used.

Let me clarify what I meant by "you don't have enough information".
The struct tmx stores a "time zone" which is really an offset from
UTC, and a "DST offset".  Now suppose I present you with a time, say
March 16, 2002, 12:21:00, and I tell you the UTC offset (-5 hours) and
the DST offset (zero, meaning DST is not in effect on this date).  Now
let's try to do some date/time arithmetic.  What UTC offset and DST
are in effect exactly two months later?  Or exactly two months earlier?

- It could be US/Eastern, and two month later the UTC offset will be
  -4 hours and the DST will be 1 hour; two months earlier will be
  unchanged.

- It could be some place near the equator, and the UTC offset would
  remain -5 hours and the DST would remain unset throughout the year.

- It could be Chile; two months later would be -5 hours, two months
  earlier would be their DST, and so the offset would be -4 hours then.

Now, the tmx structure allows an extension, so an implementation could
hide additional information there, but I doubt that's what you were
referring to, and in any case a portable app can't rely on it.

In my design, however, the tzinfo object can implement any set of
rules you want; it has a defined interface (methods tzoffset(),
tzname(), and tzdst(), each taking a datetime instance).  How does that
work?  There are distinct tzinfo instances (or classes) that implement
the rules for Chile, US/Eastern, Equador, and so on.  There's no
single tzinfo object for US/Indiana; times in Indiana must somehow
choose the tzinfo object that applies to the county where the time is
taken.

> > See http://www.zope.org/Members/fdrake/DateTimeWiki/TimeZoneInfo
> 
> The base code

Exactly what base code?  You mean what we had before we dropped
tzoffset from the prototype implementation?

>               can't get in trouble because of this simply because
> our spec declines to say anything about what this number means,
> beyond that it's "seconds east of UTC".  I'm not sure that's
> enforcable-- or even meaningful --in the absence of other defined
> semantics.  It reads more like a hint about intent.

I don't understand what you're trying to say here.  But that may be no
more than fair: you probably don't understand what I had in mind for
the tzinfo object, because I haven't finished writing it up (still
haven't).

> This is similar to how struct tmx avoids trouble: lots of mechanism,
> little policy.  I personally find it very confusing to call a
> combined offset gimmick "a timezone", but so it goes (I was taught
> in grade school that timezones are roughly based on a grid spaced 15
> longitudinal degrees, and not even the Wisconsin legislature had the
> power to shift the state's position on the Earth at the same time it
> commanded the Sun to sleep an hour longer <wink>).

Yeah, you learn a lot of nonsense in grade school.  As became clear in
other messages in this thread, the word "timezone" means many things
to many people.

> Other confusions:
> 
> > datetimetz
> > A subclass of datetime that adds an optional timezone info object.
> > If the tzinfo object is None, this behaves identical to naive datetime.
> 
> datetimetz isn't mentioned again on this page.  In particular,
> there's nothing about how a datetimetz acts if its tzinfo object is
> not None.  There's also no way specified to ask a datetimetz what
> its timezone info object is.  IOW, so far it's got no defined
> semantics except in its degenerate (tzinfo is None) case.

Sorry, I meant that when you ask a datetimetz object for its UTC
offset (or maybe for a translation of its time to UTC), it calls its
tzinfo object's tzoffset() method.  And if you ask a datetimetz object
for its timezone name, it calls its tzinfo object's tzname() method.
Both passing itself as an argument, so the tzinfo object can make the
proper DST determination in case it knows about a specific DST
ruleset.  And I suppose if there's a use case for asking a datetimetz
object whether DST is in effect, that question, too, is passed on to
the tzinfo object.

> > 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
> 
> I believe we need to define a distinguished "I don't know" result,
> or explicitly allow that this operation may raise a specific
> exception in that case.

Absolutely.

> > tz.tzname(dt)
> > given a datetime object, returns the timezone name to be used
> > corresponding to that date and time
> 
> As above.
> 
> > Sample tzinfo classes:
> >
> >        class UTC:
> >            "UTC"
> >           def tzoffset(self, dt):
> >                return 0
> >           def tzname(self, dt):
> >                return "UTC"
> 
> I assume it's just as valid to define this as, e.g.,
> 
>         class UTC:
>             "UTC"
>            def tzoffset(self, dt):
>                 return -42137    # ONLY CHANGE IS HERE
>            def tzname(self, dt):
>                 return "UTC"
> 
> If it's not, scream at me, because then there's some hidden
> assumption about the relationship between naive time and UTC.  Or is
> the rest of the spec going to change to say that naive time *is* UTC
> (but stripped of leap secconds)?  That assumption seems to underlie
> all the sample classes: is it a required assumption, or just a
> convenient assumption for purposes of illustration?

SCREAM!!!  Returning -42137 is *not* the same as returning zero!!!

I'm not sure where the misunderstanding is.  Naive datetime doesn't
have an explicit timezone, but it could have an implied timezone that
the application knows.  The datetimetz class is intended to make the
timezone explicit.  When I create a datetimetz object, I pass in a
tzinfo object that represents the timezone semantics I want to use for
this datetimetz object.  So if I am going to record times in UTC, I
pass an instance (or maybe *the* instance :-) of the UTC class.  If I
am going to record times in "local time" without specifying anything
further, I can pass a LocalTime instance (see the Wiki for this
class).  And so on.

> BTW, I'm delighted to punt the nasty issues into the court of a
> vague object.

I object to calling the tzoffset object vague.  It's got a precise
interface.

PS. I've updated the Wiki:

http://www.zope.org/Members/fdrake/DateTimeWiki/TimeZoneInfo

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