Python: Figure out local timezone

141,708

Solution 1

Try dateutil, which has a tzlocal type that does what you need.

Solution 2

In Python 3.x, local timezone can be figured out like this:

import datetime
LOCAL_TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo

It's a tricky use of datetime's code .

For python < 3.6, you'll need

import datetime
LOCAL_TIMEZONE = datetime.datetime.now(datetime.timezone(datetime.timedelta(0))).astimezone().tzinfo

Solution 3

to compare UTC timestamps from a log file with local timestamps.

It is hard to find out Olson TZ name for a local timezone in a portable manner. Fortunately, you don't need it to perform the comparison.

tzlocal module returns a pytz timezone corresponding to the local timezone:

from datetime import datetime

import pytz # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal

tz = get_localzone()
local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None)
utc_dt = local_dt.astimezone(pytz.utc) #NOTE: utc.normalize() is unnecessary here

Unlike other solutions presented so far the above code avoids the following issues:

  • local time can be ambiguous i.e., a precise comparison might be impossible for some local times
  • utc offset can be different for the same local timezone name for dates in the past. Some libraries that support timezone-aware datetime objects (e.g., dateutil) fail to take that into account

Note: to get timezone-aware datetime object from a naive datetime object, you should use*:

local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None)

instead of:

#XXX fails for some timezones
local_dt = datetime(2010, 4, 27, 12, 0, 0, 0, tzinfo=tz)

*is_dst=None forces an exception if given local time is ambiguous or non-existent.

If you are certain that all local timestamps use the same (current) utc offset for the local timezone then you could perform the comparison using only stdlib:

# convert a naive datetime object that represents time in local timezone to epoch time
timestamp1 = (datetime(2010, 4, 27, 12, 0, 0, 0) - datetime.fromtimestamp(0)).total_seconds()

# convert a naive datetime object that represents time in UTC to epoch time
timestamp2 = (datetime(2010, 4, 27, 9, 0) - datetime.utcfromtimestamp(0)).total_seconds()

timestamp1 and timestamp2 can be compared directly.

Note:

  • timestamp1 formula works only if the UTC offset at epoch (datetime.fromtimestamp(0)) is the same as now
  • fromtimestamp() creates a naive datetime object in the current local timezone
  • utcfromtimestamp() creates a naive datetime object in UTC.

Solution 4

I was asking the same to myself, and I found the answer in 1:

Take a look at section 8.1.7: the format "%z" (lowercase, the Z uppercase returns also the time zone, but not in the 4-digit format, but in the form of timezone abbreviations, like in [3]) of strftime returns the form "+/- 4DIGIT" that is standard in email headers (see section 3.3 of RFC 2822, see [2], which obsoletes the other ways of specifying the timezone for email headers).

So, if you want your timezone in this format, use:

time.strftime("%z")

[1] http://docs.python.org/2/library/datetime.html

[2] https://www.rfc-editor.org/rfc/rfc2822#section-3.3

[3] Timezone abbreviations: http://en.wikipedia.org/wiki/List_of_time_zone_abbreviations , only for reference.

Solution 5

The following appears to work for 3.7+, using standard libs:

from datetime import timedelta
from datetime import timezone
import time

def currenttz():
    if time.daylight:
        return timezone(timedelta(seconds=-time.altzone),time.tzname[1])
    else:
        return timezone(timedelta(seconds=-time.timezone),time.tzname[0])
Share:
141,708
Adam Matan
Author by

Adam Matan

Team leader, developer, and public speaker. I build end-to-end apps using modern cloud infrastructure, especially serverless tools. My current position is R&amp;D Manager at Corvid by Wix.com, a serverless platform for rapid web app generation. My CV and contact details are available on my Github README.

Updated on September 07, 2021

Comments

  • Adam Matan
    Adam Matan over 2 years

    I want to compare UTC timestamps from a log file with local timestamps. When creating the local datetime object, I use something like:

    >>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0, 
                                     tzinfo=pytz.timezone('Israel'))
    

    I want to find an automatic tool that would replace thetzinfo=pytz.timezone('Israel') with the current local time zone.

    Any ideas?