Настроить логику логического вывода dateutil.parser
Я работаю над старыми текстовыми файлами с двузначными годами, в которых логика столетия по умолчанию 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
Но я хотел бы продолжать использовать этот модуль, так как его нечеткое совпадение, кажется, работает хорошо.
В документации не указан параметр для этого... есть ли аргумент, который я пропускаю?
3 ответа
Это не очень хорошо задокументировано, но вы можете переопределить это, используя dateutil.parser
, Второй аргумент parserinfo
объект, и метод, который вы будете иметь дело с convertyear
, Реализация по умолчанию - это то, что вызывает у вас проблемы. Вы можете видеть, что он основывает свою интерпретацию века на текущем году, плюс-минус пятьдесят лет. Вот почему вы видите переход в 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)
Вы также можете обработать извлеченные даты вручную, изменив столетие, если извлеченный год превышает указанный порог, в вашем случае - 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
Кроме написания собственного 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. Любой год, по крайней мере, 50 лет от _years
т.е. где разница
< _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. ИМХО реализация по умолчанию довольно умная.