在 Python/Django 中从城市获取时区 [英] Get Timezone from City in Python/Django

查看:36
本文介绍了在 Python/Django 中从城市获取时区的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 pytz,我可以获得这样的时区列表:

<预><代码>>>>从 pytz 导入 country_timezones>>>打印(''.join(country_timezones('ch')))欧洲/苏黎世>>>打印(''.join(country_timezones('CH')))欧洲/苏黎世

鉴于我从用户那里获得 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 dbpytzwhere:

import tzwherew = tzwhere()打印 w.tzNameAt(1.352083, 103.819836)# ->亚洲/新加坡

还有允许将(纬度、经度)转换为时区的网络服务,例如 askgeogeonames,参见 从经纬度查询时区.

正如 @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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