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 geopy
g = 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 tzwhere
w = 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 python
import os
from collections import defaultdict
from datetime import datetime
from urllib import urlretrieve
from urlparse import urljoin
from zipfile import ZipFile
import pytz # pip install pytz
geonames_url = 'http://download.geonames.org/export/dump/'
basename = 'cities15000' # all cities with a population > 15000 or capitals
filename = basename + '.zip'
# get file
if not os.path.exists(filename):
urlretrieve(urljoin(geonames_url, filename), filename)
# parse it
city2tz = defaultdict(set)
with ZipFile(filename) as zf, zf.open(basename + '.txt') as file:
for line in file:
fields = line.split(b'')
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
"
"(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): 112682
Find number of ambigious city names
(that have more than one associated timezone): 2318
Zurich is in Europe/Zurich timezone
Current time in Zurich is 2013-05-13 11:36:33 CEST+0200