python中的leap_Python-规则打破了leap年?

假设我想得到什么时候用规则来庆祝生日.然后,除leap日外,YEARLY的频率工作正常.实际上只有每四年一次.

有什么办法可以直接用rrule处理吗?

from datetime import datetime

from dateutil.rrule import rrule, YEARLY

n = 1

print(list(rrule(freq=YEARLY, count=n + 1, dtstart=datetime(1990, 4, 28))))

print(list(rrule(freq=YEARLY, count=n + 1, dtstart=datetime(1992, 2, 29))))

[datetime.datetime(1990, 4, 28, 0, 0), datetime.datetime(1991, 4, 28, 0, 0)]

[datetime.datetime(1992, 2, 29, 0, 0), datetime.datetime(1996, 2, 29, 0, 0)]

甚至没有提到leap日in the docs的事实使我想知道这是否仅仅是一个bug.

年复一日

这可能会有所帮助,但仅适用于2月28日:

from datetime import datetime

from dateutil.rrule import rrule, YEARLY

n = 5

bday = datetime(1990, 4, 28)

print(list(rrule(freq=YEARLY,

byyearday=bday.timetuple().tm_yday,

count=n + 1,

dtstart=bday)))

bday = datetime(1992, 2, 29)

print(list(rrule(freq=YEARLY,

byyearday=bday.timetuple().tm_yday,

count=n + 1,

dtstart=bday)))

[datetime.datetime(1990, 4, 28, 0, 0), datetime.datetime(1991, 4, 28, 0, 0), datetime.datetime(1992, 4, 27, 0, 0), datetime.datetime(1993, 4, 28, 0, 0), datetime.datetime(1994, 4, 28, 0, 0), datetime.datetime(1995, 4, 28, 0, 0)]

[datetime.datetime(1992, 2, 29, 0, 0), datetime.datetime(1993, 3, 1, 0, 0), datetime.datetime(1994, 3, 1, 0, 0), datetime.datetime(1995, 3, 1, 0, 0), datetime.datetime(1996, 2, 29, 0, 0), datetime.datetime(1997, 3, 1, 0, 0)]

解决方法:

Per RFC section 3.3.10, recurrence instances falling on invalid dates

and times are ignored rather than coerced:

Recurrence rules may generate recurrence instances with an invalid

date (e.g., February 30) or nonexistent local time (e.g., 1:30 AM on a

day where the local time is moved forward by an hour at 1:00 AM). Such

recurrence instances MUST be ignored and MUST NOT be counted as part

of the recurrence set.

由于1991年2月29日从不存在,因此它是无效日期,将被跳过.

这是过时的RFC 2445的限制,之后的版本由RFC 5545取代,而RFC 5545由RFC 7529更新.RFC 7529除其他外,将SKIP参数添加到重复规则中,该规则允许您指定OMIT(默认),BACKWARD或FORWARD . dateutil早于RFC 7529(甚至RFC 5545),并且仍在更新中.您可以在issue #285上跟踪进度.

该特殊问题已在PR #522中得到解决,但PR仍然缺少对一个后备案例的支持,并且尚未合并(截至2018年10月).

对于简单的函数返回年份返回到每月的最后一天的简单情况,我建议改为使用relativedelta(直到发布具有SKIP功能的版本):

from dateutil import relativedelta

from datetime import datetime

def yearly_rule(dtstart, count=None):

n = 0

while count is None or n < count:

yield dtstart + relativedelta.relativedelta(years=n)

n += 1

if __name__ == "__main__":

for dt in yearly_rule(datetime(1992, 2, 29), count=5):

print(dt)

# Prints:

# 1992-02-29 00:00:00

# 1993-02-28 00:00:00

# 1994-02-28 00:00:00

# 1995-02-28 00:00:00

# 1996-02-29 00:00:00

请注意,我在规则中使用的是基准日期时间(dtstart),而不是在上一个结果中加上1年.这样做的原因是relativedelta是有损的,因此在datetime(1995,2,28)中加上relativedelta(years = 1)会得到datetime(1996,2,28).

标签:python-dateutil,rrule,python

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值