web-dev-qa-db-ja.com

Python:ローカルタイムゾーンを把握する

ログファイルのUTCタイムスタンプとローカルタイムスタンプを比較したい。ローカルdatetimeオブジェクトを作成するとき、次のようなものを使用します。

_>>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0, 
                                 tzinfo=pytz.timezone('Israel'))
_

Thetzinfo=pytz.timezone('Israel')を現在のローカルタイムゾーンに置き換える自動ツールを見つけたいです。

何か案は?

51
Adam Matan

dateutil を試してください。これは、必要なことを行う tzlocal タイプを持っています。

30
Steven

Python 3.xでは、ローカルタイムゾーンは次のように把握できます。

import datetime
LOCAL_TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo

それはdatetimeの-​​ code のトリッキーな使用です。

63
vbem

ログファイルのUTCタイムスタンプとローカルタイムスタンプを比較します。

ローカルタイムゾーンのOlson TZ名を見つけるのは難しい ポータブルな方法です。幸いなことに、比較を実行するのにそれは必要ありません。

tzlocal module は、ローカルタイムゾーンに対応するpytzタイムゾーンを返します。

_from datetime import datetime

import pytz # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal

tz = get_localzone()
local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None)
utc_dt = local_dt.astimezone(pytz.utc) #NOTE: utc.normalize() is unnecessary here
_

これまでに紹介した他のソリューションとは異なり、上記のコードは次の問題を回避します。

  • 現地時間はあいまいになる可能性があります つまり、一部の現地時間では正確な比較ができない
  • utcオフセットは、過去の日付の同じローカルタイムゾーン名に対して異なる場合があります。タイムゾーン対応のdatetimeオブジェクトをサポートする一部のライブラリ(例:dateutil)は、それを考慮に入れません

注:単純なdatetimeオブジェクトからタイムゾーン対応のdatetimeオブジェクトを取得するには、使用する必要があります*

_local_dt = tz.localize(datetime(2010, 4, 27, 12, 0, 0, 0), is_dst=None)
_

の代わりに:

_#XXX fails for some timezones
local_dt = datetime(2010, 4, 27, 12, 0, 0, 0, tzinfo=tz)
_

*_is_dst=None_は、指定されたローカル時間があいまいまたは存在しない場合に例外を強制します。

すべてのローカルタイムスタンプがローカルタイムゾーンに同じ(現在の)utcオフセットを使用していることが確実な場合は、stdlibのみを使用して比較を実行できます。

_# convert a naive datetime object that represents time in local timezone to Epoch time
timestamp1 = (datetime(2010, 4, 27, 12, 0, 0, 0) - datetime.fromtimestamp(0)).total_seconds()

# convert a naive datetime object that represents time in UTC to Epoch time
timestamp2 = (datetime(2010, 4, 27, 9, 0) - datetime.utcfromtimestamp(0)).total_seconds()
_

_timestamp1_と_timestamp2_は直接比較できます。

注意:

  • _timestamp1_式は、エポック(datetime.fromtimestamp(0))のUTCオフセットが現在と同じ場合にのみ機能します
  • fromtimestamp()は、現在のローカルタイムゾーンで単純なdatetimeオブジェクトを作成します
  • utcfromtimestamp()は、UTCで単純なdatetimeオブジェクトを作成します。
28
jfs

私は自分自身に同じことを尋ねていました、そして私は答えを1で見つけました:

セクション8.1.7を見てください:形式 "%z"(小文字、Zの大文字はタイムゾーンも返しますが、4桁の形式ではなく、[3]のようなタイムゾーンの略語の形式) strftimeの形式は、電子メールヘッダーの標準である「+/- 4DIGIT」という形式を返します(RFC 2822のセクション3.3を参照、[2]を参照、電子メールヘッダーのタイムゾーンを指定する他の方法を廃止)。

したがって、この形式のタイムゾーンが必要な場合は、次を使用します。

time.strftime("%z")

[1] http://docs.python.org/2/library/datetime.html

[2] http://tools.ietf.org/html/rfc2822#section-3.

[3]タイムゾーンの略語: http://en.wikipedia.org/wiki/List_of_time_zone_abbreviations 、参照のみ。

12
David L

最初にpytzおよびtzlocalモジュールを取得します

pip install pytz tzlocal

それから

from tzlocal import get_localzone
local = get_localzone()

その後、次のようなことができます

from datetime import datetime
print(datetime.now(local))
6
aminalid

標準ライブラリのみを使用してローカルタイムゾーンを取得する方法を次に示します(* nix環境でのみ機能します)。

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

これを使用して、pytzタイムゾーンを作成できます。

>>> import pytz
>>> my_tz_name = '/'.join(os.path.realpath('/etc/localtime').split('/')[-2:])
>>> my_tz = pytz.timezone(my_tz_name)
>>> my_tz
<DstTzInfo 'Australia/Sydney' LMT+10:05:00 STD>

...これをdatetimeに適用できます:

>>> import datetime
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2014, 9, 3, 9, 23, 24, 139059)

>>> now.replace(tzinfo=my_tz)
>>> now
datetime.datetime(2014, 9, 3, 9, 23, 24, 139059, tzinfo=<DstTzInfo 'Australia/Sydney' LMT+10:05:00 STD>)
4
amorphic

J. F. Sebastian's answer に基づいて、これを標準ライブラリで実行できます。

