datetime オブジェクトを認識させる方法 (ナイーブではない) 質問する

datetime オブジェクトを認識させる方法 (ナイーブではない) 質問する

私は何をする必要がありますか

タイムゾーンを認識しない datetime オブジェクトがあり、他のタイムゾーンを認識する datetime オブジェクトと比較できるように、これにタイムゾーンを追加する必要があります。この 1 つのレガシー ケースのために、アプリケーション全体をタイムゾーンを認識しない形式に変換したくありません。

私が試したこと

まず、問題を説明します。

Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> import pytz
>>> unaware = datetime.datetime(2011,8,15,8,15,12,0)
>>> unaware
datetime.datetime(2011, 8, 15, 8, 15, 12)
>>> aware = datetime.datetime(2011,8,15,8,15,12,0,pytz.UTC)
>>> aware
datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)
>>> aware == unaware
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware datetimes

まず、astimezoneを試しました:

>>> unaware.astimezone(pytz.UTC)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: astimezone() cannot be applied to a naive datetime
>>>

実際に変換しようとしているので、これが失敗してもそれほど驚くことではありません。置換のほうが良い選択のように思えます(Python で「タイムゾーン対応」の datetime.today() の値を取得するにはどうすればよいですか?):

>>> unaware.replace(tzinfo=pytz.UTC)
datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)
>>> unaware == aware
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware datetimes
>>> 

しかし、ご覧のとおり、replace は tzinfo を設定するものの、オブジェクトを認識させるわけではないようです。解析する前に入力文字列を加工してタイムゾーンを設定する準備をしていますが (解析には dateutil を使用していますが、これが重要であれば)、これは非常に不格好に思えます。

また、これを Python 2.6 と Python 2.7 の両方で試しましたが、結果は同じでした。

コンテクスト

私はいくつかのデータ ファイルのパーサーを作成しています。日付文字列にタイムゾーン インジケーターがない古い形式をサポートする必要があります。データ ソースはすでに修正しましたが、レガシー データ形式をサポートする必要があります。レガシー データを 1 回変換することは、さまざまなビジネス上の理由からオプションではありません。一般的に、デフォルトのタイムゾーンをハードコーディングするという考えは好きではありませんが、この場合はそれが最善のオプションのようです。問題のすべてのレガシー データが UTC であることは十分に確信しているので、この場合はデフォルトに設定するリスクを受け入れる覚悟があります。

ベストアンサー1

一般的に、単純なdatetimeをタイムゾーン対応にするには、ローカライズメソッド:

import datetime
import pytz

unaware = datetime.datetime(2011, 8, 15, 8, 15, 12, 0)
aware = datetime.datetime(2011, 8, 15, 8, 15, 12, 0, pytz.UTC)

now_aware = pytz.utc.localize(unaware)
assert aware == now_aware

localizeUTC タイムゾーンの場合、夏時間の計算を処理する必要がないため、実際に使用する必要はありません。

now_aware = unaware.replace(tzinfo=pytz.UTC)

動作します。(.replace新しい datetime を返します。 は変更されませんunaware。)

おすすめ記事