web-dev-qa-db-ja.com

pythonでタイムゾーンを変換する予期しない結果

タイムゾーンをUTCに変換するときにこれらの結果が得られる理由を理解しようとしています:

In [74]: d1 = datetime(2007, 12, 5, 6, 30,tzinfo=pytz.timezone('US/Pacific'))
In [75]: d1
Out[75]: datetime.datetime(2007, 12, 5, 6, 30, tzinfo=<DstTzInfo 'US/Pacific' LMT-1 day, **16:07:00 STD**>)
In [76]: d1.astimezone(pytz.utc)
Out[76]: datetime.datetime(2007, 12, 5, 14, 23, tzinfo=<UTC>)

なぜ6:30 amが2:23 pmになったのですか?

一方、次のアプローチを使用すると、期待どおりの結果が得られます。

In [90]: d2 = datetime(2007, 12, 5, 6, 30)
In [91]: uspac = pytz.timezone('US/Pacific')
In [92]: d2_aware = uspac.localize(d2)
In [94]: d2_aware.astimezone(pytz.utc)
Out[94]: datetime.datetime(2007, 12, 5, 14, 30, tzinfo=<UTC>)
41
jxstanford

部分的なドキュメントから: http://pytz.sourceforge.net/#localized-times-and-date-arithmetic

残念ながら、標準の日時コンストラクタのtzinfo引数を使用すると、多くのタイムゾーンでpytzが「機能しない」ことになります。 [...] UTCなどの夏時間の移行がないタイムゾーンでも安全です。 [...]時間を処理するための推奨される方法は、常にUTCで機能し、人間が読み取る出力を生成するときにのみローカル時間に変換することです。

30
user3834473

私が得たのは単なる回避策であり、単純なルールはdatetime()を使用してタイムゾーン情報で日付時刻を作成しないです。

このサンプルは、これについてのヒントを提供します。ご覧のように、予期しない違いを回避できます。「ナイーブ」な日時(タイムゾーン情報のない日時)を作成してローカライズするだけです(ただし、UTCで日時を作成する場合は適用されません)。

import pytz
from datetime import datetime

# make Jan 1 on PDT -> UTC
pdt = pytz.timezone("America/Los_Angeles")
pdtnow1 = datetime(2014,1,1, tzinfo=pdt)
pdtnow2 = pdt.localize(datetime(2014,1,1))
pytz.utc.normalize(pdtnow1)
# > datetime.datetime(2014, 1, 1, 7, 53, tzinfo=<UTC>)
pytz.utc.normalize(pdtnow2)
# > datetime.datetime(2014, 1, 1, 8, 0, tzinfo=<UTC>)

# make Jan 1 on UTC -> PDT
utcnow1 = datetime(2014,1,1, tzinfo=pytz.utc)
utcnow2 = pytz.utc.localize(datetime(2014,1,1))
pdt.normalize(utcnow1)
# > datetime.datetime(2013, 12, 31, 16, 0, 
# > tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>)
pdt.normalize(utcnow2)
# > datetime.datetime(2013, 12, 31, 16, 0, 
# > tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>)
48
Kenial

日付と時刻に関するいくつかの質問を再検討して、このような状況で(またはそうでない場合)新しいライブラリのいくつかがより役立つことが判明するかどうかを確認します。 振り子 はタイムゾーンを日付と時刻で保存するもので、このような状況で特に価値があります。

>>> import pendulum
>>> d1 = pendulum.datetime(2007,12,5,6,30, tzinfo='US/Pacific')
>>> d1
<Pendulum [2007-12-05T06:30:00-08:00]>
>>> d1.timezone
<Timezone [US/Pacific]>
>>> d1.astimezone(tz='UTC')
<Pendulum [2007-12-05T14:30:00+00:00]>

他にもたくさんの甘い機能があります。

4
Bill Bell

残念ながら、この方法を使用してタイムゾーン対応の日付を作成することはできません。

Djangoを使用している場合、それらにはユーティリティ関数 make_aware があり、これが正しく機能します。

from Django.utils.timezone import make_aware
from pytz import timezone

unaware_datetime = datetime(2007, 12, 5)
local_datetime = make_aware(datetime(2007, 12, 5))
specific_datetime = make_aware(datetime(2007, 12, 5), timezone("Australia/Melbourne"))
3
Shadow

印刷d2_aware.astimezoneと表示されますPST-1(太平洋標準時)ですが、最初の例ではLMT-1(ローカル平均時間)-そしておそらく7分の差が出る可能性があります。

しかし、pytzが異なるタイムゾーンを使用する理由がわかりません。

0
furas