私はタイムゾーンをたくさん扱い、それらを横断するプログラムを書いています。私が最も扱っている2つのことは、「今」から日時オブジェクトを作成してから、単純な日時オブジェクトをローカライズすることです。
これから太平洋時間帯で日時オブジェクトを作成するために、現在これを行っています(python 2.7.2 +)
from datetime import datetime
import pytz
la = pytz.timezone("America/Los_Angeles")
now = datetime.now(la)
これはDSTに関して正しいですか?そうでない場合は、次のことを行う必要があると思います。
now2 = la.localize(datetime.now())
私の質問はなぜですか?最初が間違っていて秒が正しい場合を誰かに見せてもらえますか?
秒の質問については、カリフォルニア州ロサンゼルスで2012年9月1日の午前8時にユーザー入力から素朴な日付と時刻があったとします。このように日時を作成する正しい方法は次のとおりです。
la.localize(datetime(2012, 9, 1, 8, 0))
そうでない場合、これらの日時をどのように作成する必要がありますか?
pytzドキュメント から:
時間の処理に適した方法は、常にUTCで作業し、人間が読み取る出力を生成する場合にのみ現地時間に変換することです。
したがって、理想的には、utcnow
の代わりにnow
を使用する必要があります。
何らかの理由で手を縛られて現地時間で作業する必要があると仮定すると、夏時間の移行ウィンドウ中に現在の時刻をローカライズしようとすると、問題が発生する可能性があります。同じdatetime
が2回発生する可能性があります。1回は夏時間、もう1回は標準時間です。また、localize
メソッドは、is_dst
パラメーターで明示的に指定しない限り、競合を解決する方法を知りません。
したがって、現在のUTC時刻を取得するには:
utc = pytz.timezone('UTC')
now = utc.localize(datetime.datetime.utcnow())
そしてそれをあなたの現地時間に変換するために(しかしあなたがしなければならないときだけ):
la = pytz.timezone('America/Los_Angeles')
local_time = now.astimezone(la)
編集: @ J.Fによるコメントで指摘されているように。 Sebastian 、datetime.now(tz)
を使用した最初の例はすべての場合に機能します。上で概説したように、2番目の例は秋の移行中に失敗します。私はまだ、表示以外のすべてに現地時間の代わりにUTCを使用することを提唱しています。
最初の解決策はDSTに関して正しく、2番目の解決策は悪いです。
例を挙げましょう。ここヨーロッパでは、このコードを実行すると:
_from datetime import datetime
import pytz # $ pip install pytz
la = pytz.timezone("America/Los_Angeles")
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
now = datetime.now(la)
now2 = la.localize(datetime.now())
now3 = datetime.now()
print(now.strftime(fmt))
print(now2.strftime(fmt))
print(now3.strftime(fmt))
_
私は次のようになります:
_2012-08-30 12:34:06 PDT-0700
2012-08-30 21:34:06 PDT-0700
2012-08-30 21:34:06
_
datetime.now(la)
は、LAの現在の時刻と、LAのタイムゾーン情報を使用して日時を作成します。
la.localize(datetime.now())
は、単純な日時にタイムゾーン情報を追加しますが、タイムゾーン変換は行いません。時間がすでにこのタイムゾーンにあることを前提としています。
datetime.now()
は、現地時間で単純な日時(タイムゾーン情報なし)を作成します。
LAにいる限り、違いはわかりませんが、コードが他の場所で実行された場合、おそらく期待どおりに動作しません。
それとは別に、タイムゾーンを真剣に扱う必要がある場合は、すべての時間をUTCで設定することをお勧めします。これにより、DSTに関する多くの問題を回避できます。
これは機能します:
_# naive datetime
d = datetime.datetime(2016, 11, 5, 16, 43, 45)
utc = pytz.UTC # UTC timezone
pst = pytz.timezone('America/Los_Angeles') # LA timezone
# Convert to UTC timezone aware datetime
d = utc.localize(d)
>>> datetime.datetime(2016, 11, 5, 16, 43, 45, tzinfo=<UTC>)
# show as in LA time zone (not converting here)
d.astimezone(pst)
>>> datetime.datetime(2016, 11, 5, 9, 43, 45,
tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>)
# we get Pacific Daylight Time: PDT
# add 1 day to UTC date
d = d + datetime.timedelta(days=1)
>>> datetime.datetime(2016, 11, 6, 16, 43, 45, tzinfo=<UTC>)
d.astimezone(pst) # now cast to LA time zone
>>> datetime.datetime(2016, 11, 6, 8, 43, 45,
tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>)
# Daylight saving is applied -> we get Pacific Standard Time PST
_
これは機能しません:
_# naive datetime
d = datetime.datetime(2016, 11, 5, 16, 43, 45)
utc = pytz.UTC # UTC timezone
pst = pytz.timezone('America/Los_Angeles') # LA timezone
# convert to UTC timezone aware datetime
d = utc.localize(d)
>>> datetime.datetime(2016, 11, 5, 16, 43, 45, tzinfo=<UTC>)
# convert to 'America/Los_Angeles' timezone: DON'T DO THIS
d = d.astimezone(pst)
>>> datetime.datetime(2016, 11, 5, 9, 43, 45,
tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>)
# we are in Pacific Daylight Time PDT
# add 1 day to LA local date: DON'T DO THAT
d = d + datetime.timedelta(days=1)
>>> datetime.datetime(2016, 11, 6, 9, 43, 45,
tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>)
# Daylight Saving is NOT respected, we are still in PDT time, not PST
_
結論:
datetime.timedelta()
しない夏時間を考慮します。
常にUTCタイムゾーンで時間を加算/減算してください。出力/表示のためにのみ現地時間にキャストします。
pytzウェブサイト は言う:
残念ながら、標準の日時コンストラクターのtzinfo引数を使用すると、多くのタイムゾーンでpytzで「機能しません」。
したがって、datetime.now(la)
は使用しないでください。詳細はわかりませんが、一部のタイムゾーンは、以前よりもエキゾチックなルールで動作し、Pythonの日時コードではそれらを処理できません。 pytzのコードを使用することにより、pytzの目的であるため、正しく処理されるはずです。また、夏時間のジャンプ時間のおかげで2回発生する時間にも問題がある可能性があります。
2番目の質問に関しては、それはまさにドキュメントが示していることなので、あなたは良いはずです。