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

2024-11-07 08:55:00
admin
原创
232
摘要:问题描述:如何获取与 C 的调用给出的值相对应的Olson 时区名称(例如) ?Australia/Sydney`localtime`这是通过TZ、符号链接/etc/localtime或TIMEZONE在时间相关的系统配置文件中设置变量覆盖的值。解决方案 1:我知道这有点作弊,但是 get from'/etc...

问题描述:

如何获取与 C 的调用给出的值相对应的Olson 时区名称(例如) ?Australia/Sydney`localtime`

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


解决方案 1:

我知道这有点作弊,但是 get from'/etc/localtime'对你不起作用?像下面这样:

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

希望有帮助。

编辑:我喜欢@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()

解决方案 2:

我认为最好的办法是遍历所有 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

输出:

['美洲/阿蒂科坎', '美洲/巴伊亚班德拉斯', '美洲/巴伊亚班德拉斯', '美洲/伯利兹', '美洲/剑桥湾', '美洲/坎昆', '美洲/芝加哥', '美洲/奇瓦瓦', '美洲/珊瑚港', '美洲/哥斯达黎加', '美洲/萨尔瓦多', '美洲/韦恩堡', '美洲/危地马拉', '美洲/印第安纳州/印第安纳波利斯', '美洲/印第安纳州/诺克斯', '美洲/印第安纳州/马伦戈', '美洲/印第安纳州/马伦戈', '美洲/印第安纳州/彼得斯堡', '美洲/印第安纳州/特尔城', '美洲/印第安纳州/韦韦', '美洲/印第安纳州/文森斯', '美洲/印第安纳州/威纳马克', '美洲/印第安纳波利斯', '美洲/伊卡卢伊特', '美洲/肯塔基州/路易斯维尔', '美洲/肯塔基州/路易斯维尔', '美洲/肯塔基州/蒙蒂塞洛', '美洲/诺克斯印第安纳州', '美洲/路易斯维尔', '美洲/路易斯维尔', '美洲/马那瓜', '美洲/马塔莫罗斯', '美洲/梅诺米尼', '美洲/梅里达', '美洲/墨西哥城', '美洲/蒙特雷', '美洲/北达科他州/Beulah'、'美洲/北达科他州/中心'、'美洲/北达科他州/新塞勒姆'、'美洲/Ojinaga'、'美洲/Pangnirtung'、'美洲/Rainy_River'、'美洲/Rankin_Inlet'、'美洲/坚决'、'美洲/坚决'、 “美国/特古西加尔巴”、“美国/温尼伯”、“CST6CDT”、“加拿大/中部”、“墨西哥/将军”、“美国/中部”、“美国/东印第安纳”、“美国/印第安纳-斯塔克”]

在生产中,您可以预先创建这样的映射并保存它,而不是总是进行迭代。

更改时区后的测试脚本:

$ export TZ='澳大利亚/悉尼'

$ python get_tz_names.py

['南极洲/麦夸里', '澳大利亚/澳大利亚首都领地', '澳大利亚/布里斯班', '澳大利亚/堪培拉', '澳大利亚/柯里', '澳大利亚/霍巴特', '澳大利亚/林德曼', '澳大利亚/墨尔本', '澳大利亚/新南威尔士州', '澳大利亚/昆士兰州', '澳大利亚/悉尼', '澳大利亚/塔斯马尼亚州', '澳大利亚/维多利亚']

解决方案 3:

一个问题是,有多个“漂亮的名称”,如“澳大利亚/悉尼”,指向同一个时区(例如 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"

您应该检查是否有一个包装 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']

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

解决方案 4:

如果评估/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
...

可以仅使用官方区域名称“欧洲”、“美洲”等来过滤重复项...如果仍然有重复项,则可以采用最短的名称:-)

解决方案 5:

安装 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

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

例如,简单匹配时区名称可能会得到America/MonctonAmerica/MontrealAmerica/New_YorkEST (GMT-5)。但是,如果您所在的国家/地区是美国,则答案将限制为America/New_York

但是,如果您所在的国家是加拿大,脚本将默认使用最顶部的加拿大结果 ( America/Moncton)。如果有进一步改进的方法,请随时在评论中留下建议。

解决方案 6:

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

解决方案 7:

这将根据 TZ 变量或本地时间文件中的内容(如果未设置)获取时区名称:

#! /usr/bin/env python

import time

time.tzset
print time.tzname

解决方案 8:

这是另一种可能性,使用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'

这里是在本地时区中解释原始日期时间(就像数据库查询返回的那样)。

解决方案 9:

我更喜欢遵循比探索 _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()

解决方案 10:

我修改了 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()

解决方案 11:

这个 JavaScript 项目试图在浏览器客户端解决同样的问题。它的工作原理是与语言环境玩“二十个问题”,询问过去某些时间的 UTC 偏移量(以测试夏令时边界等),并使用这些结果推断当地时区应该是什么。不幸的是,我不知道有任何等效的 Python 包,所以如果有人想使用这个解决方案,就必须将其移植到 Python。

虽然此公式需要在每次更新 TZ 数据库时(最坏的情况下)进行更新,但我认为,将此算法与 Anurag Uniyal 提出的解决方案(仅保留两种方法返回的可能性)相结合是计算有效本地时区最可靠的方法。只要任意两个时区中至少一个本地时间的 UTC 偏移量存在差异,这样的系统就可以在它们之间进行正确选择。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2500  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1541  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   16  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   23  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   26  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用