Get Timezone from City in Python/Django Get Timezone from City in Python/Django django django

Get Timezone from City in Python/Django


pytz is a wrapper around IANA Time Zone Database (Olson database). It does not contain data to map an arbitrary city in the world to the timezone it is in.

You might need a geocoder such as geopy that can translate a place (e.g., a city name) to its coordinates (latitude, longitude) using various web-services:

from geopy import geocoders # pip install geopyg = geocoders.GoogleV3()place, (lat, lng) = g.geocode('Singapore')# -> (u'Singapore', (1.352083, 103.819836))

Given city's latitude, longitude, it is possible to find its timezone using tz_world, an efele.net/tz map / a shapefile of the TZ timezones of the world e.g., via postgis timezone db or pytzwhere:

import tzwherew = tzwhere()print w.tzNameAt(1.352083, 103.819836)# -> Asia/Singapore

There are also web-services that allow to convert (latitude, longitude) into a timezone e.g., askgeo, geonames, see Timezone lookup from latitude longitude.

As @dashesy pointed out in the comment, geopy also can find timezone (since 1.2):

timezone = g.timezone((lat, lng)) # return pytz timezone object# -> <DstTzInfo 'Asia/Singapore' LMT+6:55:00 STD>

GeoNames also provides offline data that allows to get city's timezone directly from its name e.g.:

#!/usr/bin/env pythonimport osfrom collections import defaultdictfrom datetime import datetimefrom urllib   import urlretrievefrom urlparse import urljoinfrom zipfile  import ZipFileimport pytz # pip install pytzgeonames_url = 'http://download.geonames.org/export/dump/'basename = 'cities15000' # all cities with a population > 15000 or capitalsfilename = basename + '.zip'# get fileif not os.path.exists(filename):    urlretrieve(urljoin(geonames_url, filename), filename)# parse itcity2tz = defaultdict(set)with ZipFile(filename) as zf, zf.open(basename + '.txt') as file:    for line in file:        fields = line.split(b'\t')        if fields: # geoname table http://download.geonames.org/export/dump/            name, asciiname, alternatenames = fields[1:4]            timezone = fields[-2].decode('utf-8').strip()            if timezone:                for city in [name, asciiname] + alternatenames.split(b','):                    city = city.decode('utf-8').strip()                    if city:                        city2tz[city].add(timezone)print("Number of available city names (with aliases): %d" % len(city2tz))#n = sum((len(timezones) > 1) for city, timezones in city2tz.iteritems())print("")print("Find number of ambigious city names\n "      "(that have more than one associated timezone): %d" % n)#fmt = '%Y-%m-%d %H:%M:%S %Z%z'city = "Zurich"for tzname in city2tz[city]:    now = datetime.now(pytz.timezone(tzname))    print("")    print("%s is in %s timezone" % (city, tzname))    print("Current time in %s is %s" % (city, now.strftime(fmt)))

Output

Number of available city names (with aliases): 112682Find number of ambigious city names (that have more than one associated timezone): 2318Zurich is in Europe/Zurich timezoneCurrent time in Zurich is 2013-05-13 11:36:33 CEST+0200


I think you're going to need to manually search the timezone database for the city you're looking for:

from pytz import country_timezones, timezonedef find_city(query):    for country, cities in country_timezones.items():        for city in cities:            if query in city:                yield timezone(city)for tz in find_city('Zurich'):    print(tz)

(that's just a quick-and-dirty solution, it for instance doesn't try to match only the city-part of a timezone – try searching for Europe, it does substring matches, doesn't search case-insensitive, etc.)


there have been a lot of possible solutions proposed here and they're all a bit tedious to set up.

To make things quicker for the next person with this problem, I took the one from Will Charlton and made a quick python library out of it: https://pypi.python.org/pypi/whenareyou

from whenareyou import whenareyoutz = whenareyou('Hamburg')tz.localize(datetime(2002, 10, 27, 6, 0, 0))

Gets you datetime.datetime(2002, 10, 27, 6, 0, tzinfo=<DstTzInfo 'Europe/Berlin' CET+1:00:00 STD>).

This gets you a pytz object (tz in the example) so you can use it pythonicly.

  • It uses the google API
  • Leaves daylight savings calculation to pytz, only one call per city, rest happens offline
  • LRU caches the requests so you shouldn't hit the API limit easily
  • Should also work with any address or anything google maps understands