web-dev-qa-db-ja.com

Python strptime()およびタイムゾーン?

IPDDumpを使用して作成されたBlackberry IPDバックアップからのCSVダンプファイルがあります。ここの日付/時刻文字列は次のようになります(ESTはオーストラリアのタイムゾーンです):

Tue Jun 22 07:46:22 EST 2010

Pythonでこの日付を解析できるようにする必要があります。最初は、datettimeからstrptime()関数を使用しようとしました。

>>> datetime.datetime.strptime('Tue Jun 22 12:10:20 2010 EST', '%a %b %d %H:%M:%S %Y %Z')

ただし、何らかの理由で、戻ってくるdatetimeオブジェクトにはtzinfoが関連付けられていないようです。

私は このページ を読みましたが、明らかにdatetime.strptimeは静かにtzinfoを破棄しますが、ドキュメントを確認しましたが、その効果に関するドキュメントは見つかりません ここ

サードパーティのPythonライブラリ、 dateutil を使用して解析された日付を取得できましたが、組み込みのstrptime()間違っていますか? strptime()をタイムゾーンでうまく再生する方法はありますか?

137
victorhooi

datetimeモジュールのドキュメント の意味:

形式に従って解析された、date_stringに対応する日時を返します。これはdatetime(*(time.strptime(date_string, format)[0:6]))と同等です。

[0:6](year, month, day, hour, minute, second)になります。他に何もありません。タイムゾーンについての言及はありません。

興味深いことに、[Win XP SP2、Python 2.6、2.7]をtime.strptimeに渡すことは機能しませんが、「%Z」と「 EST」は動作します。また、「EST」の代わりに「UTC」または「GMT」を使用することもできます。 「PST」と「MEZ」は機能しません。不可解です。

これはバージョン3.2の時点で更新されており、同じドキュメントで次のようになっていることに注意してください。

%zディレクティブがstrptime()メソッドに提供されると、認識された日時オブジェクトが生成されます。結果のtzinfoはタイムゾーンインスタンスに設定されます。

これは%Zでは機能しないため、大文字と小文字が区別されることに注意してください。次の例を参照してください。

In [1]: from datetime import datetime

In [2]: start_time = datetime.strptime('2018-04-18-17-04-30-AEST','%Y-%m-%d-%H-%M-%S-%Z')

In [3]: print("TZ NAME: {tz}".format(tz=start_time.tzname()))
TZ NAME: None

In [4]: start_time = datetime.strptime('2018-04-18-17-04-30-+1000','%Y-%m-%d-%H-%M-%S-%z')

In [5]: print("TZ NAME: {tz}".format(tz=start_time.tzname()))
TZ NAME: UTC+10:00
44
John Machin

python-dateutil を使用することをお勧めします。そのパーサーは、私がこれまでに投げたすべての日付形式を解析することができました。

>>> from dateutil import parser
>>> parser.parse("Tue Jun 22 07:46:22 EST 2010")
datetime.datetime(2010, 6, 22, 7, 46, 22, tzinfo=tzlocal())
>>> parser.parse("Fri, 11 Nov 2011 03:18:09 -0400")
datetime.datetime(2011, 11, 11, 3, 18, 9, tzinfo=tzoffset(None, -14400))
>>> parser.parse("Sun")
datetime.datetime(2011, 12, 18, 0, 0)
>>> parser.parse("10-11-08")
datetime.datetime(2008, 10, 11, 0, 0)

等々。 strptime()形式のナンセンスを扱うことはありません...日付を投げるだけで正しいことを行います。

Update:エラー。元の質問で、dateutilを使用しているとおっしゃいましたが、ごめんなさい。しかし、日付解析の質問があり、そのモジュールの有用性を見るときにこの質問に出くわした他の人々にとって、この答えがまだ役に立つことを願っています。

327
Joe Shaw

時間文字列は rfc 2822(電子メールの日付形式、httpヘッダー) の時刻形式に似ています。 stdlibのみを使用して解析できます。

>>> from email.utils import parsedate_tz
>>> parsedate_tz('Tue Jun 22 07:46:22 EST 2010')
(2010, 6, 22, 7, 46, 22, 0, 1, -1, -18000)

さまざまなPythonバージョンのタイムゾーン対応のdatetimeオブジェクトを生成するソリューションを参照してください: メールからのタイムゾーンを使用した日付の解析

このフォーマットでは、- EST-0500 と意味的に同等です。ただし、一般的には、 タイムゾーンの略語ではタイムゾーンを一意に識別するのに十分ではありません

9
jfs