dateutils rrule返回相隔2个月的日期 [英] dateutils rrule returns dates that 2 months apart

查看:166
本文介绍了dateutils rrule返回相隔2个月的日期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Python的新手,也是dateutil模块的新手.我正在传递以下参数:

I am new to Python and also dateutil module. I am passing the following arguments:

disclosure_start_date = resultsDict['fd_disclosure_start_date']
disclosure_end_date = datetime.datetime.now()
disclosure_dates = [dt for dt in rrule(MONTHLY, dtstart=disclosure_start_date, until=disclosure_end_date)]

此处转换为日期时间的disclosure_start_date = 2012-10-31 00:00:00datetime.datetime(2012, 10, 31, 0, 0)

Here disclosure_start_date = 2012-10-31 00:00:00 which converted to datetime is datetime.datetime(2012, 10, 31, 0, 0)

截止日期为现在.

当我使用时:

disclosure_dates = [dt for dt in rrule(MONTHLY, dtstart=disclosure_start_date, until=disclosure_end_date)]

我每隔两个月或相隔两个月就会得到日期.结果是:

I get the dates for every other month or 2 months apart. The result is:

>>> list(disclosure_dates)
[datetime.datetime(2012, 10, 31, 0, 0), 
 datetime.datetime(2012, 12, 31, 0, 0), 
 datetime.datetime(2013, 1, 31, 0, 0), 
 datetime.datetime(2013, 3, 31, 0, 0), 
 datetime.datetime(2013, 5, 31, 0, 0), 
 datetime.datetime(2013, 7, 31, 0, 0), 
 datetime.datetime(2013, 8, 31, 0, 0), 
 datetime.datetime(2013, 10, 31, 0, 0), 
 datetime.datetime(2013, 12, 31, 0, 0), 
 datetime.datetime(2014, 1, 31, 0, 0), 
 datetime.datetime(2014, 3, 31, 0, 0), 
 datetime.datetime(2014, 5, 31, 0, 0), 
 datetime.datetime(2014, 7, 31, 0, 0), 
 datetime.datetime(2014, 8, 31, 0, 0), 
 datetime.datetime(2014, 10, 31, 0, 0), 
 datetime.datetime(2014, 12, 31, 0, 0), 
 datetime.datetime(2015, 1, 31, 0, 0), 
 datetime.datetime(2015, 3, 31, 0, 0), 
 datetime.datetime(2015, 5, 31, 0, 0), 
 datetime.datetime(2015, 7, 31, 0, 0), 
 datetime.datetime(2015, 8, 31, 0, 0), 
 datetime.datetime(2015, 10, 31, 0, 0), 
 datetime.datetime(2015, 12, 31, 0, 0), 
 datetime.datetime(2016, 1, 31, 0, 0), 
 datetime.datetime(2016, 3, 31, 0, 0), 
 datetime.datetime(2016, 5, 31, 0, 0)]

我不确定自己在做什么错.有人可以在这里指出错误吗?

I am not sure what I am doing wrong. Can someone please point out the mistake here?

推荐答案

您遇到的问题是由于datetime.datetime(2012, 10, 31, 0, 0)是该月的31号,而并非所有月份都具有31号.由于rrule模块是RFC 2445的实现.根据RFC 3.3.10:

The issue you are coming up against comes from the fact that datetime.datetime(2012, 10, 31, 0, 0) is the 31st of the month, and not all months have a 31st. Since the rrule module is an implementation of RFC 2445. Per RFC 3.3.10:

重复发生规则可能会生成具有无效日期(例如2月30日)或不存在本地时间(例如当地时间在凌晨1:00向前移动一个小时的一天中的1:30 AM)的重复发生实例.此类重复实例必须被忽略,并且绝不能被视为重复集的一部分.

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.

由于您有一个按月产生的每月规则,因此它将跳过所有少于30天或少于30天的月份.您可以在dateutil中看到关于此问题的此错误报告.

Since you have a monthly rule that generates the 31st of a month, it will skip all months with 30 or fewer days. You can see this bug report in dateutil about this issue.

如果只想每月的最后一天,则应使用bymonthday=-1参数:

If you just want the last day of the month, you should use the bymonthday=-1 argument:

from dateutil.rrule import rrule, MONTHLY
from datetime import datetime

disclosure_start_date = datetime(2012, 10, 31, 0, 0)

rr = rrule(freq=MONTHLY, dtstart=disclosure_start_date, bymonthday=-1)
# >>>rr.between(datetime(2013, 1, 1), datetime(2013, 5, 1))
# [datetime.datetime(2013, 1, 31, 0, 0),
#  datetime.datetime(2013, 2, 28, 0, 0),
#  datetime.datetime(2013, 3, 31, 0, 0),
#  datetime.datetime(2013, 4, 30, 0, 0)]

不幸的是,我认为没有一种符合RFC的方法来生成简单的RRULE,如果有必要的话,它会回到月底(例如,如果1月30日,您会怎么做-您需要2月份的备用广告,但是您不想使用bymonthday=-2,因为这会给您2月27日,依此类推.

Unfortunately, I don't think there's an RFC-compliant way to generate a simple RRULE that just falls back to the end of the month if-and-only-if it's necessary (e.g. what do you do with January 30th - you need fallback for February, but you don't want to use bymonthday=-2 because that will give you Feb. 27th, etc).

或者,对于像这样的简单月度规则,一个更好的选择可能是使用relativedelta,而 会回溯到月底:

Alternatively, for a simple monthly rule like this, a better option is probably to just use relativedelta, which does fall back to the end of the month:

from dateutil.relativedelta import relativedelta
from datetime import datetime

def disclosure_dates(dtstart, rd, dtend=None):
    ii = 0
    while True:
        cdate = dtstart + ii*rd
        ii += 1

        yield cdate
        if dtend is not None and cdate >= dtend:
            break


dtstart = datetime(2013, 1, 31, 0, 0)
rd = relativedelta(months=1)
rr = disclosure_dates(dtstart, rd, dtend=datetime(2013, 5, 1))

# >>> list(rr)
# [datetime.datetime(2013, 1, 31, 0, 0),
#  datetime.datetime(2013, 2, 28, 0, 0),
#  datetime.datetime(2013, 3, 31, 0, 0),
#  datetime.datetime(2013, 4, 30, 0, 0),
#  datetime.datetime(2013, 5, 31, 0, 0)]

请注意,我专门使用了cdate = dtstart + ii * rd,您不是只想保留运行统计",因为这将使统计显示的最短时间达到目​​标:

Note that I specifically used cdate = dtstart + ii * rd, you do not want to just keep a "running tally", as that will pin to the shortest month the tally has seen:

dt_base = datetime(2013, 1, 31)
dt = dt_base
for ii in range(5):
    cdt = dt_base + ii*rd
    print('{} | {}'.format(dt, cdt))
    dt += rd

结果:

2013-01-31 00:00:00 | 2013-01-31 00:00:00
2013-02-28 00:00:00 | 2013-02-28 00:00:00
2013-03-28 00:00:00 | 2013-03-31 00:00:00
2013-04-28 00:00:00 | 2013-04-30 00:00:00
2013-05-28 00:00:00 | 2013-05-31 00:00:00

这篇关于dateutils rrule返回相隔2个月的日期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