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

Guido van Rossum guido@python.org
Mon, 18 Mar 2002 14:13:03 -0500


[Patrick]
> I think what is confusing is that (I think) a tzinfo object is only
> meaningfully useable in the context of a given datetimetz. (I'm
> assuming this is what Guido intends.) So even though a tzinfo has
> methods that take a dt argument, I think what is implied is the the
> dt argument would never be anything other than the datetimetz
> instance that also held the tzinfo instance in question. (I hope
> that makes sense.)

Yes.  I pass the dt object because many dt objects usually share a
single tz object (in a real implementation, I'd probably make UTC and
LocalTime singletons, and use a cache for FixedOffset instances).

> So to put a tzinfo object in a datetimetz
> instance (as part of the init) is to specificy that there is a
> relationship between the tzinfo instance and the "underlying" naive
> datetime. Presumably the application that creates these datetimetz
> instances would have the logic (and responsibility) for associating
> naive datetimes with the "right" tzinfos. (If datetimetz were a
> container that held one naive datetime and one tzinfo, rather than a
> subclass of datetime, that would be closer to how I conceptualize
> the relationship between these things.)

Fine by me; it's possible that the only reason for subclassing is that
I want dt objects to be small; a container would require two object
headers, two object allocations (not counting the tz object, which is
widely shared).  Jim Fulton already remarked that he expected we'd end
up with a sitation where a datetime subclasses date but is not a
subtype in the type-theoretical sense; probably the same will hold for
datetimetz and datetime.

> > Perhaps it's trying to say that a tzinfo *specifies*, rather than
> > reveals,
> 
> That is how I interpret the example code. (But I had to read it a
> few times to come to my current understanding, which may still be
> flawed relative to what Guido really has in mind.)

Yes!

> > the tzoffset corresponding to a given datetime.  That even appears
> > likely now.  But even in that case, it's unclear why the sample
> > classes ignore whatever tzinfo object may be attached to their dt
> > argument if dt is a datetimetz instance.
> 
> I had assumed that the dt argument would be supplied by the
> datetimetz object that held the tzinfo instance, and could therefore
> be ignored. (See my sample code below.) Other messages have
> suggested some kind of conversion could take place. The semantics of
> all this definitely need to be worked out. I think we are all
> confused a bit by the partial implementation.

I think I've clarified this in the Wiki now.  The tz object specifies
the meaning of the dt fields further; the dt object records local time
according to the tz object; tz conversions are not the intention, and
in fact the tz methods now require that their dt argument points back
to the same tz object.

> > I'm afraid this just isn't going to make sense to me until I see
> > concrete examples of intended use.
> 
> I agree. Here is how I picture the datetimetz class. I'm sure Guido
> will yell if I'm way off base with this.
> 
> class datetimetz(datetime):
>     """A subclass of datetime that adds an optional timezone info object.
>     If the tzinfo object is None, this behaves identical to naive datetime."""
>     def __init__(dtstuff, tzinfo=None):
>         # Greatly simplified -- for illustration purposes only.
>         super(datetimetz, self).__init__(dtstuff)
>         self.tzinfo = tzinfo
> 
>     def tzoffset(self):
>     "Return the offset east of UTC, in minutes"
>         if tzinfo is None: raise AttributeError
>         return self.tzinfo.tzoffset(dt=self)
> 
>     def tzname(self):
>     "Return a string that names the intended timezone"
>         if tzinfo is None: raise AttributeError
>         return self.tzinfo.tzname(dt=self)
> 
>     def tzdst(self):
>     "Return 0 if DST is not in effect, or the DST offset if DST is in effect"
>         if tzinfo is None: raise AttributeError
>         return self.tzinfo.tzdst(dt=self)
> 
>     def tzinfo(self):
>     "Return the tzinfo object"
>         return self.tzinfo

This is by and large what I had in mind, yes, except for some trivial
corrections (using self.__tzinfo rather than tzinfo or self.tzinfo),
and I would return None rather than raising an exception (and
AttributeError is not a very good exception).

> With this approach, I don't see anyone accessing a tzinfo's methods
> directly, only indirectly through a datetimetz instance.

Agreed.  But the sematics should be understood this way, (a) so that
one can understand how to write the tzinfo object, (b) so that one can
emulate this behavior when necessary.

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