import time, datetime
local_timezone = datetime.timezone(datetime.timedelta(seconds=-time.timezone))

3.4でテスト済み、3.4 +で動作するはずです

3
Gilly

@vbemのソリューションのもう少し簡潔なバージョンを次に示します。

_from datetime import datetime as dt

dt.utcnow().astimezone().tzinfo
_

唯一の実質的な違いは、datetime.datetime.now(datetime.timezone.utc)datetime.datetime.utcnow()に置き換えたことです。簡潔にするために、_datetime.datetime_をdtとしてエイリアス化しました。

私の目的のために、秒単位のUTCオフセットが必要です。これは次のようなものです。

_dt.utcnow().astimezone().utcoffset().total_seconds()
_
3
David Marx

上記のThokuの回答に基づいて、タイムゾーンを最も近い30分に解決する回答を次に示します(南オーストラリアなどの一部のタイムゾーンに関連します)。

from datetime import datetime
round((round((datetime.now()-datetime.utcnow()).total_seconds())/1800)/2)
2
user2380550

非標準モジュールの回避(datetimeモジュールのメソッドが欠落しているようです):

from datetime import datetime
utcOffset_min = int(round((datetime.now() - datetime.utcnow()).total_seconds())) / 60   # round for taking time twice
utcOffset_h = utcOffset_min / 60
assert(utcOffset_min == utcOffset_h * 60)   # we do not handle 1/2 h timezone offsets

print 'Local time offset is %i h to UTC.' % (utcOffset_h)
2
thoku

簡単にするために、次のtzinfo実装を使用できます。これは、OSにタイムゾーンオフセットを照会します。

import datetime
import time

class LocalTZ(datetime.tzinfo):
    _unixEpochOrdinal = datetime.datetime.utcfromtimestamp(0).toordinal()

    def dst(self, dt):
        return datetime.timedelta(0)

    def utcoffset(self, dt):
        t = (dt.toordinal() - self._unixEpochOrdinal)*86400 + dt.hour*3600 + dt.minute*60 + dt.second + time.timezone
        utc = datetime.datetime(*time.gmtime(t)[:6])
        local = datetime.datetime(*time.localtime(t)[:6])
        return local - utc


print datetime.datetime.now(LocalTZ())
print datetime.datetime(2010, 4, 27, 12, 0, 0, tzinfo=LocalTZ())

# If you're in the EU, the following datetimes are right on the DST change.
print datetime.datetime(2013, 3, 31, 0, 59, 59, tzinfo=LocalTZ())
print datetime.datetime(2013, 3, 31, 1, 0, 0, tzinfo=LocalTZ())
print datetime.datetime(2013, 3, 31, 1, 59, 59, tzinfo=LocalTZ())

# The following datetime is invalid, as the clock moves directly from
# 01:59:59 standard time to 03:00:00 daylight savings time.
print datetime.datetime(2013, 3, 31, 2, 0, 0, tzinfo=LocalTZ())

print datetime.datetime(2013, 10, 27, 0, 59, 59, tzinfo=LocalTZ())
print datetime.datetime(2013, 10, 27, 1, 0, 0, tzinfo=LocalTZ())
print datetime.datetime(2013, 10, 27, 1, 59, 59, tzinfo=LocalTZ())

# The following datetime is ambigous, as 02:00 can be either DST or standard
# time. (It is interpreted as standard time.)
print datetime.datetime(2013, 10, 27, 2, 0, 0, tzinfo=LocalTZ())
1
Søren Løvborg

振り子 で満足するかもしれません

>>> pendulum.datetime(2015, 2, 5, tz='local').timezone.name
'Israel'

Pendulumには、日付を操作するための適切に設計されたAPIがあります。すべてがTZ対応です。

1
Étienne Bersac
now_dt = datetime.datetime.now()
utc_now = datetime.datetime.utcnow()
now_ts, utc_ts = map(time.mktime, map(datetime.datetime.timetuple, (now_dt, utc_now)))
offset = int((now_ts - utc_ts) / 3600)

これがあなたのお役に立てば幸いです。

1
宝城 p

まず、質問が認識された日時オブジェクトの不正な初期化を示していることに注意してください。

_>>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0,
...                                  tzinfo=pytz.timezone('Israel'))
_

無効なインスタンスを作成します。結果のオブジェクトのUTCオフセットを計算することで問題を確認できます。

_>>> print(local_time.utcoffset())
2:21:00
_

(1時間の奇数分数である結果に注意してください。)

Pytzを使用して認識日時を適切に初期化するには、次のようにlocalize()メソッドを使用する必要があります。

_>>> local_time=pytz.timezone('Israel').localize(datetime.datetime(2010, 4, 27, 12))
>>> print(local_time.utcoffset())
3:00:00
_

ここで、新しいtzinfoとしてローカルpytzタイムゾーンが必要な場合は、他の人が説明したようにtzlocalパッケージを使用する必要がありますが、必要なのは、正しいローカルタイムゾーンオフセットと略語を持つインスタンスだけで、Python 3.3、引数なしでastimezone()メソッドを呼び出して、対応するdatetimeインスタンスをローカルタイムゾーンに変換できます。

_>>> local_time.astimezone().strftime('%Y-%m-%d %H:%M %Z %z')
'2010-04-27 05:00 EDT -0400'
_