Ответ 1
Маргинально лучше...
base = datetime.datetime.today()
date_list = [base - datetime.timedelta(days=x) for x in range(numdays)]
Я хочу создать список дат, начиная с сегодняшнего дня, и вернуться к произвольному количеству дней, скажем, в моем примере 100 дней. Есть ли лучший способ сделать это, чем это?
import datetime
a = datetime.datetime.today()
numdays = 100
dateList = []
for x in range (0, numdays):
dateList.append(a - datetime.timedelta(days = x))
print dateList
Маргинально лучше...
base = datetime.datetime.today()
date_list = [base - datetime.timedelta(days=x) for x in range(numdays)]
Pandas
отлично подходит для временных рядов в целом и имеет прямую поддержку диапазонов дат.
Например, pd.date_range()
:
import pandas as pd
datelist = pd.date_range(pd.datetime.today(), periods=100).tolist()
У этого также есть много вариантов, чтобы облегчить жизнь. Например, если вы хотите только будние дни, вы просто должны поменяться местами в bdate_range
.
См. документацию по диапазону дат
.Кроме того, он полностью поддерживает временные зоны pytz и может плавно охватывать смену летнего и весеннего времени.
ОБНОВЛЕНИЕ OP:
Если вам нужны реальные даты Python, в отличие от отметок времени Pandas:
pd.date_range(end = pd.datetime.today(), periods = 100).to_pydatetime().tolist()
Здесь используется параметр "конец", чтобы соответствовать исходному вопросу, но если вы хотите, чтобы даты по убыванию:
pd.date_range(pd.datetime.today(), periods=100).to_pydatetime().tolist()
Получить диапазон дат между указанной датой начала и окончания (оптимизирован для сложности времени и пространства):
import datetime
start = datetime.datetime.strptime("21-06-2014", "%d-%m-%Y")
end = datetime.datetime.strptime("07-07-2014", "%d-%m-%Y")
date_generated = [start + datetime.timedelta(days=x) for x in range(0, (end-start).days)]
for date in date_generated:
print date.strftime("%d-%m-%Y")
Вы можете написать функцию генератора, которая возвращает объекты даты начиная с сегодняшнего дня:
import datetime
def date_generator():
from_date = datetime.datetime.today()
while True:
yield from_date
from_date = from_date - datetime.timedelta(days=1)
Этот генератор возвращает даты, начинающиеся с сегодняшнего дня, и один за другим. Вот как сделать первые 3 даты:
>>> import itertools
>>> dates = itertools.islice(date_generator(), 3)
>>> list(dates)
[datetime.datetime(2009, 6, 14, 19, 12, 21, 703890), datetime.datetime(2009, 6, 13, 19, 12, 21, 703890), datetime.datetime(2009, 6, 12, 19, 12, 21, 703890)]
Преимущество этого подхода в понимании цикла или списка заключается в том, что вы можете вернуться столько раз, сколько хотите.
Edit
Более компактная версия с использованием выражения генератора вместо функции:
date_generator = (datetime.datetime.today() - datetime.timedelta(days=i) for i in itertools.count())
Использование:
>>> dates = itertools.islice(date_generator, 3)
>>> list(dates)
[datetime.datetime(2009, 6, 15, 1, 32, 37, 286765), datetime.datetime(2009, 6, 14, 1, 32, 37, 286836), datetime.datetime(2009, 6, 13, 1, 32, 37, 286859)]
Вы также можете использовать порядковый номер дня, чтобы сделать его более простым:
def date_range(start_date, end_date):
for ordinal in range(start_date.toordinal(), end_date.toordinal()):
yield datetime.date.fromordinal(ordinal)
Или, как указано в комментариях, вы можете создать такой список:
date_range = [
datetime.date.fromordinal(ordinal)
for ordinal in range(
start_date.toordinal(),
end_date.toordinal(),
)
]
Да, изобретать колесо.... просто найдите форум, и вы получите что-то вроде этого:
from dateutil import rrule
from datetime import datetime
list(rrule.rrule(rrule.DAILY,count=100,dtstart=datetime.now()))
Из названия этого вопроса я ожидал найти что-то вроде range()
, что позволило бы мне указать две даты и создать список со всеми датами между ними. Таким образом, не нужно вычислять количество дней между этими двумя датами, если заранее не знать об этом.
Таким образом, с риском быть слегка не по теме, этот однострочный лайнер выполняет работу:
import datetime
start_date = datetime.date(2011, 01, 01)
end_date = datetime.date(2014, 01, 01)
dates_2011_2013 = [ start_date + datetime.timedelta(n) for n in range(int ((end_date - start_date).days))]
Все кредиты !
Здесь немного другое ответное построение ответа S.Lott, которое дает список дат между двумя датами start
и end
. В приведенном ниже примере, с начала 2017 года по сегодняшний день.
start = datetime.datetime(2017,1,1)
end = datetime.datetime.today()
daterange = [start + datetime.timedelta(days=x) for x in range(0, (end-start).days)]
Немного позднего ответа, который я знаю, но у меня была такая же проблема, и я решил, что функция внутреннего диапазона Python в этом отношении немного отсутствует, поэтому я переопределил ее в модуле моего использования.
from __builtin__ import range as _range
from datetime import datetime, timedelta
def range(*args):
if len(args) != 3:
return _range(*args)
start, stop, step = args
if start < stop:
cmp = lambda a, b: a < b
inc = lambda a: a + step
else:
cmp = lambda a, b: a > b
inc = lambda a: a - step
output = [start]
while cmp(start, stop):
start = inc(start)
output.append(start)
return output
print range(datetime(2011, 5, 1), datetime(2011, 10, 1), timedelta(days=30))
Вот суть, которую я создал, из моего собственного кода, это может помочь. (Я знаю, что вопрос слишком стар, но другие могут его использовать)
https://gist.github.com/2287345
(то же самое ниже)
import datetime
from time import mktime
def convert_date_to_datetime(date_object):
date_tuple = date_object.timetuple()
date_timestamp = mktime(date_tuple)
return datetime.datetime.fromtimestamp(date_timestamp)
def date_range(how_many=7):
for x in range(0, how_many):
some_date = datetime.datetime.today() - datetime.timedelta(days=x)
some_datetime = convert_date_to_datetime(some_date.date())
yield some_datetime
def pick_two_dates(how_many=7):
a = b = convert_date_to_datetime(datetime.datetime.now().date())
for each_date in date_range(how_many):
b = a
a = each_date
if a == b:
continue
yield b, a
Если есть две даты, и вам нужен диапазон, попробуйте
from dateutil import rrule, parser
date1 = '1995-01-01'
date2 = '1995-02-28'
datesx = list(rrule.rrule(rrule.DAILY, dtstart=parser.parse(date1), until=parser.parse(date2)))
Здесь один liner для bash скриптов, чтобы получить список будних дней, это python 3. Легко измененный для любого, int в конце - это количество дней в прошлом, которое вы хотите.
python -c "import sys,datetime; print('\n'.join([(datetime.datetime.today() - datetime.timedelta(days=x)).strftime(\"%Y/%m/%d\") for x in range(0,int(sys.argv[1])) if (datetime.datetime.today() - datetime.timedelta(days=x)).isoweekday()<6]))" 10
Вот вариант, чтобы указать дату начала (или, вернее, конца)
python -c "import sys,datetime; print('\n'.join([(datetime.datetime.strptime(sys.argv[1],\"%Y/%m/%d\") - datetime.timedelta(days=x)).strftime(\"%Y/%m/%d \") for x in range(0,int(sys.argv[2])) if (datetime.datetime.today() - datetime.timedelta(days=x)).isoweekday()<6]))" 2015/12/30 10
Вот вариант для произвольной даты начала и окончания. не то, что это не очень эффективно, но хорошо для ввода цикла for в bash script:
python -c "import sys,datetime; print('\n'.join([(datetime.datetime.strptime(sys.argv[1],\"%Y/%m/%d\") + datetime.timedelta(days=x)).strftime(\"%Y/%m/%d\") for x in range(0,int((datetime.datetime.strptime(sys.argv[2], \"%Y/%m/%d\") - datetime.datetime.strptime(sys.argv[1], \"%Y/%m/%d\")).days)) if (datetime.datetime.strptime(sys.argv[1], \"%Y/%m/%d\") + datetime.timedelta(days=x)).isoweekday()<6]))" 2015/12/15 2015/12/30
Соответствие Matplotlib
from matplotlib.dates import drange
import datetime
base = datetime.date.today()
end = base + datetime.timedelta(days=100)
delta = datetime.timedelta(days=1)
l = drange(base, end, delta)
Исходя из ответов, я написал для себя это:
import datetime;
print [(datetime.date.today() - datetime.timedelta(days=x)).strftime('%Y-%m-%d') for x in range(-5, 0)]
Выход:
['2017-12-11', '2017-12-10', '2017-12-09', '2017-12-08', '2017-12-07']
Разница в том, что я получаю объект date
, а не datetime.datetime
.
Я знаю, что на это ответили, но я запишу свой ответ в исторических целях, и, поскольку я думаю, что это прямо вперед.
import numpy as np
import datetime as dt
listOfDates=[date for date in np.arange(firstDate,lastDate,dt.timedelta(days=x))]
Конечно, это не выиграет ничего, как Code-Golf, но я думаю, что это элегантно.
from datetime import datetime, timedelta
from dateutil import parser
def getDateRange(begin, end):
""" """
beginDate = parser.parse(begin)
endDate = parser.parse(end)
delta = endDate-beginDate
numdays = delta.days + 1
dayList = [datetime.strftime(beginDate + timedelta(days=x), '%Y%m%d') for x in range(0, numdays)]
return dayList
Ежемесячный генератор диапазонов дат с dateutil
datetime
и dateutil
. Просто и легко понять:
import datetime as dt
from dateutil.relativedelta import relativedelta
def month_range(start_date, n_months):
for m in range(n_months):
yield start_date + relativedelta(months=+m)
import datetime
def date_generator():
cur = base = datetime.date.today()
end = base + datetime.timedelta(days=100)
delta = datetime.timedelta(days=1)
while(end>base):
base = base+delta
print base
date_generator()