[Guido]
But now even the simplest tzinfo implementations (those with a fixed offset) have to implement something a bit tricky:
ZERO = timedelta() class fixed(tzinfo): def __init__(self, offset): self.offset = timedelta(minutes=offset) def utcoffset(self, dt): return self.offset def dst(self, dt): return ZERO def fromutc(self, dt): return datetimetz.combine(dt.date(), dt.time(), tzinfo=self) + self.offset
I find that last line cumbersome.
It is. Since astimezone() will only call it with a datetimetz argument,
That's not how I read your previous mail, but it's certainly more sensible, given that astimezone() is primarily a method on a datetimetz. :-)
it could be simplified to
return dt.replace(tzinfo=self) + self.offset
For that matter, astimezone could attach self to dt before calling this, so that the user implementation becomes
return dt + self.offset
For variable-dst zones it goes way up: the DST transition boundaries have to be translated to UTC in order to be able to make sense out of them in fromutc(), but they're still needed in local time for dst().
Some time zones have to translate them to UTC in dst() anyway; your EU.py does this, for example.
Agreed. DST-aware tzinfo classes will always be complex.
But I agree that we could probably improve life for all involved if we changed the tzinfo implementation. Perhaps we should constrain DST-aware timezones to the most common model, where there are two offsets (standard and DST) and two transition datetime points in local standard time (DST on and DST off). A tzinfo would have methods that would let you inquire these things directly; the offsets would be simple attributes, and the DST on and off points would be returned by a method that only takes the year as input (astimezone() would have to be careful to expect DST on to be > DST off for the southern hemisphere). I suppose the Israeli implementation would have to use a table of transition points for past years and always return standard time for future years (since the Knesseth decides on the switch points each year). The implementation for British time during WWII would have to tell a little lie -- big deal.
Well, I'm not sure that adding a bunch of new methods is going to make life easier for users.
I meant to use these *only* and throw away the other methods. (tzname() would have to be replaced by two string attributes, e.g. stdname and dstname, or perhaps a sequence of two strings, like the time module does in its tzname variable.)
Another idea: fromutc() is just a defined hook. If a tzinfo object has it, astimezone() will use it and believe whatever it returns. If it's not defined, then the current implementation is used -- and it should work for any tz where tz.utcoffset(dt)-tz.dst(dt) is invariant wrt dt. That covers the only worlds I live in <wink>.
If we constrain what a tzinfo class *can* do to fit a one-size-fits-all implementation, then we may as well steal Java's SimpleTimeZone API and let users get away without coding anything (in return, they get to spend days trying to guess what all the constructor arguments really mean <wink>).
I want to be able to model at least table-based historic DST transitions, which SimpleTimeZone doesn't do. Its abstract base class, TimeZone, allows you to write a concrete subclass that *does* support historic DST transitions. But the mess Java made here is obvious in the number of deprecated methods and constructors, and I'd like to stay away from it as far as possible. (January==0? Gimme a break! :-). --Guido van Rossum (home page: http://www.python.org/~guido/)