生成间隔之间的日期时间列表

Jou*_*cks 49 python datetime date list period

给定两个日期时间(start_dateend_date),我想生成这两个日期之间的其他日期时间列表,新的日期时间由可变间隔分隔.例如,2011-10-10和2011-12-12之间每4天或从现在到明天19点之间每8小时一次.

也许大致相当于Dateperiod PHP类的东西.

在Python中实现这一目标的最有效方法是什么?

Mar*_*ers 82

用途datetime.timedelta:

from datetime import date, datetime, timedelta

def perdelta(start, end, delta):
    curr = start
    while curr < end:
        yield curr
        curr += delta

>>> for result in perdelta(date(2011, 10, 10), date(2011, 12, 12), timedelta(days=4)):
...     print result
...
2011-10-10
2011-10-14
2011-10-18
2011-10-22
2011-10-26
2011-10-30
2011-11-03
2011-11-07
2011-11-11
2011-11-15
2011-11-19
2011-11-23
2011-11-27
2011-12-01
2011-12-05
2011-12-09
Run Code Online (Sandbox Code Playgroud)

适用于日期和日期时间对象.你的第二个例子:

>>> for result in perdelta(datetime.now(),
...         datetime.now().replace(hour=19) + timedelta(days=1),
...         timedelta(hours=8)):
...     print result
... 
2012-05-21 17:25:47.668022
2012-05-22 01:25:47.668022
2012-05-22 09:25:47.668022
2012-05-22 17:25:47.668022
Run Code Online (Sandbox Code Playgroud)

  • @TylerCrompton:"明确比隐含更好." 什么会增加范围:天,秒,微秒,毫秒,分钟,小时或周? (4认同)
  • @NoctisSkytower步长值将是一个"timedelta"对象. (3认同)
  • 那个生成器是我整天看到的最漂亮的Python代码.谢谢! (3认同)
  • Python应该允许`range`中的日期.这只会有意义.有一个原因是它的类型很弱...... (2认同)

Ósc*_*pez 17

试试这个:

from datetime import datetime
from dateutil.relativedelta import relativedelta

def date_range(start_date, end_date, increment, period):
    result = []
    nxt = start_date
    delta = relativedelta(**{period:increment})
    while nxt <= end_date:
        result.append(nxt)
        nxt += delta
    return result
Run Code Online (Sandbox Code Playgroud)

问题中的例子"从现在到明天19:00之间每8小时"将写成如下:

start_date = datetime.now()
end_date = start_date + relativedelta(days=1)
end_date = end_date.replace(hour=19, minute=0, second=0, microsecond=0)
date_range(start_date, end_date, 8, 'hours')    
Run Code Online (Sandbox Code Playgroud)

请注意,有效值period是为relativedelta相关信息定义的值,即:'years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'microseconds'.

我的解决方案根据问题的要求返回一个列表.如果您不需要同时使用所有元素,则可以使用生成器,如@MartijnPieters中所述.


Tod*_*dor 7

我非常喜欢@Martijn Pieters和@ÓscarLópez的两个答案.让我建议我在这两个答案之间的综合解决方案.

from datetime import date, datetime, timedelta

def datetime_range(start, end, delta):
    current = start
    if not isinstance(delta, timedelta):
        delta = timedelta(**delta)
    while current < end:
        yield current
        current += delta


start = datetime(2015,1,1)
end = datetime(2015,1,31)

#this unlocks the following interface:
for dt in datetime_range(start, end, {'days': 2, 'hours':12}):
    print dt
    print dt

2015-01-01 00:00:00
2015-01-03 12:00:00
2015-01-06 00:00:00
2015-01-08 12:00:00
2015-01-11 00:00:00
2015-01-13 12:00:00
2015-01-16 00:00:00
2015-01-18 12:00:00
2015-01-21 00:00:00
2015-01-23 12:00:00
2015-01-26 00:00:00
2015-01-28 12:00:00
Run Code Online (Sandbox Code Playgroud)