获取当地时区的Olson TZ名称?

Mat*_*ner 49 python linux timezone datetime localtime

如何获得与C 呼叫给出的值对应的Olson时区名称(例如Australia/Sydney)localtime

这是TZ通过符号链接/etc/localtimeTIMEZONE在时间相关的系统配置文件中设置变量来覆盖的值.

Thi*_*elo 17

我知道,这是一种作弊行为,但是'/etc/localtime'起作用对你不起作用?如下:

>>>  import os
>>> '/'.join(os.readlink('/etc/localtime').split('/')[-2:])
'Australia/Sydney'
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你.

编辑:我喜欢@ AH的想法,万一 '/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()
Run Code Online (Sandbox Code Playgroud)

  • 在我的Ubuntu系统上,这很遗憾地返回zoneinfo/localtime. (2认同)

Anu*_*yal 17

我认为最好的办法是去通所有pytz时区和检查哪一个相匹配的本地时区,每个pytz时区对象包含有关UTCOFFSET和TZNAME像CDT,EST信息,可以从以下地址获得有关本地时间相同的信息time.timezone/altzonetime.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
Run Code Online (Sandbox Code Playgroud)

输出:

['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','Am erica/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 ='澳大利亚/悉尼'
$ 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']

  • 要确定DST是否有效:`if time.daylight和time.localtime().tm_isdst> 0`.注意:`time.daylight`只是告诉当地时区是否有DST,它不会告诉当前状态. (2认同)

Til*_*ilo 13

一个问题是有多个"漂亮的名字",如"澳大利亚/悉尼",它指向同一时区(例如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"
Run Code Online (Sandbox Code Playgroud)

你应该检查是否有一个包装TZinfo来处理时区API.

例如:对于Python,检查pytz库:

http://pytz.sourceforge.net/

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']
Run Code Online (Sandbox Code Playgroud)

但是Python的API似乎非常有限,例如它似乎没有像Ruby这样的调用all_linked_zone_names- 它可以找到给定时区的所有同义词名称.


A.H*_*.H. 8

如果/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
...
Run Code Online (Sandbox Code Playgroud)

只使用官方地区名称"欧洲","美国"过滤重复项...如果仍有重复项,您可以使用最短的名称:-)


Pat*_*ini 7

安装pytz

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
Run Code Online (Sandbox Code Playgroud)

根据您的时区名称(根据Python的time模块)和您的国家代码(根据Python的locale模块,hostip.info项目,它引用您的IP地址和地理位置),此代码将根据您的Olson Timezone进行最佳猜测.你呢).

例如,简单地匹配Timzone名称可能导致America/Moncton,America/MontrealAmerica/New_York对EST(GMT-5).但是,如果你的国家是美国,它将限制答案America/New_York.

但是,如果您所在的国家/地区是加拿大,则该脚本将默认为加拿大最顶级的结果(America/Moncton).如果有办法进一步完善这一点,请随时在评论中留下建议.


Mat*_*int 5

Python 的tzlocal模块正是针对这个问题。它在 Linux 和 Windows 下产生一致的结果,使用 CLDR 映射正确地将 Windows 时区 ID 转换为 Olson。