Python dateutil.parser:如何处理同一列中的dd/mm和mm/dd?

Python dateutil.parser:如何处理同一列中的dd/mm和mm/dd?,python,validation,date,python-dateutil,Python,Validation,Date,Python Dateutil,我正在分析一个CSV文件,其中一列是“datetime”。这些CSV格式不正确,一些CSV文件具有28-02-2018T00:00:00.000+1000,而其他CSV文件具有2018-02-28800:00:00.000+1000 如果我这样做: dateutil.parser.parse(my_csv["timestamp"]) 无论是my_csv[“timestamp”]是02-28-2018T00:00:00.000+1000还是2018-02-28:00:00.000+1000都是无

我正在分析一个CSV文件,其中一列是“datetime”。这些CSV格式不正确,一些CSV文件具有
28-02-2018T00:00:00.000+1000
,而其他CSV文件具有
2018-02-28800:00:00.000+1000

如果我这样做:

dateutil.parser.parse(my_csv["timestamp"])
无论是
my_csv[“timestamp”]
02-28-2018T00:00:00.000+1000
还是
2018-02-28:00:00.000+1000
都是无关的。如果我不指定格式,它将是正确的,因为库将识别没有“第28个月”,因此它将自己选择正确的格式

但是如何处理日期和月份对两种格式槽都有效的情况呢

2018-02-04
04-02-2018
都是相同的日期,但一个日期为
%m-%d
,另一个日期为
%d-%m

我可以告诉解析器格式是
%y-%m-%d
还是
%d-%m-%y


当我解析时,是否有一个额外的参数可以用来告诉解析器,如果
%y
的4位数字首先出现,那么使用
%y-%m-%d
,否则使用
%d-%m-%y

当前dateutil解析器的自定义选项很少,无法指定所需的内容

但是,如果只是这两种格式,我建议不要使用dateutil的解析器。您可以使用一个函数来解析这些日期,该函数先尝试一种格式,然后尝试另一种格式:

from datetime import datetime

def parse_myformats(dtstr):
    try:
        return datetime.strptime(dtstr, '%Y-%m-%dT%H:%M:%S.%f%z')
    except ValueError:
        return datetime.strptime(dtstr, '%d-%m-%YT%H:%M:%S.%f%z')
这假定Python3(
%z
指令)。在Python2中,必须去掉最后5位数字,并分别解析时区

也就是说,由于第一个datetime是ISO8601 datetime,您还可以将其用作条件的第一个分支,并将
parse
用作回退:

from datetime import datetime
from dateutil import parser

def parse_myformats_du(dtstr):
    try:
        return parser.isoparse(dtstr)
    except ValueError:
        return parser.parse(dtstr, dayfirst=True)
这个版本可以在Python2和Python3中工作,无需进行额外的修改,不过在调用
dateutil.parser.parse
的分支上可能会慢一些。在行动中看到它:

>>> parse_myformats('2018-02-04T00:00:00.000+1000')
datetime.datetime(2018, 2, 4, 0, 0, tzinfo=datetime.timezone(datetime.timedelta(0, 36000)))

>>> parse_myformats('04-02-2018T00:00:00.000+1000')
datetime.datetime(2018, 2, 4, 0, 0, tzinfo=datetime.timezone(datetime.timedelta(0, 36000)))

>>> parse_myformats_du('2018-02-04T00:00:00.000+1000')
datetime.datetime(2018, 2, 4, 0, 0, tzinfo=tzoffset(None, 36000))

>>> parse_myformats_du('04-02-2018T00:00:00.000+1000')
datetime.datetime(2018, 2, 4, 0, 0, tzinfo=tzoffset(None, 36000))
如果您关心速度,以下是IPython
%timeit
微基准:

%timeit parse_myformats('2018-02-04T00:00:00.000+1000')
31.8 µs ± 1.23 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit parse_myformats('04-02-2018T00:00:00.000+1000')
45.1 µs ± 2.34 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit parse_myformats_du('2018-02-04T00:00:00.00+1000')
31.3 µs ± 574 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit parse_myformats_du('04-02-2018T00:00:00.000+1000')
191 µs ± 2.99 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

还有其他格式吗?或者你提到的两种格式?这有助于解决问题。感谢您的帮助和有益的解释@Paul