我知道这有点不光彩,但是从'/etc/localtime'
获取不行吗?像下面这样:
>>> import os
>>> '/'.join(os.readlink('/etc/localtime').split('/')[-2:])
'Australia/Sydney'
希望有所帮助。
编辑: 我喜欢@A.H.的想法,在'/etc/localtime'
不是符号链接的情况下。把它翻译成Python代码:
#!/usr/bin/env python
from hashlib import sha224
import os
def get_current_olsonname():
tzfile = open('/etc/localtime')
tzfile_digest = sha224(tzfile.read()).hexdigest()
tzfile.close()
for root, dirs, filenames in os.walk("/usr/share/zoneinfo/"):
for filename in filenames:
fullname = os.path.join(root, filename)
f = open(fullname)
digest = sha224(f.read()).hexdigest()
if digest == tzfile_digest:
return '/'.join((fullname.split('/'))[-2:])
f.close()
return None
if __name__ == '__main__':
print get_current_olsonname()
/etc/localtime
没有被更新会发生什么。此外,我建议您立即切换到4个空格缩进而不是制表符(或8个空格)。 - Matt Joiner我认为最好的方法是遍历所有的pytz时区,并检查哪个与本地时区匹配,每个pytz时区对象都包含有关utcoffset和tzname(如CDT、EST)的信息,可以从time.timezone/altzone
和time.tzname
获取有关本地时间的相同信息,我认为这足以正确匹配pytz数据库中的本地时区。
import time
import pytz
import datetime
local_names = []
if time.daylight:
local_offset = time.altzone
localtz = time.tzname[1]
else:
local_offset = time.timezone
localtz = time.tzname[0]
local_offset = datetime.timedelta(seconds=-local_offset)
for name in pytz.all_timezones:
timezone = pytz.timezone(name)
if not hasattr(timezone, '_tzinfos'):
continue#skip, if some timezone doesn't have info
# go thru tzinfo and see if short name like EDT and offset matches
for (utcoffset, daylight, tzname), _ in timezone._tzinfos.iteritems():
if utcoffset == local_offset and tzname == localtz:
local_names.append(name)
print local_names
输出:
['America/Atikokan', 'America/Bahia_Banderas', 'America/Bahia_Banderas', 'America/Belize', 'America/Cambridge_Bay', 'America/Cancun', 'America/Chicago', 'America/Chihuahua', 'America/Coral_Harbour', 'America/Costa_Rica', 'America/El_Salvador', 'America/Fort_Wayne', 'America/Guatemala', 'America/Indiana/Indianapolis', 'America/Indiana/Knox', 'America/Indiana/Marengo', 'America/Indiana/Marengo', 'America/Indiana/Petersburg', 'America/Indiana/Tell_City', 'America/Indiana/Vevay', 'America/Indiana/Vincennes', 'America/Indiana/Winamac', 'America/Indianapolis', 'America/Iqaluit', 'America/Kentucky/Louisville', 'America/Kentucky/Louisville', 'America/Kentucky/Monticello', 'America/Knox_IN', 'America/Louisville', 'America/Louisville', 'America/Managua', 'America/Matamoros', 'America/Menominee', 'America/Merida', 'America/Mexico_City', 'America/Monterrey', 'America/North_Dakota/Beulah', 'America/North_Dakota/Center', 'America/North_Dakota/New_Salem', 'America/Ojinaga', 'America/Pangnirtung', 'America/Rainy_River', 'America/Rankin_Inlet', 'America/Resolute', 'America/Resolute', 'America/Tegucigalpa', 'America/Winnipeg', 'CST6CDT', 'Canada/Central', 'Mexico/General', 'US/Central', 'US/East-Indiana', 'US/Indiana-Starke']
在生产环境中,您可以预先创建这样的映射并保存它,而不是总是迭代。
更改时区后的测试脚本:
$ export TZ='Australia/Sydney'
$ python get_tz_names.py
['Antarctica/Macquarie', 'Australia/ACT', 'Australia/Brisbane', 'Australia/Canberra', 'Australia/Currie', 'Australia/Hobart', 'Australia/Lindeman', 'Australia/Melbourne', 'Australia/NSW', 'Australia/Queensland', 'Australia/Sydney', 'Australia/Tasmania', 'Australia/Victoria']
if time.daylight and time.localtime().tm_isdst > 0
。注意:time.daylight
只是告诉您本地时区是否采用了夏令时,它并没有提供任何关于当前状态的信息。 - jfs一个问题是存在多个“美丽的名称”,比如“澳大利亚/悉尼”,它们指向同一个时区(例如CST)。
因此,您需要获取本地时区的所有可能名称,然后选择您喜欢的名称。
例如:对于澳大利亚,有5个时区,但更多的时区标识符:
"Australia/Lord_Howe", "Australia/Hobart", "Australia/Currie",
"Australia/Melbourne", "Australia/Sydney", "Australia/Broken_Hill",
"Australia/Brisbane", "Australia/Lindeman", "Australia/Adelaide",
"Australia/Darwin", "Australia/Perth", "Australia/Eucla"
并且
http://pypi.python.org/pypi/pytz/
在Python中,你可以做到:from pytz import timezone
import pytz
In [56]: pytz.country_timezones('AU')
Out[56]:
[u'Australia/Lord_Howe',
u'Australia/Hobart',
u'Australia/Currie',
u'Australia/Melbourne',
u'Australia/Sydney',
u'Australia/Broken_Hill',
u'Australia/Brisbane',
u'Australia/Lindeman',
u'Australia/Adelaide',
u'Australia/Darwin',
u'Australia/Perth',
u'Australia/Eucla']
但是Python的API似乎相当有限,例如它似乎没有像Ruby的all_linked_zone_names
这样的调用——可以找到给定时区的所有同义词名称。
/etc/localtime
是可以接受的,那么下面的技巧可能有效 - 在将其翻译为Python后:> md5sum /etc/localtime
abcdefabcdefabcdefabcdefabcdefab /etc/localtime
> find /usr/share/zoneinfo -type f |xargs md5sum | grep abcdefabcdefabcdefabcdefabcdefab
abcdefabcdefabcdefabcdefabcdefab /usr/share/zoneinfo/Europe/London
abcdefabcdefabcdefabcdefabcdefab /usr/share/zoneinfo/posix/Europe/London
...
import pytz
import time
#import locale
import urllib2
yourOlsonTZ = None
#yourCountryCode = locale.getdefaultlocale()[0].split('_')[1]
yourCountryCode = urllib2.urlopen('http://api.hostip.info/country.php').read()
for olsonTZ in [pytz.timezone(olsonTZ) for olsonTZ in pytz.all_timezones]:
if (olsonTZ._tzname in time.tzname) and (str(olsonTZ) in pytz.country_timezones[yourCountryCode]):
yourOlsonTZ = olsonTZ
break
print yourOlsonTZ
time
模块)和您的国家代码(根据hostip.info项目,引用您的IP地址并相应地确定您的位置),尽力猜测您的Olson时区。例如,仅匹配时区名称可能会得出EST(GMT-5)的America/Moncton
、America/Montreal
或America/New_York
。然而,如果您的国家是美国,它将限制答案为America/New_York
。但是,如果您的国家是加拿大,则脚本将简单地默认为最顶部的加拿大结果(America/Moncton
)。如果有更进一步完善的方法,请随时在评论中提出建议。en_AU
,但拥有en_US
并不罕见。此外,我的时区名称是“EST”,因此您的算法会给出“America/New_York”,但我实际上在“悉尼/澳大利亚”。 - Matt Joiner这将根据TZ变量中的内容或未设置时的本地时间文件获取时区名称:
#! /usr/bin/env python
import time
time.tzset
print time.tzname
America/New_York
或者Australia/Sydney
。"BST"可以是Europe/London
或者Asia/Dhaka
。 - wberryls -l /etc/localtime
的返回结果并从中提取链接路径。这里有一个关于如何做到这一点的完整线程:https://dev59.com/SnVD5IYBdhLWcg3wGXlI(调用ls而不是解析路径) - Yanick Girouard这里还有另一种可能性,可以使用PyICU代替;这对我的目的来说是有效的:
>>> from PyICU import ICUtzinfo
>>> from datetime import datetime
>>> datetime(2012, 1, 1, 12, 30, 18).replace(tzinfo=ICUtzinfo.getDefault()).isoformat()
'2012-01-01T12:30:18-05:00'
>>> datetime(2012, 6, 1, 12, 30, 18).replace(tzinfo=ICUtzinfo.getDefault()).isoformat()
'2012-06-01T12:30:18-04:00'
这里是将本地时区中的naive日期时间(如数据库查询返回的)进行解释。
我更喜欢遵循稍微好一点的方式,而不是四处摸索 _xxx 值。
import time, pytz, os
cur_name=time.tzname
cur_TZ=os.environ.get("TZ")
def is_current(name):
os.environ["TZ"]=name
time.tzset()
return time.tzname==cur_name
print "Possible choices:", filter(is_current, pytz.all_timezones)
# optional tz restore
if cur_TZ is None: del os.environ["TZ"]
else: os.environ["TZ"]=cur_TZ
time.tzset()
我修改了tcurvelo的脚本,以找到正确的时区形式(大陆/.../城市),在大多数情况下,但如果失败则返回所有时区形式
#!/usr/bin/env python
from hashlib import sha224
import os
from os import listdir
from os.path import join, isfile, isdir
infoDir = '/usr/share/zoneinfo/'
def get_current_olsonname():
result = []
tzfile_digest = sha224(open('/etc/localtime').read()).hexdigest()
test_match = lambda filepath: sha224(open(filepath).read()).hexdigest() == tzfile_digest
def walk_over(dirpath):
for root, dirs, filenames in os.walk(dirpath):
for fname in filenames:
fpath = join(root, fname)
if test_match(fpath):
result.append(tuple(root.split('/')[4:]+[fname]))
for dname in listdir(infoDir):
if dname in ('posix', 'right', 'SystemV', 'Etc'):
continue
dpath = join(infoDir, dname)
if not isdir(dpath):
continue
walk_over(dpath)
if not result:
walk_over(join(infoDir))
return result
if __name__ == '__main__':
print get_current_olsonname()
America/New_York
)的方法? - wberry