我试图用dateutil.rrule
找到给定datetime
之前的第一个匹配项
尝试1:
我的第一次尝试是:
dtstart = datetime(2010, 1, 1, 0, 00)
myRule = rrule(freq=WEEKLY, dtstart=dt)
result = myRule.before(dt)
它不起作用,变量结果将等于None
如果我是对的,当您执行rrule
的方法before
时,您将不幸地在传递给参数dtstart
的datetime
之后进行搜索。
基本上,我之前的代码可以表示为这样的时间线:
[A区][TARGET]
[B区][dtstart]
[C区]
在这个时间轴中,只有[zone C]被解析,所以我的目标永远找不到
尝试2:
我的第二次尝试很有效,但确实很难看。。。其目的是将[dtstart]
移到[TARGET]
之前,以获得如下所示的时间线:
[A区][dtstart]
[B区][TARGET]
[C区]
要做到这一点,我必须找出一个dtstart
,这是肯定的,在目标之前,不要太远,以避免性能问题。因此[zone B]必须存在,但必须尽可能短
seekdt = datetime(2010, 1, 1, 0, 00)
startdt = seekdt - timedelta(days=7) # While my rrule.freq is WEEKLY and the interval is 1 (default), I'm sure that my startdt will be before my target if I shift it by 7 days
myRule = rrule(freq=WEEKLY, dtstart=startdt)
result = muRule.before(seekdt)
正如我所说,这个解决方案真的很难看。。。此外,如果我有一个更复杂的rrule或rruleset,那么很难定义最佳移位
最好的解决方案,但实际上并不存在……:'(:
如果rrule可以使用dtend而不是dtstart,那就太完美了。我可以这样做:
dtstart = datetime(2010, 1, 1, 0, 00)
myRule = rrule(freq=WEEKLY, dtend=dt)
result = muRule.before(dt)
问题:
如果没有任何简单的功能,我会感到奇怪。有什么优雅的方法可以达到我的目标吗?我的尝试2是最好的解决方案吗
换句话说(同样有问题,但作为练习):
你如何找到2月13日的最后一个星期五(基于今天)
假设dateutils.rrule不提供开箱即用的功能,我认为您自己的解决方案很接近,但还没有完全实现。您需要在正确的时间间隔内倒退,并计算目标日期之前的最后结果。如果没有完全指定规则,并且结果继承了原始日期的某些属性,则“正确间隔”很重要
例如,如果您的规则是
MONTHLY
,那么您必须确保您在本月的同一天或上一个月结束。这很棘手,因为前一个月甚至可能没有这一天,例如,从7月31日开始倒退1个月会给你一个错误的结果——在这种情况下,你必须一直追溯到5月31日。另一个例子:从2月29日开始,按照YEARLY
规则向后走——你必须向后走4年(有时甚至8年)此外,您必须确保跳过规则中指定的间隔数。对于每两周一次的规则(例如
FREQ=WEEKLY;INTERVAL=2
),您必须在时间上返回两周,否则您的结果将出现在错误的一周另一个需要注意的陷阱是间隔可能是空的。为了举一个例子,您可能需要倒退几周才能找到与
FREQ=WEEKLY;BYDAY=FR;BYMONTHDAY=13
匹配的日期。你必须为此做好准备,继续向后走,直到找到一个非空的我不熟悉dateutil.rrule,因此下面是一些伪代码,可以为您指明方向:
请注意,规则的指定方式很可能不会产生单一结果。所以,如果您的代码接受用户输入,您应该为此做好准备,并避免无限循环
处理继承属性的另一种方法是,如果某些字段不存在,则调整规则。例如,对于不带
BYMONTHDAY
的MONTHLY
规则,可以将rule.bymonthday
设置为目标日期的monthday。但是您必须设置的字段因FREQ
而异,因此这有其自身的缺陷相关问题 更多 >
编程相关推荐