regebro / tzlocal

A Python module that tries to figure out what your local timezone is

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Various issues with tzlocal on OS X

mitsuhiko opened this issue · comments

tzlocal on OS X currently does not produce a timezone with the correct name, instead it reads the zone file and constructs a new pytz timezone object.

The object returned technically works but it has a few problems. For one it carries the wrong name: "local" instead of the actual olson name. On my OS X machine the timezone right now is set to "Europe/London" but the object returned reports "local" as zone. This becomes problematic as it breaks deepcopy:

>>> zone = tzlocal.get_localzone()
>>> zone
<DstTzInfo 'local' GMT0:00:00 STD>
>>> copy.deepcopy({'foo': zone})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
pytz.exceptions.UnknownTimeZoneError: 'local'

More important than that is that when I was playing around with this during EuroPython in italy I actually got a one hour offset from the local timezone to what actually was my local system time. I tried reproducing this now but I failed in doing that.

What I started doing in babel is to see if I can reproduce the name out of the symlink. On OS X the file is currently always a symlink to the zone info file:

$ ls -alh /etc/localtime 
lrwxr-xr-x  1 root  wheel    33B Jul  8 09:14 /etc/localtime -> /usr/share/zoneinfo/Europe/London

This then gives me the correct name which makes loading easier and then reports the actual zone.

Ah, I see. It doesn't use the "wrong" Olson name. The situation is that it is impossible to figure out what the Olson name is on this system. This is probably typical for OS X. tzlocal then returns a timezone object that is usable, but with no Olsen name. I didn't know this makes pytz zones unpicklable, but it is not possible to fix through tzlocal.

I did consider using the linkname this way but decided it was too hackish, perhaps I should do it anyway.

There is actually a way to figure out the name, but it's pretty ugly:

$ systemsetup -gettimezone
Time Zone: Europe/London

Interestingly enough, it would appear that systemsetup just reads the symlink. The only other thing it does is mmapping the "icudt46l.dat" icu file which I don't think has anything to do with timezones.

Whatever pyicu does, it does the right thing:

>>> from icu import ICUtzinfo
>>> ICUtzinfo.getDefault()
<ICUtzinfo: Europe/London>

I can confirm this for OS X. My current workaround is

if "darwin" in sys.platform:
    return os.popen("systemsetup -gettimezone").read().replace("Time Zone: ", "").strip()
else:
    return str(tzlocal.get_localzone())

But it would be nice tzlocal could handle this as well!

I commited a tentative attempt to make better support for OS X, please test!

I think this will not work for users without administrative access (try running systemsetup -gettimezone on a guest account). I added a PR for that (see the corresponding issue in jrnl for reference)

No more bugs on this has arrived, so I close this now. A release will come soonish.