web-dev-qa-db-ja.com

ローカルタイムゾーンのOlsonTZ名を取得しますか?

Cの localtime 呼び出しで指定された値に対応する Olsonタイムゾーン名Australia/Sydneyなど)を取得するにはどうすればよいですか?

これは、TZを介して、/etc/localtimeをシンボリックリンクするか、時間関連のシステム構成ファイルにTIMEZONE変数を設定することによってオーバーライドされる値です。

49
Matt Joiner

すべてのpytzタイムゾーンを調べて、どれがローカルタイムゾーンに一致するかを確認するのが最善の策だと思います。各pytzタイムゾーンオブジェクトには、CDT、ESTなどのutcoffsetとtznameに関する情報が含まれています。ローカル時間に関する同じ情報は、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

出力:

['America/Atikokan'、 'America/Bahia_Banderas'、 'America/Baia_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 /マレンゴ '、'アメリカ/インディアナ/マレンゴ '、'アメリカ/インディアナ/ピーターズバーグ '、'アメリカ/インディアナ/テルシティ '、'アメリカ/インディアナ/ベヴァイ '、'アメリカ/インディアナ/ヴァンセンヌ '、'アメリカ/インディアナ/ウィナマック ' 、 'America/Indianapolis'、 'America/Iqaluit'、 'America/Kentucky/Louisville'、 'America/Kentucky/Louisville'、 'America/Kentucky/Monticello'、 'America/Knox_IN'、 'America/Louisville'、 'アメリカ/ルイビル '、'アメリカ/マナグア '、'アメリカ/マタモロス '、'アメリカ/メノミネ '、'アメリカ/メリダ '、'アメリカ/メキシコ_シティ '、'アメリカ/モンテレー '、'アメリカ/ノースダコタ/ベウラ '、' 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 ']

17
Anurag Uniyal

これは一種の不正行為ですが、'/etc/localtime'から取得してもうまくいきませんか?次のように:

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

それが役に立てば幸い。

編集'/etc/localtime'がシンボリックリンクでない場合に備えて、@ A.H。のアイデアが気に入りました。それを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 __== '__main__':
    print get_current_olsonname()
17
Thiago Curvelo

1つの問題は、「オーストラリア/シドニー」のように、同じタイムゾーン(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"

タイムゾーンAPIを処理するために、TZinfoをラップするライブラリがあるかどうかを確認する必要があります。

例:Pythonの場合は、pytzライブラリを確認してください:

http://pytz.sourceforge.net/

そして

http://pypi.python.org/pypi/pytz/

in 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のような呼び出しはないようです。これは特定の時間のすべての同義語名を見つけることができます。ゾーン。

13
Tilo

評価する場合/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
...

重複は、公式の地域名「Europe」、「America」のみを使用してフィルタリングできます...まだ重複がある場合は、最短の名前を使用できます:-)

8
A.H.

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モジュールによる)と国コード(による)の両方に基づいて、Olsonタイムゾーンで最善の推測を行います。 Pythonのlocaleモジュールhostip.info プロジェクト。IPアドレスを参照し、それに応じて地理的に配置します)。

たとえば、Timzone名を単純に一致させると、EST(GMT-5)の場合はAmerica/MonctonAmerica/Montreal、またはAmerica/New_Yorkになります。ただし、お住まいの国が米国の場合は、回答がAmerica/New_Yorkに制限されます。

ただし、お住まいの国がカナダの場合、スクリプトはデフォルトでカナダの最上位の結果(America/Moncton)になります。これをさらに改善する方法がある場合は、コメントに提案を残してください。

7
Patrick Perini

tzlocal モジュールPythonは、まさにこの問題を対象としています。これは、LinuxとWindowsの両方で一貫した結果を生成し、CLDRを使用してWindowsのタイムゾーンIDからOlsonに適切に変換します。マッピング。

4

これにより、TZ変数の内容に応じたタイムゾーン名、または設定されていない場合はローカルタイムファイルが取得されます。

#! /usr/bin/env python

import time

time.tzset
print time.tzname
2

代わりに PyIC を使用する別の可能性があります。これは私の目的のために働いています:

>>> 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'

ここでは、ローカルタイムゾーンでのナイーブ日時(データベースクエリによって返される)を解釈しています。

_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()
0
korc

ほとんどの場合、正しい形式のタイムゾーン(大陸/..../都市)を見つけるように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 __== '__main__':
    print get_current_olsonname()
0
saeedgnu