How to get system timezone setting and pass it to pytz.timezone? How to get system timezone setting and pass it to pytz.timezone? python python

How to get system timezone setting and pass it to pytz.timezone?


tzlocal module returns pytz tzinfo's object corresponding to the local timezone:

import timefrom datetime import datetimeimport pytz # $ pip install pytzfrom tzlocal import get_localzone # $ pip install tzlocal# get local timezone    local_tz = get_localzone() # test it# utc_now, now = datetime.utcnow(), datetime.now()ts = time.time()utc_now, now = datetime.utcfromtimestamp(ts), datetime.fromtimestamp(ts)local_now = utc_now.replace(tzinfo=pytz.utc).astimezone(local_tz) # utc -> localassert local_now.replace(tzinfo=None) == now

It works even during daylight savings time transitions when local time may be ambiguous.

local_tz also works for past dates even if utc offset for the local timezone was different at the time. dateutil.tz.tzlocal()-based solution fails in this case e.g., in Europe/Moscow timezone (example from 2013):

>>> import os, time>>> os.environ['TZ'] = 'Europe/Moscow'>>> time.tzset()>>> from datetime import datetime>>> from dateutil.tz import tzlocal>>> from tzlocal import get_localzone>>> dateutil_tz = tzlocal()>>> tzlocal_tz = get_localzone()>>> datetime.fromtimestamp(0, dateutil_tz)                              datetime.datetime(1970, 1, 1, 4, 0, tzinfo=tzlocal())>>> datetime.fromtimestamp(0, tzlocal_tz)datetime.datetime(1970, 1, 1, 3, 0, tzinfo=<DstTzInfo 'Europe/Moscow' MSK+3:00:00 STD>)

dateutil returns wrong UTC+4 offset instead of the correct UTC+3 on 1970-01-01.

For those bumping into this in 2017 dateutil.tz.tzlocal() is still broken. The above example works now because the current utf offset is UTC+3 in Moscow (that by accident is equal to the utc offset from 1970). To demonstrate the error we can choose a date when utc offset is UTC+4:

>>> import os, time>>> os.environ['TZ'] = 'Europe/Moscow'>>> time.tzset()>>> from datetime import datetime>>> from dateutil.tz import tzlocal>>> from tzlocal import get_localzone>>> dateutil_tz = tzlocal()>>> tzlocal_tz = get_localzone()>>> ts = datetime(2014, 6,1).timestamp() # get date in 2014 when gmtoff=14400 in Moscow>>> datetime.fromtimestamp(ts, dateutil_tz)datetime.datetime(2014, 5, 31, 23, 0, tzinfo=tzlocal())>>> datetime.fromtimestamp(ts, tzlocal_tz)datetime.datetime(2014, 6, 1, 0, 0, tzinfo=<DstTzInfo 'Europe/Moscow' MSK+4:00:00 STD>)

dateutil returns wrong UTC+3 offset instead of the correct UTC+4 on 2014-06-01.


Use the tzlocal function from the python-dateutil package:

from dateutil.tz import tzlocallocaltimezone = tzlocal()

Internally, this is a class that uses time.timezone and time.altzone (switching based on time.daylight), but creates a suitable timezone object from that.

You use this instead of a pytz timezone.

The alternative is to read the currently configured timezone from the operating system instead, but this differs widely from OS to OS. On Mac OS X you need to read the output of systemsetup -gettimezone:

$ systemsetup -gettimezoneTime Zone: Europe/Copenhagen

On Debian and Ubuntu systems, you can read /etc/timezone:

$ cat /etc/timezoneEurope/Oslo

On RedHat and direved systems, you'll need to read it from /etc/sysconfig/clock:

$ grep ZONE /etc/sysconfig/clockZONE="Europe/Oslo"


Since Python 3.6, you can simply run naive_datetime.astimezone() and system time zone will be added to naive_datetime object.

If called without arguments (or with tz=None) the system local timezone is assumed for the target timezone. The .tzinfo attribute of the converted datetime instance will be set to an instance of timezone with the zone name and offset obtained from the OS.

https://docs.python.org/3/library/datetime.html#datetime.datetime.astimezone

Example:

>>> import datetime>>> datetime.datetime.now().astimezone().isoformat(timespec='minutes')'2018-10-02T13:09+03:00'