2017-06-02 119 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])