给定两个日期时间( start_date
和end_date
),我想以产生这两个日期之间的其他日期时间的列表,新的日期时间被由可变间隔隔开。 例如2011-10-10 2011-12-12和或每8小时之间,每4天,现在和未来之间19p.m.
也许事情大致相当于Dateperiod PHP类。
什么是Python中完成这一任务的最有效的方法是什么?
给定两个日期时间( start_date
和end_date
),我想以产生这两个日期之间的其他日期时间的列表,新的日期时间被由可变间隔隔开。 例如2011-10-10 2011-12-12和或每8小时之间,每4天,现在和未来之间19p.m.
也许事情大致相当于Dateperiod PHP类。
什么是Python中完成这一任务的最有效的方法是什么?
使用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
同时适用于日期和datetime对象。 你的第二个例子:
>>> 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
试试这个:
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
在的问题,“现在和明天至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')
请注意,对于有效值period
是那些定义relativedelta
相关信息,即: 'years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'microseconds'
。
我的解决方法返回一个列表 ,在这个问题需要。 如果你不需要马上就可以使用生成的所有元素,如@MartijnPieters答案。
我真的很喜欢通过@Martijn皮特斯和@奥斯卡·洛佩斯两个答案。 让我提出这两个答案之间我的组合解决方案。
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
这里提出的解决方案的间隔天数,小时等采用做工精良timedelta
,或任何dateutil.relativedelta
如果你想依靠第三方库支持。 但是,我想分享一下我,格式为YYYYMM每月一次的特殊情况下的解决方案,请点击这里 (但标记为这个问题的副本)。
def iterate_months(start_ym, end_ym):
for ym in range(int(start_ym), int(end_ym) + 1):
if ym % 100 > 12 or ym % 100 == 0:
continue
yield str(ym)
list(iterate_months('201710', '201803'))
输出:
['201710', '201711', '201712', '201801', '201802', '201803']
该解决方案是相当具体为YYYYMM格式此特别需要(虽然它经常出现在我的世界,至少),也有可能与大量的最有效的答案continue
S,但是具有简洁,方便的优点理解,并且不涉及许多库或日期转换代码的。
这里给出的所有解决方案到目前为止是特定的情况下,启动“停止,但你可以轻松地适应他们处理的情况下停止<开始使用操作模块如下面的代码,改编自@ MartijnPieters的回答,说明。
import datetime
import operator
def time_range(start: datetime.datetime, stop, step: datetime.timedelta):
"Imitate range function for datetimes instead of ints."
sec = step.total_seconds()
if sec == 0:
raise ValueError("step must not be 0 seconds")
if sec < 0:
compare = operator.gt
else:
compare = operator.lt
x = start
while compare(x, stop):
yield x
x += step # immutable