使用pip上提供的最新dateutil,使用循环count规则调用DAILY方法时,我得到了奇怪的时间和与排序有关的行为。

>>> import dateutil
>>> dateutil.__version__
'2.4.2'
>>> from dateutil import rrule
>>> import datetime

>>> rules = rrule.rruleset()
>>> rules.rrule(rrule.rrule(rrule.DAILY, until=datetime.datetime(2038,1,1,0,0,0)))
>>> rules.count()
8179
>>> rules.exrule(rrule.rrule(rrule.DAILY, until=datetime.datetime(2038,1,1,0,0,0)))
>>> rules.count()
8179  # ??? Expected 0

>>> rules = rrule.rruleset()
>>> rules.exrule(rrule.rrule(rrule.DAILY, until=datetime.datetime(2038,1,1,0,0,0)))
>>> rules.rrule(rrule.rrule(rrule.DAILY, until=datetime.datetime(2038,1,1,0,0,0)))
>>> rules.count()
8179  # ??? Expected 0

>>> rules = rrule.rruleset()
>>> rules.exrule(rrule.rrule(rrule.DAILY, until=datetime.datetime(2038,1,1,0,0,0)))
>>> rules.count()
0
>>> rules.rrule(rrule.rrule(rrule.DAILY, until=datetime.datetime(2038,1,1,0,0,0)))
>>> rules.count()
0  # Now its working???

>>> rules = rrule.rruleset()
>>> rules.exrule(rrule.rrule(rrule.DAILY, until=datetime.datetime(2038,1,1,0,0,0)))
>>> rules.rrule(rrule.rrule(rrule.DAILY, until=datetime.datetime(2038,1,1,0,0,0)))
>>> rules.count()
8179  # ??? Expected 0

>>> rules = rrule.rruleset()
>>> rules.count()
0
>>> rules.rrule(rrule.rrule(rrule.DAILY, until=datetime.datetime(2038,1,1,0,0,0)))
>>> rules.count()
0  # WHAT???
>>> rules.count()
0

>>> rules = rrule.rruleset()
>>> rules.rrule(rrule.rrule(rrule.DAILY, until=datetime.datetime(2038,1,1,0,0,0)))
>>> rules.count()
8179  # IM DONE... WTF

最佳答案

答案很简单,因为创建规则集时未包含dtstart参数,当不包含该参数时,默认值为当前时间datetime.datetime.now(),并且包含直到当前微秒的分量。

因此,当您首次使用-创建规则集时

>>> rules = rrule.rruleset()
>>> rules.rrule(rrule.rrule(rrule.DAILY, until=datetime.datetime(2038,1,1,0,0,0)))
>>> rules.count()
8179


您可以从当前时间开始(不超过微秒)开始输入。

一段时间后,当您再次尝试-

rules.exrule(rrule.rrule(rrule.DAILY, until=datetime.datetime(2038,1,1,0,0,0)))


您将从当前时间开始再次创建rrule.rrule对象,因此它与您在rules中创建的上一个对象不同。

要解决此问题,您可以指定dtstart属性以确保它同时启动。

范例-

>>> rules = rrule.rruleset()
>>> rules.rrule(rrule.rrule(rrule.DAILY, until=datetime.datetime(2038,1,1,0,0,0), dtstart=datetime.datetime(now.year,now.month,now.day,0,0,0)))
>>> rules.count()
8179
>>> rules.exrule(rrule.rrule(rrule.DAILY, until=datetime.datetime(2038,1,1,0,0,0), dtstart=datetime.datetime(now.year,now.month,now.day,0,0,0)))
>>> l3 = list(rules)
>>> len(l3)
0
>>> rules.count()
0


在其他示例中,也会发生类似的问题。



鉴于上述情况,我认为dateutil代码中存在一个问题,即当您第一次调用count()时,它们实际上是在缓存规则集的计数(长度),然后仅在对其进行迭代时才重新计算其正确长度,等等

该问题出现在rrulebase类中,该类是ruleset的基类。来自的代码是(source-https://github.com/dateutil/dateutil/blob/master/dateutil/rrule.py)-

def count(self):
    """ Returns the number of recurrences in this set. It will have go
        trough the whole recurrence, if this hasn't been done before. """
    if self._len is None:
        for x in self:
            pass
    return self._len


因此,即使在应用exrule()之后,如果您以前曾调用过.count(),它也将继续返回相同的计数。

我不是100%知道它是否有错误,或是否打算这样做,很可能是错误。

我已经为此打开issue

关于python - 非常奇怪的行为集行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31957080/

10-11 02:20