Python strptime()とタイムゾーン?


157

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

Tue Jun 22 07:46:22 EST 2010

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

>>> 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()タイムゾーンをうまく利用する方法はありますか?


1
ただ...すべての日付をGMTに変換できませんか?
Robus、2010

2
@Robus:うーん、私はそうすることを望んでいました-しかし、私はstrftime / datetimeが何らかの形でそれを行うことができると想定していましたか?どちらの場合も、日時がESTタイムゾーンであるか、それらが私に発生するタイムゾーンであるという事実を保存/解析する必要があります。スクリプトは、タイムゾーン情報を使用して一般的な日時を解析できる必要があります(たとえば、ETCは他のタイムゾーンでもかまいません)。
victorhooi 2010

3
ESTは、米国のタイムゾーンの省略形でもあります。(同様に、BSTは英国とブラジルの両方のタイムゾーンの省略形です。)そのような省略形は本質的にあいまいです。代わりに、UTC / GMTに関連するオフセットを使用してください。(省略形をサポートする必要がある場合は、マッピングをロケール依存にする必要があります。これは厄介なネズミ穴です。)
Donal Fellows

回答:


58

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


353

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()意味のない形式を扱う必要はありません...日付を投げるだけで、正しいことが行われます。

更新:おっと。元の質問で、を使用したとのことでdateutil、すみませんでした。しかし、この回答が、日付の解析に関する質問があり、そのモジュールの有用性を理解しているときに、この質問に出くわした他の人々にとって依然として役立つことを願っています。


多くの人々がpython-dateutilを使用する傾向があることを考えると、私はそのlibの1つの制限を指摘したいと思います。>>> parser.parse("Thu, 25 Sep 2003 10:49:41,123 -0300") Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Users/wanghq/awscli/lib/python2.7/site-packages/dateutil/parser.py", line 748, in parse return DEFAULTPARSER.parse(timestr, **kwargs) File "/Users/wanghq/awscli/lib/python2.7/site-packages/dateutil/parser.py", line 310, in parse res, skipped_tokens = self._parse(timestr, **kwargs) TypeError: 'NoneType' object is not iterable
wanghq 14

1
@wanghq最後のコンマをピリオドに置き換える必要があります。その後parser.parse("Thu, 25 Sep 2003 10:49:41.123 -0300") returns: datetime.datetime(2003, 9, 25, 10, 49, 41, 123000, tzinfo=tzoffset(None, -10800))
flyingfoxlee

7
@flyingfoxlee、はい、私はそれを理解しています。私は人々にpython-dateutilの制限を伝えたいだけです。それは魔法のことをしますが、時にはそれをしないことがあります。それで、「それに日付を投げれば、それは正しいことをします。」100%真ではありません。
wanghq 2014

4
dateutil.parser.parse("10-27-2016 09:06 AM PDT")戻り値:datetime.datetime(2016, 10, 27, 9, 6)タイムゾーンの把握に失敗しました...
HaPsantran

2
それは自分の目標次第です。dateutil parser使い方は簡単かもしれませんstrptime()が、高速です。さらに、その形式は非常に簡単に習得できます。
携挙は

9

時間の文字列は、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バージョンのタイムゾーン対応の日時オブジェクトを生成するソリューションを参照してください。メールからタイムゾーンを使用して日付を解析します

この形式でEST-0500は意味的にと同等です。一般に、タイムゾーンの省略形は、タイムゾーンを一意に識別するには不十分です。


0

この正確な問題にぶつかった。

私がやったこと:

# starting with date string
sdt = "20190901"
std_format = '%Y%m%d'

# create naive datetime object
from datetime import datetime
dt = datetime.strptime(sdt, sdt_format)

# extract the relevant date time items
dt_formatters = ['%Y','%m','%d']
dt_vals = tuple(map(lambda formatter: int(datetime.strftime(dt,formatter)), dt_formatters))

# set timezone
import pendulum
tz = pendulum.timezone('utc')

dt_tz = datetime(*dt_vals,tzinfo=tz)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.