2017-06-02 117 views
2

我有以下字符串輸入:24052017。當我嘗試做:使用dateutil.parser轉換DDMMYYYY

>>>dateutil.parser.parse("24052017") 

它告訴我,month must be in 1..12

我甚至想這樣做:

>>>dateutil.parser.parse("24052017", firstday=True) 

它給了我正是個相同的結果。

似乎發生的事情是,它不喜歡沒有空格或分隔符的事實。它正確地讀了一天,但是當它涉及到這個月它讀取0520。至少這是我懷疑的。

如何在不操縱字符串的情況下使用dateutil.parser轉換此特定輸入?

回答

4

dateutil目前不支持此格式。一般來說,如果您知道日期的格式並且沒有時區,則應該使用datetime.datetime.strptime來解析日期,因爲dateutil.parser.parse有相當多的開銷,它試圖找出日期的格式而且,關鍵的是,它可能會導致格式錯誤。

有一個針對正在辯論的2.6.0分支的拉請求添加這種格式,你可以找到它here, ondateutil's github。反對此的主要理由是,如果您試圖解析一系列日期,它將將12052017解釋爲「2017年12月5日」,但13052017解釋爲「2017年5月13日」。 (也就是說,您現在確實有相同的不一致性,因爲第一個日期將解析爲2017年12月5日,但第二個日期將簡單失敗)。

如果你不知道字符串的格式,但你知道,如果是你希望它被解釋爲DDMMYYYY,現在最好的辦法是硬的8位數字的日期代碼異常到您的解析器:

from dateutil.parser import parse as duparse 
from datetime import datetime 

def parse(dtstr, *args, **kwargs): 
    if len(dtstr) == 8 and dtstr.isnumeric(): 
     return datetime.strptime(dtstr, '%d%m%Y') 
    else: 
     return duparse(dtstr, *args, **kwargs) 

有一些滯銷計劃努力爲dateutil提供更靈活和可擴展的解析器,但沒有太多的工作已在此沒有完成。

6

如果你不珍貴有關使用dateutil,你可以用datetime.datetime.strptime做到這一點:

from datetime import datetime 

print datetime.strptime("24052017", '%d%m%Y') 

這將返回(在YYYY-MM-DD HH:MM:SS)

2017-05-24 00:00:00 
+0

謝謝您的回答。我知道我可以這樣做,但是,我想知道是否有一種方法可以使用'dateutil.parser' :) – Renier

1

那麼,dateutil.parser.parse需要一些關於你試圖解析的日期格式的提示;由於缺乏這種提示,它會採用YYYYMMDD格式,因此您的輸入等於2405-20-17;要麼重新排列你的字符串來讀取20170524或使用分隔符:dateutil.parser.parse("24.05.2017")將工作。

+0

即使我指定'dayfirst = True',它仍然會給我同樣的錯誤。對此有何想法? – Renier

+0

@雷尼請重新閱讀Blotosmetek的回答 –

+0

所以我將不得不操縱輸入,然後添加'提示'?即使我指定'dayfirst = True'? – Renier

-1

不能使用dateutil.parser.parse而不操作字符串。

import dateutil.parser 

parserinfo = dateutil.parser.parserinfo(dayfirst=True, yearfirst=False) 
print dateutil.parser.parse("24052017", parserinfo) 

> Traceback (most recent call last): 
> File "python", line 4, in <module> 
> ValueError: month must be in 1..12 

http://dateutil.readthedocs.io/en/stable/parser.html#dateutil.parser.parserinfo

內部parserinfo,在JUMP是分離器的陣列。

# m from a.m/p.m, t from ISO T separator 
JUMP = [" ", ".", ",", ";", "-", "/", "'", 
     "at", "on", "and", "ad", "m", "t", "of", 
     "st", "nd", "rd", "th"] 

串是不是它的一部分。

+0

我只是提醒你,問題是「如何使用dateutil.parser轉換此特定輸入,而不處理字符串?」每個人都在操縱這個字符串。 – M07

+0

你的回答不是特別有用,但更麻煩的是你的推理是錯誤的。如果這些值不是分開的,則它們會被計爲一個標記,如果標記爲8位數,解析器將嘗試確定其是否爲'YYYYMMDD'或'MMDDYYYY',但不檢查'DDMMYYYY'。我的答案和asongtoruin的答案都給出了不操縱字符串的替代方法。 – Paul

+0

你的選擇是在某些情況下使用datetime.strptime ...所以,爲什麼不使用asongtoruin建議的datetime.strptime?除了有更復雜的解決方案。沒有人用dateutil.parser方法提供了一個單行的答案,因爲沒有解決方案。我的回答是唯一正確的,解決問題的替代方案已由asongtoruin提供。 – M07

1

您應該使用datetime庫,如asongtoruin' answer中所述。但是,如果您想使用dateutil.parser來實現此目的,則必須先將字符串轉換爲dateutil可理解的格式。下面是例子:

>>> d_string = "24052017" 

#             to consider day before month v 
>>> dateutil.parser.parse('/'.join([d_string[:2], d_string[2:4],d_string[4:]]), dayfirst=True) 
datetime.datetime(2017, 5, 24, 0, 0) 

這被傳遞到dateutil.parser.parse(...)之前,我轉換"24052017""24/05/2017"

+1

仍然容易出錯,考慮'03/06/2017' - 是6月3日還是3月6日? –

+0

@Błotosmętek感謝您指出這一點!我有這種想法,但在編寫答案時未提及:) –

+0

這就是爲什麼我都是ISO格式(YYYYMMDD hhmmss);它也使按日期排序更容易;-) –

1

如果你堅持要用dateutil.parser.parse,我建議去這樣:

d = '24052017' 
dateutil.parser.parse(d[4:8]+d[2:4]+d[0:2])