自定义dateutil.parser世纪推理逻辑

时间:2016-07-25 20:41:37

标签: python python-dateutil

我正在研究具有2位数年份的旧文本文件,其中dateutil.parser中的默认世纪逻辑似乎不能正常工作。例如,对珍珠港的袭击不在dparser.parse("12/7/41")(返回2041-12-7)。

进口世纪"门槛"重新回到1900年似乎发生在66:

import dateutil.parser as dparser
print(dparser.parse("12/31/65")) # goes forward to 2065-12-31 00:00:00
print(dparser.parse("1/1/66")) # goes back to 1966-01-01 00:00:00

出于我的目的,我想设置这个"阈值"在17岁,所以:

  • "12/31/16"解析为2016-12-31(yyyy-mm-dd
  • "1/1/17"解析为1917-01-01

但我想继续使用这个模块,因为它的模糊匹配似乎运作良好。

documentation并没有确定执行此操作的参数...是否存在我忽视的争论?

3 个答案:

答案 0 :(得分:4)

这个文档没有特别详细,但您实际上可以使用dateutil.parser覆盖它。第二个参数是parserinfo对象,您将关注的方法是convertyeardefault implementation正是导致你出现问题的原因。你可以看到它是基于当前年份,即上下五十年的世纪解释。这就是你在1966年看到过渡的原因。明年它将是1967年。:)

由于您个人使用此功能并且可能具有非常特殊的需求,因此您不必具有超级通用性。如果它适合你,你可以做一些简单的事情:

from dateutil.parser import parse, parserinfo

class MyParserInfo(parserinfo):
    def convertyear(self, year, *args, **kwargs):
        if year < 100:
            year += 1900
        return year

parse('1/21/47', MyParserInfo())
# datetime.datetime(1947, 1, 21, 0, 0)

答案 1 :(得分:1)

如果提取的年份超过指定的阈值,您还可以后处理提取的日期手动更改世纪 - 在您的情况下 - 2016:

import dateutil.parser as dparser

THRESHOLD = 2016

date_strings = ["12/31/65", "1/1/66", "12/31/16", "1/1/17"]
for date_string in date_strings:
    dt = dparser.parse(date_string)
    if dt.year > THRESHOLD:
        dt = dt.replace(year=dt.year - 100)
    print(dt)

打印:

1965-12-31 00:00:00
1966-01-01 00:00:00
2016-12-31 00:00:00
1917-01-01 00:00:00

答案 2 :(得分:1)

除了编写自己的parserinfo.convertyear方法之外,您还可以通过传递标准parserinfo对象并更改_century_year设置*来自定义此方法:

from dateutil.parser import parse, parserinfo
info = parserinfo()
info._century = 1900
info._year  = 1965
parse('12/31/65', parserinfo=info)
=> 1965-12-31 00:00:00

_century指定添加到任何年份编号的默认年份,即65 + 1900 = 1965

_year指定截止年+ - 50.任何一年至少距离_years 50年,即差异为

  • < _year将切换到下个世纪
  • >= _year将切换到上个世纪

将此视为时间表:

1900          1916          1965          2015
+--- (...) ---+--- (...) ---+--- (...) ---+
^             ^             ^             ^
_century      _year - 49    _year         _year + 50

parsed years:
              16,17,...             99,00,...15

换句话说,年份00, 01, ..., 99会映射到时间范围_year - 49 .. _year + 50_year设置为此100年期间的中间位置。使用这两个设置,您可以指定您喜欢的任何截止。

*)注意这两个变量是未记录的,但是在编写本文时,最新稳定版本的parserinfo.convertyear的默认实现中使用了2.5.3。恕我直言,默认实现非常聪明。

相关问题