在Python中创建一系列日期

Tho*_*wne 315 python datetime date

我想创建一个日期列表,从今天开始,然后返回任意天数,例如,在我的例子中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
Run Code Online (Sandbox Code Playgroud)

S.L*_*ott 409

边缘更好......

base = datetime.datetime.today()
date_list = [base - datetime.timedelta(days=x) for x in range(numdays)]
Run Code Online (Sandbox Code Playgroud)

  • 如果您使用时区感知日期时间并且有DST的转变,这不起作用!我的意思是,当你使用开始和结束日期并在这种方式之间填写... (5认同)
  • “稍微好一点……”更正:_Lott_更好。 (4认同)
  • 我以略有不同的方式使用了此方法,以生成十个,五分钟的间隔,+ /-某个值(在我的情况下为30秒)。我只是想分享一下:`datetimes = [start + timedelta(seconds = x * 60 + randint(-30,30))对于范围(0,range_end * 5,5)中的x],其中变量`range_end = 10` (2认同)

fan*_*ous 204

Pandas 非常适合时间序列,并且直接支持日期范围.

例如pd.date_range():

import pandas as pd
datelist = pd.date_range(pd.datetime.today(), periods=100).tolist()
Run Code Online (Sandbox Code Playgroud)

它还有很多选项可以让生活更轻松.例如,如果你只想要工作日,你只需要交换bdate_range.

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

此外,它完全支持pytz时区,可以顺利跨越春/秋季DST班次.

  • 如果已经使用了大熊猫,则取消最佳答案.我要添加的唯一内容是,如果您的日期按照原始帖子向后移动,则您将使用end =参数.pd.date_range(end = pd.datetime.today(),periods = 100).tolist() (20认同)
  • 这个方法的一个问题是当你需要Python Datetime类型时...使用Pandas或numpy日期范围方法将创建Timestamp和Datetime64类型......你需要```list(map(pd.Timestamp.to_pydatetime,datelist))` ``获取日期时间类型... (5认同)

San*_*eep 61

获取指定开始日期和结束日期之间的日期范围(针对时间和空间复杂度进行了优化):

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")
Run Code Online (Sandbox Code Playgroud)

  • `(end-start+1)` 不起作用,你不能添加 timedelta 和 int。不过,您可以使用“(end-start).days + 1”。 (9认同)
  • 最初的建议是使用()而不是[]来获取date_generator.从某种意义上讲,没有必要存储整个日期数组并仅在需要时生成日期. (5认同)
  • 使用(end-start + 1)来获得结束日期. (5认同)
  • 不回答OP的问题,但这就是我追求的:) (5认同)
  • 请注意,不会生成 end_date。 (2认同)

Aym*_*ieh 42

您可以编写一个从今天开始返回日期对象的生成器函数:

import datetime

def date_generator():
  from_date = datetime.datetime.today()
  while True:
    yield from_date
    from_date = from_date - datetime.timedelta(days=1)
Run Code Online (Sandbox Code Playgroud)

此生成器从今天开始返回日期,一次向后返回一天.以下是前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)]
Run Code Online (Sandbox Code Playgroud)

这种方法优于循环或列表理解的优点是您可以根据需要返回多次.

编辑

使用生成器表达式而不是函数的更紧凑的版本:

date_generator = (datetime.datetime.today() - datetime.timedelta(days=i) for i in itertools.count())
Run Code Online (Sandbox Code Playgroud)

用法:

>>> 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)]
Run Code Online (Sandbox Code Playgroud)

  • 如果天数是任意的,则生成器是执行此操作的理想方式。 (2认同)

Hos*_*ane 31

您还可以使用day ordinal使其更简单:

def date_range(start_date, end_date):
    for ordinal in range(start_date.toordinal(), end_date.toordinal()):
        yield datetime.date.fromordinal(ordinal)
Run Code Online (Sandbox Code Playgroud)

或者按照评论中的建议,您可以创建如下列表:

date_range = [
    datetime.date.fromordinal(ordinal) 
    for ordinal in range(
        start_date.toordinal(),
        end_date.toordinal(),
    )
]
Run Code Online (Sandbox Code Playgroud)


小智 28

是的,重新发明轮子....只是搜索论坛,你会得到这样的东西:

from dateutil import rrule
from datetime import datetime

list(rrule.rrule(rrule.DAILY,count=100,dtstart=datetime.now()))
Run Code Online (Sandbox Code Playgroud)

  • 需要http://labix.org/python-dateutil.看起来不错,但几乎不值得外部依赖只是为了节省一条线. (21认同)
  • @ BeniCherniavsky-Paskin:在实现句点(日历)算法时引入细微的错误非常容易.`dateutil.rrule`实现[iCalendar RFC](https://tools.ietf.org/html/rfc5545) - 使用具有明确定义的行为的函数更容易,而不是使用几乎相同的功能的多个实现有点不同.`dateutil.rrule`允许将bug修复限制在一个地方. (5认同)
  • @ Mark0978:`rrule`这个名字不是随意的; 它来自[相应的rfc](https://tools.ietf.org/html/rfc5545) (3认同)
  • @BeniCherniavsky-Paskin https://gist.github.com/Asday/be44c79fa5ead8461e8da8da2b93c30e 这是你的错误。该日期不存在。 (2认同)

sna*_*mer 15

从这个问题的标题我希望找到类似的东西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))]
Run Code Online (Sandbox Code Playgroud)

这个答案的所有功劳!

  • 我从来没有假装这比其他答案更像是单线,也不是这是一个更好的解决方案.我展示了一段代码,它与你要求的东西略有不同,但我会很高兴在这里找到问题的标题. (4认同)
  • 与这个问题的许多其他答案一样,这并不是一个简单的说法。 (3认同)

小智 10

这里有一个稍微不同的答案美国洛特的回答,让两个日期之间的日期列表的建设关startend。在下面的示例中,从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)]
Run Code Online (Sandbox Code Playgroud)


Rob*_*ung 7

我知道有点迟到的答案,但我遇到了同样的问题,并且认为Python的内部范围函数在这方面有点缺乏,所以我在我的util模块中重写了它.

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))
Run Code Online (Sandbox Code Playgroud)

  • 我认为如果你命名函数`date_range`,这个答案会更好. (2认同)

小智 6

如果有两个日期,并且您需要范围,请尝试

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)))
Run Code Online (Sandbox Code Playgroud)


roo*_*esh 5

这是我创建的要点,从我自己的代码,这可能会有所帮助.(我知道这个问题太旧了,但其他人可以使用它)

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
Run Code Online (Sandbox Code Playgroud)


wml*_*ski 5

根据我为自己写的答案:

import datetime;
print [(datetime.date.today() - datetime.timedelta(days=x)).strftime('%Y-%m-%d') for x in range(-5, 0)]
Run Code Online (Sandbox Code Playgroud)

输出:

['2017-12-11', '2017-12-10', '2017-12-09', '2017-12-08', '2017-12-07']
Run Code Online (Sandbox Code Playgroud)

区别在于我得到的是' date'对象,而不是' datetime.datetime'一个对象。


kun*_*dan 5

一种通用方法,允许根据参数化窗口大小(日、分钟、小时、秒)创建日期范围:

from datetime import datetime, timedelta

def create_date_ranges(start, end, **interval):
    start_ = start
    while start_ < end:
        end_ = start_ + timedelta(**interval)
        yield (start_, min(end_, end))
        start_ = end_
Run Code Online (Sandbox Code Playgroud)

测试:

def main():
    tests = [
        ('2021-11-15:00:00:00', '2021-11-17:13:00:00', {'days': 1}),
        ('2021-11-15:00:00:00', '2021-11-16:13:00:00', {'hours': 12}),
        ('2021-11-15:00:00:00', '2021-11-15:01:45:00', {'minutes': 30}),
        ('2021-11-15:00:00:00', '2021-11-15:00:01:12', {'seconds': 30})
    ]
    for t in tests:
        print("\nInterval: %s, range(%s to %s)" % (t[2], t[0], t[1]))
        start = datetime.strptime(t[0], '%Y-%m-%d:%H:%M:%S')
        end =  datetime.strptime(t[1], '%Y-%m-%d:%H:%M:%S')
        ranges = list(create_date_ranges(start, end, **t[2]))        
        x = list(map(
            lambda x: (x[0].strftime('%Y-%m-%d:%H:%M:%S'), x[1].strftime('%Y-%m-%d:%H:%M:%S')),
            ranges
        ))
        print(x)
main()
Run Code Online (Sandbox Code Playgroud)

测试输出:

Interval: {'days': 1}, range(2021-11-15:00:00:00 to 2021-11-17:13:00:00)
[('2021-11-15:00:00:00', '2021-11-16:00:00:00'), ('2021-11-16:00:00:00', '2021-11-17:00:00:00'), ('2021-11-17:00:00:00', '2021-11-17:13:00:00')]

Interval: {'hours': 12}, range(2021-11-15:00:00:00 to 2021-11-16:13:00:00)
[('2021-11-15:00:00:00', '2021-11-15:12:00:00'), ('2021-11-15:12:00:00', '2021-11-16:00:00:00'), ('2021-11-16:00:00:00', '2021-11-16:12:00:00'), ('2021-11-16:12:00:00', '2021-11-16:13:00:00')]

Interval: {'minutes': 30}, range(2021-11-15:00:00:00 to 2021-11-15:01:45:00)
[('2021-11-15:00:00:00', '2021-11-15:00:30:00'), ('2021-11-15:00:30:00', '2021-11-15:01:00:00'), ('2021-11-15:01:00:00', '2021-11-15:01:30:00'), ('2021-11-15:01:30:00', '2021-11-15:01:45:00')]

Interval: {'seconds': 30}, range(2021-11-15:00:00:00 to 2021-11-15:00:01:12)
[('2021-11-15:00:00:00', '2021-11-15:00:00:30'), ('2021-11-15:00:00:30', '2021-11-15:00:01:00'), ('2021-11-15:00:01:00', '2021-11-15:00:01:12')]
Run Code Online (Sandbox Code Playgroud)