Создание всех дат в заданном диапазоне в python

У меня есть две строковые переменные, которые содержат даты в формате yyyy-mm-dd следующим образом:

date1 = '2011-05-03'
date2 = '2011-05-10'

Я хочу написать код, который генерирует все даты в диапазоне date1 до date2. Как это можно сделать в Python?

Ответ 1

Даты могут сравниваться друг с другом точно так же, как цифры, и вы можете использовать математику, связанную с датами, с объектом datetime.timedelta. Там нет причин использовать dateutil здесь, и нет причин для жесткого кодирования числа итераций a la 'range (9)'. Это действительно похоже на то, как вы справляетесь с обычными старыми числами.

>>> import datetime
>>> date1 = '2011-05-03'
>>> date2 = '2011-05-10'
>>> start = datetime.datetime.strptime(date1, '%Y-%m-%d')
>>> end = datetime.datetime.strptime(date2, '%Y-%m-%d')
>>> step = datetime.timedelta(days=1)
>>> while start <= end:
...     print start.date()
...     start += step
... 
2011-05-03
2011-05-04
2011-05-05
2011-05-06
2011-05-07
2011-05-08
2011-05-09
2011-05-10
>>> 

Ответ 2

from dateutil import rrule, parser

date1 = '2011-05-03'
date2 = '2011-05-10'

dates = list(rrule.rrule(rrule.DAILY,
                         dtstart=parser.parse(date1),
                         until=parser.parse(date2)))

print dates

Поскольку dateutil не является стандартной библиотекой, вам придется установить его как отдельный пакет. Подробнее см. Документацию относительно формата (особенно dayfirst и yearfirst).

Ответ 3

Pandas отлично подходит для временных рядов в целом и имеет прямую поддержку как для диапазонов дат, так и для синтаксического анализа даты (он автоматически).

import pandas as pd
date1 = '2011-05-03'
date2 = '2011-05-10'
mydates = pd.date_range(date1, date2).tolist()

В нем также есть много возможностей сделать жизнь проще. Например, если вам нужны только будние дни, вы просто замените bdate_range.

См. http://pandas.pydata.org/pandas-docs/stable/timeseries.html#generating-ranges-of-timestamps

Ответ 4

Мне нравится этот, потому что он интуитивно понятен и дает массив строк даты.

import re
import datetime

def datetime_to_str_date(dt):
    return re.sub(r'\T.+$','', dt.isoformat())

start_date = datetime.datetime.strptime('2016-01-01', '%Y-%m-%d')
end_date = datetime.datetime.today()
num_of_days = (end_date - start_date).days

date_list = map(
        datetime_to_str_date, 
        [start_date + datetime.timedelta(days=x) for x in range(0, num_of_days)]
)

Ответ 5

import datetime
real_date1 = datetime.date(*[int(x) for x in date1.split('-')])
real_date2 = datetime.date(*[int(x) for x in date2.split('-')])
date_range =  real_date2 - real_date1
dates = list()
for days in xrange(date_range.days):
    dates.append(real_date1 + datetime.timedelta(days))

print dates

Ответ 6

import time

def dates_between(start, end):
  start_epoch = int(time.mktime(time.strptime(start, "%Y-%m-%d")))
  end_epoch = int(time.mktime(time.strptime(end, "%Y-%m-%d"))) + 1 #include end
  return range(start_epoch, end_epoch, 86400)

Ответ 7

Предполагая, что ваши даты уже являются классами datetime.date, вы можете использовать .fromordinal и .toordinal для создания этого oneliner.

from datetime import date

start_date = date(2011, 5, 3)
end_date = date(2011, 5, 10)

[date.fromordinal(i) for i in range(start_date.toordinal(), end_date.toordinal())]

Результат является эксклюзивным end_date. Используйте end_date.toordinal() + 1 для диапазона включительно end_date.

Ответ 8

>>> for a in range(9):
...     print(datetime.date(2011, 05, 03) + datetime.timedelta(a))
...
2011-05-03
2011-05-04
2011-05-05
2011-05-06
2011-05-07
2011-05-08
2011-05-09
2011-05-10
2011-05-11

Я не слишком уверен в том, что синтаксический анализ строк был целым или просто так, как вы начали задавать вопрос. Если это так, пожалуйста, игнорируйте ответ как упрощенное