2012-05-21 52 views
42

2つの日付時刻(start_dateend_date)が与えられた場合、新しい日付時刻は可変間隔で区切られている。例えば2011-10-10から2011-12-12までの4日ごと、または今から明日までの8時間ごとの午後19時。間隔の間の日付時刻のリストを生成する

おそらくDateperiod PHPクラスと同等のものです。

これをPythonで達成する最も効率的な方法は何でしょうか?

答えて

65

使用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 

作品。あなたの第二の例:

>>> 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 
+0

Pythonでは 'range'で日付を許可する必要があります。それは意味をなさないでしょう。それは弱いタイプの理由があります... –

+3

@TylerCrompton: "明示的なものは暗黙的です"どの範囲で増分されますか:日、秒、マイクロ秒、ミリ秒、分、時間、または週? –

+3

@NoctisSkytowerステップ値は 'timedelta'オブジェクトになります。 –

13

これを試してみてください:問題の

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の答えのように、すべての要素を一度に必要としない場合は、ジェネレータを使用できます。

4

@Martijn Pietersと@ÓscarLópezの両方の回答が本当に好きです。 私はこれらの2つの答えの間の私の組み合わせの解決策をお勧めします。

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 
関連する問題