pytz tzinfo set using replace() uses incorrect historical timezone

Bug #1394441 reported by Douglas Linder
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
pytz
New
Undecided
Unassigned

Bug Description

Yes, this is almost a duplicate of https://bugs.launchpad.net/pytz/+bug/504272, however, please take a moment to read my argument that this is in fact a bug in pytz.

Consider this code:

    import pytz
    from datetime import datetime

    fmt = '%Y-%m-%d %H:%M:%S %Z%z'
    tz = pytz.timezone('Australia/Perth')
    timestamp = 1416387060
    print(tz)

    # Correct way
    utctime = pytz.utc.localize(datetime.utcfromtimestamp(timestamp))
    print(utctime.strftime(fmt))

    astimezone = utctime.astimezone(tz)
    print(astimezone.strftime(fmt))

    localtime = tz.normalize(astimezone)
    print(localtime.strftime(fmt))

    # Incorrect way
    incorrect = datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz)
    print(incorrect.strftime(fmt))

As show, the 'correct' way to convert between timezones is to use the normalize method. However, no matter how you look at it, this code yeilds incorrect results:

    Australia/Perth
    2014-11-19 08:51:00 UTC+0000
    2014-11-19 16:51:00 AWST+0800
    2014-11-19 16:51:00 AWST+0800
    2014-11-19 08:51:00 LMT+0743 <---- This is wrong.

Obviously there's a limit to what's possible through the datetime api, but this is troubling:

    >>> pytz.timezone("Australia/Perth")
    <DstTzInfo 'Australia/Perth' LMT+7:43:00 STD>

That shouldn't be the default. It's the default because when a DstTzInfo object is created, it has no way of knowing what the datetime it will be associated with will be, so it just takes the first one.

...but the first one is *always wrong*. It's almost universally an ancient historical timezone which is unlikely to ever be used.

tldr; DstTzInfo should use the most recent (ie. now()) timezone by default when multiple timezones are available.

This would significantly simplify trivial use cases with pytz and remove bugs where people call datetime.replace() instead of localize, as per https://bugs.launchpad.net/pytz/+bug/504272.

It's not very helpful to say 'just use the api as described'.

The datetime api is outside of the control of pytz, but it *does* exist, and people do use it.

Revision history for this message
Stuart Bishop (stub) wrote :

Some discussion of the rationale over at Bug #1319939

Is it better for the default to be almost always wrong, or a default which is sometimes what is wanted? The latter leads to Heisenbugs, where systems behave differently depending on the phase of the moon. However, 'almost always wrong' isn't that much better either.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.