month/year 个字符串的 dateutil 解析器
dateutil parser for month/year strings
与此有点相关 post:
给定 'Sep-2020' 形式的日期字符串,dateutil.parser.parse
正确识别了月份和年份,但也添加了日期。如果提供默认值,则需要一天的时间。否则,它将只使用今天。有没有办法判断解析器是否使用了任何默认术语?
例如,我如何从下面的三个选项中判断出第一种情况中输入的日期字符串不包括日期并且使用了默认值?
>>> from datetime import datetime
>>> from dateutil import parser
>>> d = datetime(1978, 1, 1, 0, 0)
>>> parser.parse('Sep-2020', default=d)
datetime.datetime(2020, 9, 1, 0, 0)
>>> parser.parse('1-Sep-2020', default=d)
datetime.datetime(2020, 9, 1, 0, 0)
>>> parser.parse('Sep-1-2020', default=d)
datetime.datetime(2020, 9, 1, 0, 0)
``
我做了一些疯狂的事情来解决这个问题。这很疯狂,因为它不能保证与 dateutil
的未来版本一起使用(因为它依赖于 some dateutil 内部)。
目前我正在使用:python-dateutil 2.8.1
。
我写了自己的 class 并将其作为 default
传递给解析器:
from datetime import datetime
class SentinelDateTime:
def __init__(self, year=0, month=0, day=0, default=None):
self._year = year
self._month = month
self._day = day
if default is None:
default = datetime.now().replace(
hour=0, minute=0,
second=0, microsecond=0
)
self.year = default.year
self.month = default.month
self.day = default.day
self.default = default
@property
def has_year(self):
return self._year != 0
@property
def has_month(self):
return self._month != 0
@property
def has_day(self):
return self._day != 0
def todatetime(self):
res = {
attr: value
for attr, value in [
("year", self._year),
("month", self._month),
("day", self._day),
] if value
}
return self.default.replace(**res)
def replace(self, **result):
return SentinelDateTime(**result, default=self.default)
def __repr__(self):
return "%s(%d, %d, %d)" % (
self.__class__.__qualname__,
self._year,
self._month,
self._day
)
dateutils 方法现在 returns 这个 SentinelDateTime
class:
>>> from dateutil import parser
>>> from datetime import datetime
>>> from snippet1 import SentinelDateTime
>>>
>>> sentinel = SentinelDateTime()
>>> s = parser.parse('Sep-2020', default=sentinel)
>>> s
SentinelDateTime(2020, 9, 0)
>>> s.has_day
False
>>> s.todatetime()
datetime.datetime(2020, 9, 9, 0, 0)
>>> d = datetime(1978, 1, 1)
>>> sentinel = SentinelDateTime(default=d)
>>> s = parser.parse('Sep-2020', default=sentinel)
>>> s
SentinelDateTime(2020, 9, 0)
>>> s.has_day
False
>>> s.todatetime()
datetime.datetime(2020, 9, 1, 0, 0)
我把这个答案写进了一个小包里:https://github.com/foxyblue/sentinel-datetime
我找到了一个不太复杂的解决方案:
from datetime import datetime
from dataclasses import dataclass
from dateutil import parser
@dataclass
class Result:
dt: datetime
data: dict
class subparser(parser.parser):
def _build_naive(self, res, default):
naive = super()._build_naive(res, default)
return Result(dt=naive, data=res)
举个例子:
>>> PARSER = subparser()
>>> info = PARSER.parse("2020")
>>> info.data.year)
2020
>>> info.data.month
None
>>> info.dt
2020-01-10 00:00:00
与此有点相关 post:
给定 'Sep-2020' 形式的日期字符串,dateutil.parser.parse
正确识别了月份和年份,但也添加了日期。如果提供默认值,则需要一天的时间。否则,它将只使用今天。有没有办法判断解析器是否使用了任何默认术语?
例如,我如何从下面的三个选项中判断出第一种情况中输入的日期字符串不包括日期并且使用了默认值?
>>> from datetime import datetime
>>> from dateutil import parser
>>> d = datetime(1978, 1, 1, 0, 0)
>>> parser.parse('Sep-2020', default=d)
datetime.datetime(2020, 9, 1, 0, 0)
>>> parser.parse('1-Sep-2020', default=d)
datetime.datetime(2020, 9, 1, 0, 0)
>>> parser.parse('Sep-1-2020', default=d)
datetime.datetime(2020, 9, 1, 0, 0)
``
我做了一些疯狂的事情来解决这个问题。这很疯狂,因为它不能保证与 dateutil
的未来版本一起使用(因为它依赖于 some dateutil 内部)。
目前我正在使用:python-dateutil 2.8.1
。
我写了自己的 class 并将其作为 default
传递给解析器:
from datetime import datetime
class SentinelDateTime:
def __init__(self, year=0, month=0, day=0, default=None):
self._year = year
self._month = month
self._day = day
if default is None:
default = datetime.now().replace(
hour=0, minute=0,
second=0, microsecond=0
)
self.year = default.year
self.month = default.month
self.day = default.day
self.default = default
@property
def has_year(self):
return self._year != 0
@property
def has_month(self):
return self._month != 0
@property
def has_day(self):
return self._day != 0
def todatetime(self):
res = {
attr: value
for attr, value in [
("year", self._year),
("month", self._month),
("day", self._day),
] if value
}
return self.default.replace(**res)
def replace(self, **result):
return SentinelDateTime(**result, default=self.default)
def __repr__(self):
return "%s(%d, %d, %d)" % (
self.__class__.__qualname__,
self._year,
self._month,
self._day
)
dateutils 方法现在 returns 这个 SentinelDateTime
class:
>>> from dateutil import parser
>>> from datetime import datetime
>>> from snippet1 import SentinelDateTime
>>>
>>> sentinel = SentinelDateTime()
>>> s = parser.parse('Sep-2020', default=sentinel)
>>> s
SentinelDateTime(2020, 9, 0)
>>> s.has_day
False
>>> s.todatetime()
datetime.datetime(2020, 9, 9, 0, 0)
>>> d = datetime(1978, 1, 1)
>>> sentinel = SentinelDateTime(default=d)
>>> s = parser.parse('Sep-2020', default=sentinel)
>>> s
SentinelDateTime(2020, 9, 0)
>>> s.has_day
False
>>> s.todatetime()
datetime.datetime(2020, 9, 1, 0, 0)
我把这个答案写进了一个小包里:https://github.com/foxyblue/sentinel-datetime
我找到了一个不太复杂的解决方案:
from datetime import datetime
from dataclasses import dataclass
from dateutil import parser
@dataclass
class Result:
dt: datetime
data: dict
class subparser(parser.parser):
def _build_naive(self, res, default):
naive = super()._build_naive(res, default)
return Result(dt=naive, data=res)
举个例子:
>>> PARSER = subparser()
>>> info = PARSER.parse("2020")
>>> info.data.year)
2020
>>> info.data.month
None
>>> info.dt
2020-01-10 00:00:00