4
>>> import pytz
>>> tz = pytz.timezone('America/Chicago')
>>> dt_naive = datetime(year=2017, month=6, day=6)
>>> dt_aware = tz.localize(dt_naive)
>>> dt_aware.tzinfo == tz
False

What's the reason for these to differ?

>>> dt_aware.tzinfo
<DstTzInfo 'America/Chicago' CDT-1 day, 19:00:00 DST>
>>> tz
<DstTzInfo 'America/Chicago' LMT-1 day, 18:09:00 STD>
wim
  • 338,267
  • 99
  • 616
  • 750
  • @MarkRansom I don't agree it's a duplicate (and I had actually already seen that target). I'm asking about why they aren't considered equal, and how some sort of meaningful equality comparison between `dt_aware.tzinfo` and `tz` could be made - if that's possible. – wim Jun 07 '17 at 01:17
  • 1
    OK, I understand now. Your actual question was kind of buried. The only explicit question, "What's the reason for these to differ" was answered by the other question. – Mark Ransom Jun 07 '17 at 02:06

2 Answers2

5

The first one has been adjusted to the date and time provided, 2016-06-06T00:00:00. Central Daylight Time (CDT) is in effect at this time. It is 5 hours behind UTC (24:00 - 05:00 = 19:00).

The second one has not been localized, so it is giving you the first offset in the available time zone data, which happens to be the Local Mean Time (LMT) entry. You can see this in the tzdata sources here. The LMT is 5 hours, 50 minutes, and 36 seconds behind UTC. The seconds of the LMT offset are rounded off somewhere in pytz, so 18:09 is reflecting this correctly (24:00 - 05:51 = 18:09)

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • Can you suggest a method to make a meaningful comparison between timezone instances? i.e. do they have the same utcoffset ... what about just comparing equality on their `str(tz)`? – wim Jun 07 '17 at 01:58
4

The key that determines the timezone from pytz is the string you passed to create the object: 'America/Chicago'. That key is available through the .zone attribute.

>>> tz = pytz.timezone('America/Chicago')
>>> dt_naive = datetime(year=2017, month=6, day=6)
>>> dt_aware = tz.localize(dt_naive)
>>> dt_aware.tzinfo == tz
False
>>> tz.zone
'America/Chicago'
>>> dt_aware.tzinfo.zone == tz.zone
True
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • This is the same as using `str(tz)`. Can we do any better? There are many aliases, for example, zone "America/Chicago" and zone "US/Central" should be considered equal for all practical purposes. +1 anyway.. – wim Jun 07 '17 at 03:42
  • @wim I hadn't realized that `str(tz)` was different from `repr(tz)`. Since `zone` is the key that determines the object behavior, I assume that's the only thing that truly represents the object identity. It's possible that `'America/Chicago'` and `'US/Central'` are different in some historical context. If you just want to know if they're equivalent for some specific point in time then you could localize that point in time with both timezones and test if they're equal. – Mark Ransom Jun 07 '17 at 04:04
  • 1
    `US/Central` is an alias of `America/Chicago`. It's represented by a `Link` entry in the tzdb [here](https://github.com/eggert/tz/blob/2017b/backward#L114). So they are identical in terms of historical context. I think wim is looking for a method of comparing two different zones for equivalency over their entire set of transition rules. – Matt Johnson-Pint Jun 07 '17 at 16:05
  • @MattJohnson it's too bad that `pytz` doesn't pick a canonical zone name for the two cases and let `.zone` return something consistent. It looks like the only way to compare two timezone objects is to work with the private attributes of the object. – Mark Ransom Jun 07 '17 at 18:13
  • Yeah, I came to the same conclusion. I don't think it retains `Link` details, and it exposes very little outside of the `tzinfo` required implementation. – Matt Johnson-Pint Jun 07 '17 at 19:57