28

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.

David Z
  • 128,184
  • 27
  • 255
  • 279
  • 2
    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 Sep 20 '11 at 09:13

9 Answers9

16

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)

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.

JayRizzo
  • 3,234
  • 3
  • 33
  • 49
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • `now.strftime('%Z')` is indeed the answer I was looking for. That's under the assumption that any possibly ambigious timezone names such as EST are not used. Also, for anyone who needs it, there is a list of [`pytz` timezone names](https://stackoverflow.com/questions/13866926/is-there-a-list-of-pytz-timezones). – Asclepius Nov 01 '19 at 16:55
14

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.

JayRizzo
  • 3,234
  • 3
  • 33
  • 49
jfs
  • 399,953
  • 195
  • 994
  • 1,670
9

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.

Amber
  • 507,862
  • 82
  • 626
  • 550
  • 3
    Iterating over isn't a bad idea. I'd iterate through all of them once and build a `shelve` file or just store a `dict` in a module or something keyed by the letter code. Then you can just ship the `dict` with the app and not have to perform the search twice. You wouldn't even have to ship `pytz` in that case: you could just use it in the script that builds the `dict` – aaronasterling Aug 15 '10 at 21:00
  • 1
    Yep. It's something that works well with just pre-calculation (or even just building it on startup; it doesn't take *that* long if you're only doing it once per execution). – Amber Aug 16 '10 at 00:28
  • 1
    [`tzlocal` module can find `pytz` tzinfo object that corresponds to the local timezone](http://stackoverflow.com/a/35086646/4279) – jfs Jan 29 '16 at 14:25
  • It isn't that simple -- the current offset from UTC isn't enough to determine which time zone I'm in. For example, America/Denver and America/Phoenix have the same offset in the winter but different offsets in the summer. This is quite common. – zaphod Mar 22 '16 at 20:29
7

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.

ingyhere
  • 11,818
  • 3
  • 38
  • 52
  • 4
    I think it would be useful to mention that - assuming it's actually the case - this is a pytz feature, rather than an inherent feature of all timezone objects. – David Z Nov 01 '19 at 08:29
4

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

poolie
  • 9,289
  • 1
  • 47
  • 74
2

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'
Jesse Dhillon
  • 7,841
  • 1
  • 34
  • 34
  • But that doesn't help me if I have a `tzinfo` object that wasn't obtained from `dateutil.tz.gettz` - for example, one from `pytz` - or if I just call `gettz()` (in which case the filename is `/etc/localtime`). (Still I appreciate the info) – David Z Aug 16 '10 at 02:34
  • Well, where are these timezone objects coming from? You can store the name of the timezone -- the string argument to `gettz` -- and reconstitute timezones using that argument and `gettz`. I guess I am assuming certain use cases, for example storing a time and the associated timezone string in a database. I would never use `gettz` by itself to get the local timezone, but also in my case the user would be a person behind a web browser. – Jesse Dhillon Aug 16 '10 at 04:27
1

# use tzlocal library

from tzlocal import get_localzone

current_timezone = get_localzone()
zone = current_timezone.zone
print(zone)  
Kisakyamukama
  • 99
  • 1
  • 10
0

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.

0

You can get your computer's timezone with the external module tzlocal in your backend as shown below:

from tzlocal import get_localzone_name

print(get_localzone_name()) # America/New_York
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129