在 Python/Django 中从城市获取时区 [英] Get Timezone from City in Python/Django
问题描述
使用 pytz
,我可以获得这样的时区列表:
鉴于我从用户那里获得 Country 和 City 字段,我该如何确定城市的时区?
pytz
是 IANA 时区数据库(Olson 数据库)的包装器.它不包含将世界上任意城市映射到其所在时区的数据.
您可能需要可以翻译地点的地理编码器,例如 geopy
使用各种网络服务(例如,城市名称)到其坐标(纬度、经度):
from geopy import geocoders # pip install geopyg = geocoders.GoogleV3()place, (lat, lng) = g.geocode('新加坡')# ->(u'新加坡', (1.352083, 103.819836))
给定城市的纬度、经度,可以使用 tz_world,一个 efele.net/找到它的时区tz 地图/世界 TZ 时区的 shapefile 例如,通过 postgis timezone db 或 pytzwhere
:
import tzwherew = tzwhere()打印 w.tzNameAt(1.352083, 103.819836)# ->亚洲/新加坡
还有允许将(纬度、经度)转换为时区的网络服务,例如 askgeo、geonames,参见 从经纬度查询时区.
正如 @dashesy 在评论中指出的,geopy
也可以找到时区(从 1.2 开始):
timezone = g.timezone((lat, lng)) # 返回 pytz 时区对象# -><DstTzInfo '亚洲/新加坡' LMT+6:55:00 STD>
GeoNames 还提供离线数据,允许直接从其名称获取城市的时区,例如:
#!/usr/bin/env python导入操作系统从集合导入 defaultdict从日期时间导入日期时间从 urllib 导入 urlretrieve从 urlparse 导入 urljoin从 zipfile 导入 ZipFile导入 pytz # pip 安装 pytzgeonames_url = 'http://download.geonames.org/export/dump/'basename = 'cities15000' # 人口大于等于的所有城市15000 或大写文件名 = 基本名称 + '.zip'# 获取文件如果不是 os.path.exists(filename):urlretrieve(urljoin(geonames_url,文件名),文件名)# 解析它city2tz = defaultdict(set)使用 ZipFile(filename) 作为 zf,zf.open(basename + '.txt') 作为文件:对于文件中的行:字段 = line.split(b' ')如果字段:# geoname 表 http://download.geonames.org/export/dump/名称,asciiname,备用名称 = 字段 [1:4]timezone = fields[-2].decode('utf-8').strip()如果时区:对于 [name, asciiname] + alternames.split(b',') 中的城市:city = city.decode('utf-8').strip()如果城市:city2tz[city].add(时区)print("可用城市名称的数量(带别名):%d" % len(city2tz))#n = sum((len(timezones) > 1) for city, timezones in city2tz.iteritems())打印("")print("找出有歧义的城市名称的数量
"(具有多个关联时区):%d"%n)#fmt = '%Y-%m-%d %H:%M:%S %Z%z'城市 = "苏黎世"对于 city2tz[city] 中的 tzname:现在 = datetime.now(pytz.timezone(tzname))打印("")print("%s 在 %s 时区" % (city, tzname))print("%s 中的当前时间是 %s" % (city, now.strftime(fmt)))
输出
可用城市名称数量(带别名):112682查找模棱两可的城市名称的数量(具有多个关联时区):2318苏黎世位于欧洲/苏黎世时区苏黎世当地时间是2013-05-13 11:36:33 CEST+0200
Using pytz
, I am able to get a list of timezones like so:
>>> from pytz import country_timezones
>>> print(' '.join(country_timezones('ch')))
Europe/Zurich
>>> print(' '.join(country_timezones('CH')))
Europe/Zurich
Given that I am getting both Country and City fields from the user, how can I go about determining the timezone for the city?
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
这篇关于在 Python/Django 中从城市获取时区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!