[Datetime-SIG] Are there any "correct" implementations of tzinfo?

Tim Peters tim.peters at gmail.com
Sun Sep 13 05:54:47 CEST 2015

>>> I will try to create a  zoneinfo wrapping prototype as well, but I will
>>> probably "cheat" and build it on top of pytz.

>> It would be crazy not to ;-)  Note that Stuart got to punt on "the
>> hard part":  .utcoffset(), since pytz only uses fixed-offset classes.
>> For a prototype - and possibly forever after - I'd be inclined to
>> create an exhaustive list of transition times in local time, parallel
>> to the list of such times already there in UTC.

> Yes.  The only complication is that you need four transition points instead
> of two per year in a regular DST case: (1) start of gap; (2) end of gap; (3)
> start of fold; and (4) end of fold.  Once you know where you are with
> respect to those points, figuring out utcoffset(), dst() and tzname() for
> either value of fold is trivial.

I wouldn't call those extras transitions - they're just warts hanging
off of actual transitions.  Earlier I showed Stuart how to determine
everything about a possible fold from a UTC time using pytz's internal
info, in

    Fri, 28 Aug 2015 01:01:06 -0500

He didn't reply that I saw, so it was either obvious or
incomprehensible to him ;-)  In any case, it just takes some very
simple code once the transition record the UTC time belongs in is
found.  I'd be surprised if it weren't similarly easy to determine
everything about a possible gap.

At least in a zoneinfo wrapping, a hybrid tzinfo's .utcoffset() has to
(at least internally) find "the transition record the UTC time belongs
in" regardless.

> ...
> It's a shame though to work from a transitions in UTC list

But that's what tzfiles store.  It would be insane for a zoneinfo
wrapping not to take advantage of that.  For which reason, I do
consider dateutil's zoneinfo wrapping to be insane ;-)  (It inherits
the default .fromutc())

Ah, BTW, I think dateutil's zoneinfo's wrapping also misunderstood
some of what's actually in a tzfile.  Specifically, a tzfile's "
UTC/local indicators" and " standard/wall indicators" are 100% useless
for anything we need, and shouldn't even be read from the file(*)
(seek over 'em).

> because most of DST rules are expressed in local times and then
> laboriously converted into UTC.

It's just a few lines of code in zoneinfo's zic.c.  Nobody is doing it
"by hand" there.

> I think I should also implement the POSIX TZ spec tzinfo.

For that you really should grab dateutil.  It has a full
implementation of POSIX TZ rules, as hybrid tzinfos; here from its

>>> tz1 = tzstr('EST+05EDT,M4.1.0,M10.5.0')
>>> tz2 = tzstr('AEST-10AEDT-11,M10.5.0,M3.5.0')
>>> dt = datetime(2003, 5, 8, 2, 7, 36, tzinfo=tz1)
>>> dt.strftime('%X %x %Z')
'02:07:36 05/08/03 EDT'
>>> dt.astimezone(tz2).strftime('%X %x %Z')
'16:07:36 05/08/03 AEST'

Of course this implementation is tied into dateutil's rich supply of
"calendar operations" too.

> This is where the advantage of the "as intended" approach will be obvious.

?  "As intended" is all about (to me) using hybrid tzinfos.  And those
are far richer in tzfiles than from POSIX rules.  The latter only
present us with simplest-possible DST transitions; tzfiles present us
with every absurd political manipulation yet inflicted on humankind

(*) Long boring story.  Short course:  those indicators are only
needed, on some systems, if a POSIZ TZ rule specifies a zone offset
but gives no rules at all for daylight transitions, _and_ the system
has a "posixrules" tzfile.  Then an insane scheme is used to make up
daylight rules "as if" the source file from which the posixrules
tzfile was created had been for a zone with the TZ-specified standard
offset instead, and these absurd indicators are used to figure out
whether the posixrules source file specified _its_ daylight rules
using UTC or local times, and if the later case then whether using
standard time or wall-clock time instead.  It's completely nuts.

More information about the Python-list mailing list