Python 生成两个日期之间的日期列表

87
我想生成两个日期之间的日期列表,并以字符串格式存储在一个列表中。这个列表对于与我拥有的其他日期进行比较非常有用。
我的代码如下:
from datetime import date, timedelta

sdate = date(2019,3,22)   # start date
edate = date(2019,4,9)   # end date

def dates_bwn_twodates(start_date, end_date):
    for n in range(int ((end_date - start_date).days)):
        yield start_date + timedelta(n)
print(dates_bwn_twodates(sdate,edate))

我的目前产出:
<generator object dates_bwn_twodates at 0x000002A8E7929410>

我的预期输出:
['2019-03-22',.....,'2019-04-08']

我的代码有问题。

2
使用yield表示您的函数将返回一个生成器。 如果您想运行生成器以获取所有元素,可以执行print(list(dates_bwn_twodates(sdate, edate))) - FiddleStix
@anky_91 我需要建议。如果我想检查一个日期是否在上面的列表中?如何与列表进行比较? - Mainland
@Mainland 如果您的目标是检查一个日期是否在另外两个日期之间,那么列表是不必要的,有更简单的方法来完成这个检查。 - ALollz
@ALollz 是的!目标是手头有一份日期列表(存储在一个列表中),并比较其中的日期是否已经存在于列表中。我认为这是唯一的方法。如果有任何其他解决方案,我将不胜感激。 - Mainland
@Mainland,针对你上一个被删除的问题,可以这样实现: print(round(df["value"].min(), -2))print(round(df["value"].max(), -2) + 100) - Anton
@Anton,它没有给出正确的值。我刚试过了。 - Mainland
10个回答

127
您可以使用pandas.date_range()来完成此操作:
import pandas
pandas.date_range(sdate,edate-timedelta(days=1),freq='d')

DatetimeIndex(['2019-03-22', '2019-03-23', '2019-03-24', '2019-03-25',
           '2019-03-26', '2019-03-27', '2019-03-28', '2019-03-29',
           '2019-03-30', '2019-03-31', '2019-04-01', '2019-04-02',
           '2019-04-03', '2019-04-04', '2019-04-05', '2019-04-06',
           '2019-04-07', '2019-04-08'],
          dtype='datetime64[ns]', freq='D')

