2013-06-01 89 views
63

我有一個Python方法,它接受日期輸入爲字符串如何在Python中驗證日期字符串格式?

如何添加驗證以確保傳遞給方法的日期字符串在ffg中。格式:

'YYYY-MM-DD' 

,如果它不是,方法應該提高某種錯誤

+2

這可能是更Python(請求原諒,而不是許可)沒有在所有檢查,並捕捉髮生的任何由此產生的異常。 – Thomas

+0

相關:[在python中,如何檢查日期是否有效?](http://stackoverflow.com/q/9987818/55075) – kenorb

回答

101
>>> 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 
+0

有沒有辦法做到這一點,沒有嘗試/除外?當異常被引發和捕獲時,Python往往會顯着減速。 – chiffa

+1

@chiffa你可以匹配一個日期格式的正則表達式,但不推薦使用它,因爲它不夠健壯,異常更清晰。你確定日期驗證是你的瓶頸嗎? – jamylak

+0

不是真的,所以最後我會將throw-except構造包裝在一個函數中。我只是感到驚訝,沒有布爾返回驗證函數會觸發日期時間庫中的異常拋出。 – chiffa

34

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 parsing examples

它也處理時區,如果你需要的話。

更新基於意見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 
+0

它可能接受太多例如,'parse('13/12/2001')'是「12月13日」,但是「解析」('11/12/2001')'是「11月12日」(第一個結果暗示「12月11日」)。 – jfs

+0

'parse'實際上需要一個'dayfirst'關鍵字參數,它允許你控制這個參數。 '解析('11/12/2001',dayfirst = True)'將返回「12月11日」。 dateutil的默認值是'dayfirst = False' – Jacinda

+0

你錯過了'datetutil.parser.parse()'接受太多時間格式的問題(你可以找到其他含有模糊輸入的例子)。如果你想驗證你的輸入是YYYY-MM-DD格式,那麼'parse()'函數是錯誤的工具。 – jfs

11
from datetime import datetime 

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

..this提出了一個ValueError如果它接收到不兼容的格式。

..如果你處理的日期和時間很多(在日期時間對象的意義上,而不是unix timestamp浮點數),查看pytz模塊和storage/db是一個好主意,以UTC存儲所有內容。

+2

你的速度更快,我自己也發佈了它(http://ideone.com/vuxDDf)。給予好評。 – Tadeck

+0

..只是在發佈之後才發現它,並且恰好今天已經使用了datetime對象。 –

6

我覺得完全驗證功能應該是這樣的:

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方法不檢查的那個月和日月份是零填充十進制數字。例如

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

將被執行而沒有錯誤。

+1

「你在技術上是正確的 - 最好的一種正確的。」我需要確保我的字符串。 – delrocco

0

這是最簡單的方法:

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

所提問題的日期格式錯誤 –