如何在Python中经过数天,数小时,数周和数月的时间跨度迭代?

时间:2020-03-06 14:55:44  来源:igfitidea点击:

如何在几天,几小时,几周或者几个月后迭代一个时间跨度?

就像是:

for date in foo(from_date, to_date, delta=HOURS):
    print date

其中foo是一个函数,返回一个迭代器。我一直在查看日历模块,但是它仅适用于特定的一年或者一个月,而不适用于日期之间。

解决方案

该库提供了一个方便的日历工具:mxDateTime,应该足够了:)

我认为Python库中没有方法,但是我们可以使用datetime模块轻松地自己创建一个方法:

from datetime import date, datetime, timedelta

def datespan(startDate, endDate, delta=timedelta(days=1)):
    currentDate = startDate
    while currentDate < endDate:
        yield currentDate
        currentDate += delta

然后,我们可以像这样使用它:

>>> for day in datespan(date(2007, 3, 30), date(2007, 4, 3), 
>>>                     delta=timedelta(days=1)):
>>>     print day
2007-03-30
2007-03-31
2007-04-01
2007-04-02

或者,如果我们希望减小增量,请执行以下操作:

>>> for timestamp in datespan(datetime(2007, 3, 30, 15, 30), 
>>>                           datetime(2007, 3, 30, 18, 35), 
>>>                           delta=timedelta(hours=1)):
>>>     print timestamp
2007-03-30 15:30:00
2007-03-30 16:30:00
2007-03-30 17:30:00
2007-03-30 18:30:00

对于几个月的迭代,我们需要一个不同的方法,因为timedelta不能表示"一个月"。

from datetime import date

def jump_by_month(start_date, end_date, month_step=1):
    current_date = start_date
    while current_date < end_date:
        yield current_date
        carry, new_month = divmod(current_date.month - 1 + month_step, 12)
        new_month += 1
        current_date = current_date.replace(year=current_date.year + carry,
                                            month=new_month)

(注意:由于模数运算,我们必须从月份中减去1,然后将其加回到new_month,因为datetime.date`s中的月份从1开始。)

使用dateutil及其rrule实现,如下所示:

from dateutil import rrule
from datetime import datetime, timedelta

now = datetime.now()
hundredDaysLater = now + timedelta(days=100)

for dt in rrule.rrule(rrule.MONTHLY, dtstart=now, until=hundredDaysLater):
    print dt

输出为

2008-09-30 23:29:54
2008-10-30 23:29:54
2008-11-30 23:29:54
2008-12-30 23:29:54

将"每月"替换为"每年","每月","每周","每天","每小时","半年"或者"第二"。替换dtstart,直到我们想要的任何datetime对象。

此食谱具有在所有情况下都可以工作的优势,包括MONTHLY。我能发现的唯一警告是,如果我们传递了一个并非所有月份都存在的天数,则会跳过那些月份。

我们应该修改此行以使其正常工作:

current_date = current_date.replace(year = current_date.year +进位,month = new_month,day = 1)

;)