dateutil.parser:dd/mm和mm/dd在同一列如何处理?
dateutil.parser: how to deal with dd/mm and mm/dd in same column?
我正在解析一个 CSV 文件,其中一列是 "datetime"。这些 CSV 格式错误,一些 CSV 文件有 28-02-2018T00:00:00.000+1000
而其他 CSV 文件有 2018-02-28T00:00:00.000+1000
.
如果我这样做:
dateutil.parser.parse(my_csv["timestamp"])
my_csv["timestamp"]
是 02-28-2018T00:00:00.000+1000
还是 2018-02-28T00:00:00.000+1000
是无关紧要的。如果我不指定格式也是正确的,因为库会识别没有 "month 28",因此它会自己选择正确的格式。
但是如何处理日期和月份对两个格式槽都有效的情况?
2018-02-04
和04-02-2018
都是同一个日期,只是一个有%m-%d
,一个有%d-%m
.
我可以告诉解析器格式是 %y-%m-%d
OR %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')
这假定 Python 3(%z
指令)。在 Python 2 中,您必须去掉最后 5 位数字并单独解析时区。
也就是说,由于第一个日期时间是 ISO8601 日期时间,您还可以使用 dateutil.parser.isoparse
作为条件的第一个分支,并使用 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)
此版本可在 Python 2 和 3 中使用,无需额外修改,但在调用 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)
我正在解析一个 CSV 文件,其中一列是 "datetime"。这些 CSV 格式错误,一些 CSV 文件有 28-02-2018T00:00:00.000+1000
而其他 CSV 文件有 2018-02-28T00:00:00.000+1000
.
如果我这样做:
dateutil.parser.parse(my_csv["timestamp"])
my_csv["timestamp"]
是 02-28-2018T00:00:00.000+1000
还是 2018-02-28T00:00:00.000+1000
是无关紧要的。如果我不指定格式也是正确的,因为库会识别没有 "month 28",因此它会自己选择正确的格式。
但是如何处理日期和月份对两个格式槽都有效的情况?
2018-02-04
和04-02-2018
都是同一个日期,只是一个有%m-%d
,一个有%d-%m
.
我可以告诉解析器格式是 %y-%m-%d
OR %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')
这假定 Python 3(%z
指令)。在 Python 2 中,您必须去掉最后 5 位数字并单独解析时区。
也就是说,由于第一个日期时间是 ISO8601 日期时间,您还可以使用 dateutil.parser.isoparse
作为条件的第一个分支,并使用 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)
此版本可在 Python 2 和 3 中使用,无需额外修改,但在调用 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)