django函数parse_duration()不能解析几年或几个月



我试图使用django.utils.dateparse模块的parse_duration()功能,分别代表一年或一个月的ISO 8601持续时间P1YP1M。返回的值是None。该函数的文档显示它支持ISO 8601持续时间。但是看来它支持标准没有数年或几个月,因为我可以成功解析持续时间P2DT12H60M33S,从而导致2天和46833秒的timedelta对象。这是一个错误,一个功能还是我做错了什么?

来自dateParse.py模块的源代码:

# Support the sections of ISO 8601 date representation that are accepted by
# timedelta
iso8601_duration_re = re.compile(
    r'^(?P<sign>[-+]?)'
    r'P'
    r'(?:(?P<days>d+(.d+)?)D)?'
    r'(?:T'
    r'(?:(?P<hours>d+(.d+)?)H)?'
    r'(?:(?P<minutes>d+(.d+)?)M)?'
    r'(?:(?P<seconds>d+(.d+)?)S)?'
    r')?'
    r'$'
)
# Support PostgreSQL's day-time interval format, e.g. "3 days 04:05:06". The
# year-month and mixed intervals cannot be converted to a timedelta and thus
# aren't accepted.
postgres_interval_re = re.compile(
    r'^'
    r'(?:(?P<days>-?d+) (days? ?))?'
    r'(?:(?P<sign>[-+])?'
    r'(?P<hours>d+):'
    r'(?P<minutes>dd):'
    r'(?P<seconds>dd)'
    r'(?:.(?P<microseconds>d{1,6}))?'
    r')?$'
)

第一个正则表达式用于解析ISO 8601持续时间。正如上面的iso8601_duration_re所述,仅支持timedelta接受的ISO 8601持续时间的部分。其中timedelta仅支持几周,天,小时,分钟,秒,毫秒 microseconds 。在postgres_interval_re上方的评论中也清楚地说明了这一点:

年度和混合间隔不能转换为时间码,因此不接受。

不支持数年或几个月的事实,也可以通过检查源代码来证明。例如,iso8601_duration_re正则表达式的代码仅在天,小时,分钟的情况下进行解析。几年或几个月没有指示。

我认为,由于持续时间模棱两可,因此有一个不支持数月和数年的原因。一个月可以是 28,29,30 31 天,一年可以是 365 366 天。在ISO 8601中允许这种歧义,但在timedelta对象中不允许使用这种歧义(请参阅此答案(。这是因为它在内部将持续时间存储在天中,秒 microsconds (请参阅此处(,因此, 1年timedelta,例如可以是 365天,0秒 0微秒 366天,0秒 0 microseconds <<。/p>

最新更新