简体   繁体   中英

How can I get a human-readable timezone name in Python?

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.

The following generates a defaultdict mapping timezone offsets (eg '-0400') and abbreviations (eg 'EDT') to common geographic timezone names (eg '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)

for k, v in result.items():
    print(k, v)

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.

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 (before tzlocal 3.0 version) that corresponds to the system local timezone:

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

# display "human-readable" name (tzid)
print(tzlocal.get_localzone_name())

# Example Results:
# -> Europe/Moscow
# -> America/Chicago

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'))

# Example Results:
# -> MSK+0300 
# -> CDT-0500

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

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.

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 .

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...

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'

# use tzlocal library

from tzlocal import get_localzone

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

Working with the latest version of tzlocal which is 4.1 as of today, tzlocal.get_localzone().key produces the following error: AttributeError: '_PytzShimTimezone' object has no attribute 'key' . But tzlocal.get_localzone().zone works lovely.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM