Pythonで日付文字列形式を検証するにはどうすればよいですか?


143

文字列として日付入力を受け入れるpythonメソッドがあります

メソッドに渡される日付文字列がffgにあることを確認する検証を追加するにはどうすればよいですか。フォーマット:

'YYYY-MM-DD'

そうでない場合、メソッドは何らかのエラーを発生させるはずです


2
まったくチェックせず、結果として発生する例外をキャッチする方がPythonic(許可ではなく、許しを求める)のほうが多いかもしれません。
Thomas

回答:


230
>>> import datetime
>>> def validate(date_text):
    try:
        datetime.datetime.strptime(date_text, '%Y-%m-%d')
    except ValueError:
        raise ValueError("Incorrect data format, should be YYYY-MM-DD")


>>> validate('2003-12-23')
>>> validate('2003-12-32')

Traceback (most recent call last):
  File "<pyshell#20>", line 1, in <module>
    validate('2003-12-32')
  File "<pyshell#18>", line 5, in validate
    raise ValueError("Incorrect data format, should be YYYY-MM-DD")
ValueError: Incorrect data format, should be YYYY-MM-DD

8
try / exceptなしでそれを行う方法はありますか?Pythonは、例外が発生してキャッチされると、大幅に遅くなる傾向があります。
chiffa 2016

1
@chiffa日付形式の正規表現に一致させることもできますが、堅牢性が低く、例外が明確であるため推奨されません。日付の検証がボトルネックになっていますか?
jamylak 2016

1
実際にはそうではないので、最終的には、throw-exceptコンストラクトを関数でラップします。日時ライブラリに例外スローをトリガーするブール値を返す検証関数がないことにただ驚いています。
chiffa 2016

@chiffa多分彼らは意図的にブールを返す検証関数を含まなかった、それは外部ライブラリに存在するかもしれない
jamylak

2
日付にゼロパディングが必要な場合、strptimeはゼロパディングについて厳密ではないため、このソリューションは機能しません。独自の正規表現を実装するか、空白を取り除いた結果の文字列の長さを確認してから、このソリューションを利用してください。
Suparshva

65

Pythonのdateutilライブラリは(およびそれ以上)、このために設計されています。これは自動的にこれをdatetimeオブジェクトに変換し、変換ValueErrorできない場合はを発生させます。

例として:

>>> from dateutil.parser import parse
>>> parse("2003-09-25")
datetime.datetime(2003, 9, 25, 0, 0)

ValueError日付の形式が正しくない場合は、これが発生します。

>>> parse("2003-09-251")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/jacinda/envs/dod-backend-dev/lib/python2.7/site-packages/dateutil/parser.py", line 720, in parse
    return DEFAULTPARSER.parse(timestr, **kwargs)
  File "/Users/jacinda/envs/dod-backend-dev/lib/python2.7/site-packages/dateutil/parser.py", line 317, in parse
    ret = default.replace(**repl)
ValueError: day is out of range for month

dateutilほとんどの既知の形式をインテリジェントに処理でき、仕様を変更できるため、将来的に他の形式の解析が必要になった場合にも非常に役立ちます。dateutil解析例

また、必要に応じてタイムゾーンも処理します。

コメントに基づいた更新:日付があいまいな場合に、日または月のどちらを最初にするかを制御するparseキーワード引数も受け入れますdayfirst。デフォルトはFalseです。例えば

>>> parse('11/12/2001')
>>> datetime.datetime(2001, 11, 12, 0, 0) # Nov 12
>>> parse('11/12/2001', dayfirst=True)
>>> datetime.datetime(2001, 12, 11, 0, 0) # Dec 11

1
たとえば、「12月parse('13/12/2001')13日」ではなくparse('11/12/2001')「11月12日」(最初の結果では「11月12日」がここに示されます)です。
jfs 2015年

2
parse実際にdayfirstこれを制御できるキーワード引数を取ります。 parse('11/12/2001', dayfirst=True)「12月11日」を返します。dateutilのデフォルトはdayfirst=False
Jacinda

datetutil.parser.parse()あまりにも多くの時間形式を受け入れるポイントがありません(あいまいな入力のある他の例を見つけることができます)。入力がYYYY-MM-DD形式であることを検証する場合、parse()関数は間違ったツールです。
jfs 2015年

1
それは完全に有効なポイントです。本当にその特定の形式だけに制限したい場合、これはそれを実行しません、そして受け入れられた答えはすでにその場合に正しいことを行うのに素晴らしい仕事をしています。私が答えを書いたとき、著者が要求した特定の形式とは対照的に、それが有効な日付であるかどうかを検証する方法を指摘するという線に沿ってもっと考えていたと思います。探している。
Jacinda 2015年

オブジェクト.parse()に加えてフォーマット文字列を返す方法はありdatetimeますか?
citynorman 2017年

35

完全な検証関数は次のようになるはずです。

from datetime import datetime

def validate(date_text):
    try:
        if date_text != datetime.strptime(date_text, "%Y-%m-%d").strftime('%Y-%m-%d'):
            raise ValueError
        return True
    except ValueError:
        return False

ちょうど実行

datetime.strptime(date_text, "%Y-%m-%d") 

strptimeメソッドは、月と日がゼロが埋め込まれた10進数であることをチェックしないため、十分ではありません。例えば

datetime.strptime("2016-5-3", '%Y-%m-%d')

エラーなしで実行されます。


3
「あなたは技術的に正しい-最高の種類の正しい」文字列でこれを確認する必要がありました。
delrocco

これは私のテストに対しては正常に機能しますが、ドキュメントには「%d->ゼロが埋め込まれた10進数としての月の日付-> 01、02、…、31」と記載されているため、%mについても同じです。 ->月をゼロ詰めの10進数として。-> 01、02、…、12docs.python.org
/

月と日がゼロで埋められていることを確認する必要がある場合は、文字列の長さとを確認するだけで十分ではないでしょうdatetime.strptime(date_text, "%Y-%m-%d")か。
カイルバロン

17
from datetime import datetime

datetime.strptime(date_string, "%Y-%m-%d")

..これは ValueErrorこれは、互換性のないフォーマットを受け取っ場合にます。

..多くの場合、日付と時刻を扱う場合(UNIXタイムスタンプの浮動小数点数ではなく、日付時刻オブジェクトの意味で)、pytzモジュールを調べ、storage / dbの場合はすべてUTCに保存することをお勧めします。 。


2
あなたはより速く、私はそれを自分で投稿したでしょう(ideone.com/vuxDDf)。賛成票。
Tadeck 2013年

..投稿された直後に見ただけで、たまたま今日の日付時刻オブジェクトを操作していた。
B氏

-7

これが最も簡単な方法です。

date = datetime.now()
date = date.strftime('%Y-%m-%d_%H-%M-%S.jpg')

2
コードだけでなく、説明があるとよいでしょう。
lukas_o
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.