20
votes

In a Python project I'm working on, I'd like to be able to get a "human-readable" timezone name of the form America/New_York, corresponding to the system local timezone, to display to the user. Every piece of code I've seen that accesses timezone information only returns either a numeric offset (-0400) or a letter code (EDT) or sometimes both. Is there some Python library that can access this information, or if not that, convert the offset/letter code into a human-readable name?

If there's more than one human-readable name corresponding to a particular timezone, either a list of the possible results or any one of them is fine, and if there is no human-readable name corresponding to the current time zone, I'll take either an exception or None or [] or whatever.


A clarification: I don't remember exactly what I had in mind when I originally wrote this question, but I think what I really wanted was a way to turn a timezone into a human-readable name. I don't think this question was meant to focus on how to get the system local timezone specifically, but for the specific use case I had in mind, it just happened that the local timezone was the one I wanted the name for. I'm not editing the bit about the local timezone out of the question because there are answers focusing on both aspects.

7
you do need be careful with how you use this I think. just an example: when in Europe/Rome we switched from CEST to CET in October 2010, both 2010-10-31T02:30:00CEST and 2010-10-31T02:30:00CET have been recorded, one equivalent to 2010-10-31T00:30:00UTC and the other to 2010-10-31T01:30:00UTC. 2010-10-31T02:30:00 Europe/Rome would be ambiguous.mariotomo

7 Answers

6
votes

This may not have been around when this question was originally written, but here is a snippet to get the time zone official designation:

>>> eastern = timezone('US/Eastern')
>>> eastern.zone
'US/Eastern'

Further, this can be used with a non-naive datetime object (aka a datetime where the actual timezone has been set using pytz.<timezone>.localize(<datetime_object>) or datetime_object.astimezone(pytz.<timezone>) as follows:

>>> import datetime, pytz
>>> todaynow = datetime.datetime.now(tz=pytz.timezone('US/Hawaii'))
>>> todaynow.tzinfo # turned into a string, it can be split/parsed
<DstTzInfo 'US/Hawaii' HST-1 day, 14:00:00 STD>
>>> todaynow.strftime("%Z")
'HST'
>>> todaynow.tzinfo.zone
'US/Hawaii'

This is, of course, for the edification of those search engine users who landed here. ... See more at the pytz module site.

13
votes

The following generates a defaultdict mapping timezone offsets (e.g. '-0400') and abbreviations (e.g. 'EDT') to common geographic timezone names (e.g. 'America/New_York').

import os
import dateutil.tz as dtz
import pytz
import datetime as dt
import collections

result=collections.defaultdict(list)
for name in pytz.common_timezones:
    timezone=dtz.gettz(name)
    now=dt.datetime.now(timezone)
    offset=now.strftime('%z')
    abbrev=now.strftime('%Z')
    result[offset].append(name)
    result[abbrev].append(name)    
print(result)

Note that timezone abbreviations can have vastly different meanings. For example, 'EST' could stand for Eastern Summer Time (UTC+10) in Australia, or Eastern Standard Time (UTC-5) in North America.

Also, the offsets and abbreviations may change for regions that use daylight standard time. So saving the static dict may not provide the correct timezone name 365 days a year.

10
votes

I'd like to be able to get a "human-readable" timezone name of the form America/New_York, corresponding to the system local timezone, to display to the user.

There is tzlocal module that returns a pytz tzinfo object that corresponds to the system local timezone:

#!/usr/bin/env python
import tzlocal  # $ pip install tzlocal

print(tzlocal.get_localzone().zone) # display "human-readable" name (tzid)
# -> Europe/Moscow

To answer the question in the title (for people from google), you could use %Z%z to print the local time zone info:

#!/usr/bin/env python
import time

print(time.strftime('%Z%z'))
# -> MSK+0300

It prints the current timezone abbreviation and the utc offset corresponding to your local timezone.

9
votes

http://pytz.sourceforge.net/ may be of help. If nothing else, you may be able to grab a list of all of the timezones and then iterate through until you find one that matches your offset.

4
votes

If you want only literally what you asked for, "the timezone name of the form America/New_York, corresponding to the system local timezone", and if you only care about Linux (and similar), then this should do the job:

import os
import os.path
import sys 

def main(argv):
  tzname = os.environ.get('TZ')
  if tzname:
    print tzname
  elif os.path.exists('/etc/timezone'):
    print file('/etc/timezone').read()
  else:
    sys.exit(1)

if __name__ == '__main__':
  main(sys.argv)

Of course it would be nicer to have a library that encapsulates this in a cleaner way, and that perhaps handles the other cases you mention in comments like already having a tzinfo object. I think you can do that with pytz mentioned by Amber but it's not obvious to me just how...

1
votes

Check out python-dateutil

py> from dateutil.tz import *
py> ny = gettz('America/New York')
py> ny._filename
'/usr/share/zoneinfo/America/New_York'
py> ny._filename.split('/', 4)[-1]
'America/New_York'
1
votes

# use tzlocal library

from tzlocal import get_localzone

current_timezone = get_localzone()
zone = current_timezone.zone
print(zone)