ログファイルのUTCタイムスタンプとローカルタイムスタンプを比較したい。ローカルdatetime
オブジェクトを作成するとき、次のようなものを使用します。
_>>> local_time=datetime.datetime(2010, 4, 27, 12, 0, 0, 0,
tzinfo=pytz.timezone('Israel'))
_
Thetzinfo=pytz.timezone('Israel')
を現在のローカルタイムゾーンに置き換える自動ツールを見つけたいです。
何か案は?
Python 3.xでは、ローカルタイムゾーンは次のように把握できます。
import datetime
LOCAL_TIMEZONE = datetime.datetime.now(datetime.timezone.utc).astimezone().tzinfo
それはdatetime
の- code のトリッキーな使用です。
ログファイルの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
_
これまでに紹介した他のソリューションとは異なり、上記のコードは次の問題を回避します。
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オブジェクトを作成します。私は自分自身に同じことを尋ねていました、そして私は答えを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 、参照のみ。
最初にpytzおよびtzlocalモジュールを取得します
pip install pytz tzlocal
それから
from tzlocal import get_localzone
local = get_localzone()
その後、次のようなことができます
from datetime import datetime
print(datetime.now(local))
標準ライブラリのみを使用してローカルタイムゾーンを取得する方法を次に示します(* 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>)
J. F. Sebastian's answer に基づいて、これを標準ライブラリで実行できます。
import time, datetime
local_timezone = datetime.timezone(datetime.timedelta(seconds=-time.timezone))
3.4でテスト済み、3.4 +で動作するはずです
@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()
_
上記のThokuの回答に基づいて、タイムゾーンを最も近い30分に解決する回答を次に示します(南オーストラリアなどの一部のタイムゾーンに関連します)。
from datetime import datetime
round((round((datetime.now()-datetime.utcnow()).total_seconds())/1800)/2)
非標準モジュールの回避(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)
簡単にするために、次の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())
振り子 で満足するかもしれません
>>> pendulum.datetime(2015, 2, 5, tz='local').timezone.name
'Israel'
Pendulumには、日付を操作するための適切に設計されたAPIがあります。すべてがTZ対応です。
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)
これがあなたのお役に立てば幸いです。
まず、質問が認識された日時オブジェクトの不正な初期化を示していることに注意してください。
_>>> 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'
_