@anky 如果我想要得到日期列表,例如 ['20190322','20190323',.......],应该怎么做?谢谢 :-) - R S John
4
在末尾添加[.tolist()](https://pandas.pydata.org/docs/reference/api/pandas.Index.tolist.html)。 - anky
6
尝试在最后使用.strftime('%Y%m%d').tolist()。基本上,根据您的需要创建日期格式,然后转换为列表,文档在这里:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DatetimeIndex.strftime.html。 - anky
4
我对这个被标记为“正确”的答案唯一的批评是它依赖于Pandas,而这完全不必要来解决OP的问题。你不需要使用pandas数据处理库来生成两个日期之间的日期列表。glenn15和jagerber48在下面的回答中没有依赖第三方库,并且完成了同样的事情。 - geudrik
1
是的,你说得对,我错过了标签!我太忙于看实际代码了,被pandas的答案困惑了。 - geudrik
显示剩余2条评论

58

您的代码重写成列表推导式:

[sdate+timedelta(days=x) for x in range((edate-sdate).days)]

结果:

[datetime.date(2019, 3, 22),
 datetime.date(2019, 3, 23),
 datetime.date(2019, 3, 24),
          :
 datetime.date(2019, 4, 7),
 datetime.date(2019, 4, 8)]

5
这真是太棒了。如果你需要在列表中包含 edate ,那么很容易进行调整,就像这样:range(((edate + timedelta(days=1))-sdate).days) - Milo Persic

10

我很惊讶这在datetime包中不是一个标准函数。

下面是一个实现此功能的函数:

from datetime import timedelta

def date_range_list(start_date, end_date):
    # Return list of datetime.date objects (inclusive) between start_date and end_date (inclusive).
    date_list = []
    curr_date = start_date
    while curr_date <= end_date:
        date_list.append(curr_date)
        curr_date += timedelta(days=1)
    return date_list

使用方法:

from datetime import date, timedelta

def date_range_list(start_date, end_date):
    # Return list of datetime.date objects (inclusive) between start_date and end_date (inclusive).
    date_list = []
    curr_date = start_date
    while curr_date <= end_date:
        date_list.append(curr_date)
        curr_date += timedelta(days=1)
    return date_list

start_date = date(year=2021, month=12, day=20)
stop_date = date(year=2021, month=12, day=25)
date_list = date_range_list(start_date, stop_date)

date_list

输出:

[datetime.date(2021, 12, 20),
 datetime.date(2021, 12, 21),
 datetime.date(2021, 12, 22),
 datetime.date(2021, 12, 23),
 datetime.date(2021, 12, 24),
 datetime.date(2021, 12, 25)]

更新

虽然上述代码简单易懂,但最好将生成器提供给列表而不是直接提供列表本身。这样,除非需要,否则就不会生成和存储整个日期时间数组到内存中。以下是采用该方法的代码:

from datetime import timedelta

def date_range_list(start_date, end_date):
    # Return generator for a list datetime.date objects (inclusive) between start_date and end_date (inclusive).
    curr_date = start_date
    while curr_date <= end_date:
        yield curr_date 
        curr_date += timedelta(days=1)

使用方法:

from datetime import date, timedelta

def date_range_list(start_date, end_date):
    # Return generator for a list datetime.date objects (inclusive) between start_date and end_date (inclusive).
    curr_date = start_date
    while curr_date <= end_date:
        yield curr_date 
        curr_date += timedelta(days=1)

start_date = date(year=2021, month=12, day=20)
stop_date = date(year=2021, month=12, day=25)
date_list = date_range_list(start_date, stop_date)

for date in date_list:
   print(date)

输出:

2021-12-20
2021-12-21
2021-12-22
2021-12-23
2021-12-24
2021-12-25

6
from datetime import date, timedelta

sdate = date(2019,3,22)   # start date
edate = date(2019,4,9)   # end date
date_modified=sdate
list=[sdate] 


while date_modified<edate:
    date_modified+=timedelta(days=nbDaysbtw2dates) 
    list.append(date_modified)

print(list) 

2
当然,需要指定nbDaysbtw2dates - phloem7

4

您需要将其明确转换为字符串列表:

print([str(d) for d in dates_bwn_twodates(sdate,edate)])

3

有一种更简单的方法可以只修改您的代码即可使用。具体如下:

from datetime import datetime, timedelta
from datetime import date


def date_bwn_two_dates(start_date, end_date):
    date_list = [] # The list where we want to store
    for i in range(int((end_date-start_date).days)+1): # Iterate between the range of dates
        year = (start_date+timedelta(i)).strftime("%Y") # Get the Year
        month = (start_date+timedelta(i)).strftime("%m") # Get the month
        date_a = (start_date+timedelta(i)).strftime("%d") # Get the day
        date_list.append([year, month, date_a]) # Append the Objects accquired
    return date_list # return the list


for i in date_bwn_two_dates(date(2020, 12, 1), date(2021, 12, 1)):
    print(i)

1
如果您想要日期列表的字符串而不仅仅是日期时间索引,那么它还需要使用strftime进行格式化。
from datetime import date, timedelta

def timer():
    global datelist
    sdate = date(2022, 5, 1)
    edate = date(2022, 6, 1)

    delta = edate - sdate       
    datetimes = []
    for i in range(delta.days + 1):
        day = sdate + timedelta(days=i)
        datetimes.append(day)


    def formatting():
        global converted
        converted = pd.to_datetime(datetimes)
        return converted

    datelist = converted.strftime("%Y-%m-%d").tolist()

    formatting()

0

你可以使用https://github.com/zachwill/moment.git中的moment库来让编程更加轻松。

import moment

def dates_bwn_twodates(start_date, end_date):
    diff = abs(start_date.diff(end_date).days)
    
    for n in range(0,diff+1):
        yield start_date.strftime("%Y-%m-%d")
        start_date = (start_date).add(days=1)

sdate = moment.date('2019-03-22')   #start date
edate = moment.date('2019-04-09')   #end date  

然后你有选择

dates = list(dates_bwn_twodates(sdate,edate)) #dates as a list

或者你可以进行迭代

for date in dates_bwn_twodates(sdate,edate):
    #do something with each date

0

这是一个有点老的问题,但我想提出我的建议,因为其中一些答案似乎过于复杂:

from datetime import date, timedelta

#-- the actual method --#
def get_start_to_end(start_date, end_date):
    date_list = []
    for i in range(0, (end_date - start_date).days + 1):
        date_list.append(  str(start_date + timedelta(days=i))  ) #<-- here
    return date_list
#-- end of the actual method --#

# -- demonstrating it --#
sd = date(2022,8,12)
ed = date(2022,11,17)
dates = get_start_to_end(sd, ed)

for d in dates:
    print(d)

#-- You can just append the date object, the default string (iso)
#-- or use strftime for a different format
#-- (start_date + timedelta(days=i)) <-- date object
#-- str(start_date + timedelta(days=i))  <-- default string
#-- (start_date + timedelta(days=i)).strftime("%b %d, %Y") <-- other string format

0
另一种简单的方法是使用numpy np.arange在两个日期时间对象之间。
from datetime import datetime, timedelta
import numpy as np

start_date = datetime.strptime("2023-06-10", "%Y-%m-%d")
end_date = start_date + timedelta(13)

fut_dates = np.arange(fut_start_date, fut_end_date, dtype="datetime64[D]")

fut_dates:

array(['2023-06-10', '2023-06-11', '2023-06-12', '2023-06-13',
       '2023-06-14', '2023-06-15', '2023-06-16', '2023-06-17',
       '2023-06-18', '2023-06-19', '2023-06-20', '2023-06-21',
       '2023-06-22'], dtype='datetime64[D]')

转换为datetime.date对象:
fut_dates.astype(datetime)

array([datetime.date(2023, 6, 10), datetime.date(2023, 6, 11),
       datetime.date(2023, 6, 12), datetime.date(2023, 6, 13),
       datetime.date(2023, 6, 14), datetime.date(2023, 6, 15),
       datetime.date(2023, 6, 16), datetime.date(2023, 6, 17),
       datetime.date(2023, 6, 18), datetime.date(2023, 6, 19),
       datetime.date(2023, 6, 20), datetime.date(2023, 6, 21),
       datetime.date(2023, 6, 22)], dtype=object)

要输出一个字符串列表,你可以这样做:
[dt.strftime("%Y-%m-%d") for dt in pd.to_datetime(fut_dates)]

返回

['2023-06-10',
 '2023-06-11',
 '2023-06-12',
 '2023-06-13',
 '2023-06-14',
 '2023-06-15',
 '2023-06-16',
 '2023-06-17',
 '2023-06-18',
 '2023-06-19',
 '2023-06-20',
 '2023-06-21',
 '2023-06-22']

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接