web-dev-qa-db-ja.com

これは、dateutilでタイムゾーンを設定する正しい方法ですか?

>>> import dateutil.parser, dateutil.tz as tz
>>> dateutil.parser.parse('2017-08-09 10:45 am').replace(tzinfo=tz.gettz('America/New_York'))
datetime.datetime(2017, 8, 9, 10, 45, tzinfo=tzfile('/usr/share/zoneinfo/America/New_York'))

それは本当に解析のデフォルトのタイムゾーンを設定する方法ですか? parser および examples のドキュメントを読みましたが、「これがdateutil.parser.parseのデフォルトのタイムゾーンを設定する方法です。 "、またはそのようなものですら。

これは機能しますが、ゾーンが指定されていると、間違った処理を行う場合があります。それは私たちがこれをすべきだという意味ですか?

>>> d = dateutil.parser.parse('2017-08-09 10:45 am +06:00')
>>> d = d.replace(tzinfo=d.tzinfo or tz.gettz('America/Chicago'))

それも不格好だからです。

解析時にデフォルトのタイムゾーンを設定するための推奨される方法は何ですか?

6
Wayne Werner

これを行うには、基本的に2つの「正しい」方法があります。これはdateutilのIssue Trackerで Issue#94 として表示され、「デフォルトのタイムゾーンを設定する」は範囲外であると判断されたことがわかります。とにかくパーサーから返された情報を使用して簡単に実行できます(したがって、パーサー自体に組み込む必要はありません)。 2つの方法は次のとおりです。

  1. タイムゾーンのあるdefault日付を指定します。 defaultの日付が何であるかを気にしない場合は、日付リテラルを指定してそれで済ませることができます。動作を基本的にdateutilのデフォルトの動作と同じにしたい場合(「今日の深夜の日付」から欠落している要素を置き換える)、少し定型的なものが必要です。

    from datetime import datetime, time
    from dateutil import tz, parser
    default_date = datetime.combine(datetime.now(),
                                    time(0, tzinfo=tz.gettz("America/New_York")))
    dt = parser.parse(some_dt_str, default=default_date)
    
  2. .replaceで2番目の方法を使用します。

    from dateutil import parser
    def my_parser(*args, default_tzinfo=tz.gettz("America/New_York"), **kwargs):
        dt = parser.parse(*args, **kwargs)
        return dt.replace(tzinfo=dt.tzinfo or default_tzinfo)
    

この最後のものはおそらく最初のものよりもわずかにクリーンですが、タイトなループで実行するとパフォーマンスがわずかに低下します(最初のものはデフォルトの日付を一度作成するだけでよいため)が、dateutilのパーサーは実際にはかなり遅いです。したがって、タイトなループで実行している場合、余分な日付の構築はおそらく問題のほとんどではありません。

4
Paul

Paulのコメントを具体化する-datetimeleast年、月、日でなければならないため、dateutilにはすでに使用するデフォルトがあります。

>>> from datetime import datetime
>>> datetime.now()
datetime.datetime(2017, 10, 13, 15, 16, 13, 548750)
>>> dateutil.parser.parse('2017')
datetime.datetime(2017, 10, 13, 0, 0)

これを考えると、適切な選択は、タイムゾーンを含み、現在の日付、または意味のある日付のいずれかであるdefaultを作成することです。

>>> dateutil.parser.parse('2017', default=datetime(2017, 10, 13, tzinfo=tz.gettz('America/New_York')))

当然、デフォルトをdefault_datetimeなどの適切なものとして保存すると、次のようになります。

>>> dateutil.parser.parse('2017', default=default_datetime)
2
Wayne Werner