2017-08-09 57 views
11

我試圖驗證應該包含格式爲ISO 8601(在JSON中常用)的時間戳的字符串。如何在Python中進行驗證時要求將時間戳填充爲零?

Python的strptime似乎是非常寬容的,當涉及到確認零填充,請參見下面的代碼示例(請注意,小時缺少前導零):

>>> import datetime 
>>> s = '1985-08-23T3:00:00.000' 
>>> datetime.datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f') 
datetime.datetime(1985, 8, 23, 3, 0) 

它優雅地接受一個字符串,這不是例如,零小時填充,並且不會像我所期望的那樣拋出異常ValueError

有沒有什麼辦法強制strptime驗證它是零填充的?或者在Python的標準庫中是否還有其他內置函數呢?

我想避免寫我自己regexp爲此。

+1

您可以手動驗證字符串:檢查'.'是否處於正確的位置('str [19] =='。'):如果不是,則存在零填充問題。 – TemporalWolf

+0

也許不是這個具體的問題,但是在ISO上討論過與ISO8601有關的其他問題。一個問題提到https://pypi.python.org/pypi/iso8601,然後提到http://labix.org/python-dateutil。 –

回答

4

已經有在解析ISO8601或RFC3339日期答案/用Python strptime()是不可能的:How to parse an ISO 8601-formatted date? 所以,爲了回答你的問題,沒有辦法在標準的Python庫中進行可靠的解析 一個約會。 關於正則表達式的建議,日期字符串像

2020-14-32T45:33:44.123 

將導致有效日期。有很多Python模塊(如果您在https://pypi.python.org上搜索「iso8601」),但構建一個完整 ISO8601 Validator需要諸如閏秒,可能的時區偏移值列表等等。

0

要強制strptime爲您驗證前導零,您必須將自己的文字添加到Python的_strptime._TimeRE_cache。這個解決方案非常黑,很可能不是很便攜,並且需要編寫一個RegEx - 儘管只用於時間戳的小時部分。

該問題的另一種解決方案是編寫自己的函數,該函數使用strptime並將解析的日期轉換回字符串並比較兩個字符串。這個解決方案是可移植的,但缺乏明確的錯誤信息 - 你將無法區分幾小時,幾分鐘,幾秒內丟失的前導零。

0

我能想到的除了搞Python內部之外,唯一能想到的就是通過知道你在找什麼來測試格式的有效性。

所以,如果我把它弄好,格式是'%Y-%m-%dT%H:%M:%S.%f',應該是零填充。 然後,你知道你正在尋找和再現預期的結果字符串的確切長度..

import datetime 
s = '1985-08-23T3:00:00.000' 

stripped = datetime.datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f') 
try: 
    assert len(s) == 23 
except AssertionError: 
    raise ValueError("time data '{}' does not match format '%Y-%m-%dT%H:%M:%S.%f".format(s)) 
else: 
    print(stripped) #just for good measure 

>>ValueError: time data '1985-08-23T3:00:00.000' does not match format '%Y-%m-%dT%H:%M:%S.%f 
+0

通過這種方法,您必須小心「去除()」您的輸入,否則尾隨的換行符可能會給您一個錯誤的良好值。 – TemporalWolf

+0

然後你會遇到'ValueError:未轉換的數據依然存在:'由於strptime的優點。或者我在這裏丟失了什麼? – Uvar

1

你說你想避免一個正則表達式,但其中一個正則表達式是這其實是問題的類型適當。正如您發現的那樣,strptime對於它將接受的輸入非常靈活。然而,對於這個問題的正則表達式是比較容易組成:

import re 

date_pattern = re.compile(r'\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}') 
s_list = [ 
    '1985-08-23T3:00:00.000', 
    '1985-08-23T03:00:00.000' 
] 
for s in s_list: 
    if date_pattern.match(s): 
     print "%s is valid" % s 
    else: 
     print "%s is invalid" % s 

輸出

1985-08-23T3:00:00.000 is invalid 
1985-08-23T03:00:00.000 is valid 

嘗試在repl.it

相關問題