2012-05-21 3 views
42

두 datetime (start_dateend_date)이 주어진다면,이 두 날짜 사이에 다른 datetimes의 목록을 생성하고 싶습니다, 새로운 datetimes는 가변 간격으로 구분됩니다. 예 : 2011-10-10과 2011-12-12 사이의 4 일마다 또는 현재와 내일 사이의 매 8 시간마다 19p.m.간격 사이의 datetimes 목록 생성

Dateperiod PHP 클래스와 대략 동일 할 수도 있습니다.

파이썬에서이 작업을 수행하는 가장 효율적인 방법은 무엇입니까?

답변

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

파이썬은 '범위'에 날짜를 허용해야합니다. 그것은 단지 의미가 있습니다. 그 이유는 그것이 약한 타입의 ... –

+3

@TylerCrompton : "암시 적보다 낫다." 범위에서 증가 할 수있는 것은 일, 초, 마이크로 초, 밀리 초, 분, 시간 또는 주입니까? –

+3

@NoctisSkytower 단계 값은 'timedelta'객체입니다. –

13

이 시도 :

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')  
:

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시 사이의 8 시간마다"은 다음과 같이 기록 될 것입니다

period의 유효한 값은 relativedelta에 대해 정의 된 값인 'years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'microseconds'입니다.

내 솔루션은 질문에 따라 목록을 반환합니다. @MartijnPieters가 대답하는 것처럼 모든 요소를 ​​한 번에 필요로하지 않으면 생성기를 사용할 수 있습니다.

4

@Martijn Pieters와 @ Óscar Ló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