Создайте список datetime между интервалом

Дано две даты (start_date а такжеend_date), Я хотел бы сгенерировать список других дат и времени между этими двумя датами, причем новые даты и времени разделены переменным интервалом. например каждые 4 дня между 2011-10-10 и 2011-12-12 или каждые 8 часов между сегодняшним днем и завтра 19:00.

Может быть, что-то примерно эквивалентноDateperiod PHP класс.

Какой самый эффективный способ сделать это в Python?

Ответы на вопрос(5)

Все приведенные здесь решения относятся к случаям, когда start & lt; остановить, но вы можете легко адаптировать их для обработки случаев, когда остановка & lt; Начните использовать модуль оператора, как показано на следующем коде, адаптированном из ответа @ 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

Попробуй это:

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

Пример в вопросе «каждые 8 часов между сегодняшним днем и завтрашним днем 19:00» будет написано так:

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'.

Мое решение возвращаетlist, как требуется в вопросе. Если вам не нужны все элементы одновременно, вы можете использовать генераторы, как в ответе @MartijnPieters.

Мне очень понравились оба ответа @Martijn Pieters и @ & # xD3; scar L & # xF3; 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
Решение Вопроса

использование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
 21 мая 2012 г., 20:30
Что потребуется при использовании объектов даты.
 21 мая 2012 г., 19:58
@NoctisSkytower Значение шага будетtimedelta объект.
 21 мая 2012 г., 18:50
@TylerCrompton: & quot; явное лучше, чем неявное. & Quot; Что будет увеличиваться в диапазоне: дни, секунды, микросекунды, миллисекунды, минуты, часы или недели?
 30 сент. 2013 г., 15:34
Этот генератор - самый красивый фрагмент кода Python, который я видел весь день. Спасибо!
 21 мая 2012 г., 17:37
Python должен разрешать даты вrange, Это имеет смысл. Есть причина, по которой он слабо напечатан ...

Предлагаемые здесь решения хорошо работают в течение нескольких дней, часов и т. Д., Используя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']

Это решение довольно специфично для этой конкретной потребности в форматировании ггггмм (хотя, по крайней мере, так часто встречается в моем мире) и может быть не самым эффективным ответом с большим количествомcontinues, но имеет такие преимущества, как краткость, простота понимания и не требует большого количества библиотек или кода преобразования даты.

Ваш ответ на вопрос