Python 如何在已排序的日期列表中查找缺少的日期?

Python 如何在已排序的日期列表中查找缺少的日期?,python,Python,在Python中,如何在已排序的日期列表中查找所有缺失的日期?对日期列表进行排序并在其上迭代,记住前面的条目。如果上一个条目与当前条目之间的差异超过一天,则表示缺少天数 这里有一种实现方法: from datetime import date, timedelta from itertools import tee, izip def pairwise(iterable): "s -> (s0,s1), (s1,s2), (s2, s3), ..." a, b = tee

在Python中,如何在已排序的日期列表中查找所有缺失的日期?

对日期列表进行排序并在其上迭代,记住前面的条目。如果上一个条目与当前条目之间的差异超过一天,则表示缺少天数

这里有一种实现方法:

from datetime import date, timedelta
from itertools import tee, izip

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    b.next()
    return izip(a, b)

def missing_dates(dates):
    for prev, curr in pairwise(sorted(dates)):
        i = prev
        while i + timedelta(1) < curr:
            i += timedelta(1)
            yield i

dates = [ date(2010, 1, 8),
          date(2010, 1, 2),
          date(2010, 1, 5),
          date(2010, 1, 1),
          date(2010, 1, 7) ]

for missing in missing_dates(dates):
    print missing

性能是O(n*log(n)),其中n是输入未排序时跨度中的天数。由于您的列表已经排序,它将以O(n)的形式运行。

将日期放入一个
集合中,然后使用
datetime.timedelta()
从第一个日期迭代到最后一个日期,每次都检查集合中的包含情况。

>from datetime import datetime,timedelta>
>>> from datetime import datetime, timedelta
>>> date_list = [datetime(2010, 2, 23),datetime(2010, 2, 24),datetime(2010, 2, 25),datetime(2010, 2, 26),datetime(2010, 3, 1),datetime(2010, 3, 2)]
>>> 
>>> date_set=set(date_list)         # for faster membership tests than list
>>> one_day = timedelta(days=1)
>>> 
>>> test_date = date_list[0]
>>> missing_dates=[]
>>> while test_date < date_list[-1]:
...     if test_date not in date_set:
...         missing_dates.append(test_date)
...     test_date += one_day
... 
>>> print missing_dates
[datetime.datetime(2010, 2, 27, 0, 0), datetime.datetime(2010, 2, 28, 0, 0)]
>>>date_list=[datetime(2010,2,23),datetime(2010,2,24),datetime(2010,2,25),datetime(2010,2,26),datetime(2010,3,1),datetime(2010,3,2)] >>> >>>date_set=set(date_list)#用于比list更快的成员资格测试 >>>一天=时间增量(天=1) >>> >>>测试日期=日期列表[0] >>>缺少日期=[] >>>当测试日期<日期列表[-1]: ... 如果测试日期不在日期设置中: ... 缺少日期。追加(测试日期) ... 测试日期+=一天 ... >>>打印缺少的日期 [datetime.datetime(2010,2,27,0,0),datetime.datetime(2010,2,28,0,0)]
这也适用于
datetime.date
对象,但是OP说列表是
datetime.datetime
对象

import datetime
import datetime

DAY = datetime.timedelta(days=1)
# missing dates: a list of [start_date, end)
missing = [(d1+DAY, d2) for d1, d2 in zip(dates, dates[1:]) if (d2 - d1) > DAY]

def date_range(start_date, end, step=DAY):
    d = start_date
    while d < end:
        yield d
        d += step

missing_dates = [d for d1, d2 in missing for d in date_range(d1, d2)]
DAY=datetime.timedelta(天=1) #缺少日期:[开始日期,结束]的列表 缺失=[(d1+天,d2)对于d1,zip中的d2(日期,日期[1:]),如果(d2-d1)>天] 定义日期范围(开始日期、结束日期、步骤=天): d=开始日期 当d
使用列表理解

>>> from datetime import date, timedelta
>>> d = [date(2010, 2, 23),date(2010, 2, 24),date(2010, 2, 25),date(2010, 2, 26),date(2010, 3, 1),date(2010, 3, 2)]
>>> date_set=set(d)
>>> missing = [x for x in (d[0]+timedelta(x) for x in range((d[-1]-d[0]).days)) if x not in date_set]

>>> missing
[datetime.date(2010, 2, 27), datetime.date(2010, 2, 28)]
使用集合

>>> from datetime import date, timedelta
>>> d = [date(2010, 2, 23), date(2010, 2, 24), date(2010, 2, 25),
         date(2010, 2, 26), date(2010, 3, 1), date(2010, 3, 2)]
>>> date_set = set(d[0] + timedelta(x) for x in range((d[-1] - d[0]).days))
>>> missing = sorted(date_set - set(d))
>>> missing
[datetime.date(2010, 2, 27), datetime.date(2010, 2, 28)]
>>> 

在Python中实现这一点的一个好方法如下:您不必担心效率,除非您的列表中有多年的日期,并且此代码始终需要根据用户交互运行并立即产生输出

  • 从一个列表中获取缺少的日期(已排序或未排序)
  • 创建一个函数,为您提供从
    开始日期
    结束日期
    的所有日期,并使用它

    import datetime
    
    def get_dates(start_date, end_date):
        span_between_dates = range(end_date - start_date).days
        for index in span_between_dates + 1:
            # +1 is to make start and end dates inclusive.
            yield start_date + datetime.timedelta(index)
    
    my_date_list = ['2017-03-05', '2017-03_07', ...]
    # Edit my_date_list as per your requirement.
    start_date = min(my_date_list)
    end_date = max(my_date_list)
    for current_date in get_dates(start_date, end_date)
        if date not in my_date_list:
            print date
    
  • 获取两个日期范围之间缺少或重叠的日期
  • 应定义获取日期的函数

    my_other_date_list = []  # your other date range
    start_date = min(my_date_list)
    end_date = max(my_date_list)
    for current_date in get_dates(start_date, end_date)
        if (date in my_date_range) and (date in my_other_date_list):
            print ('overlapping dates between 2 lists:')
            print date
        elif (date in my_date_range) and (date not in my_other_date_list):
            print ('missing dates:')
            print date
    

    使用FOR循环

    您将需要的导入:

    import datetime
    from datetime import date, timedelta
    
    假设您有一个名为
    dates
    的排序列表,其中有几个缺少的日期

    首先选择第一个和最后一个日期:

    start_date = dates[0]
    end_date = dates[len(dates)-1]
    
    然后计算这两个日期之间的天数:

    numdays = (end_date - start_date).days
    
    然后创建一个新列表,其中所有日期都在开始日期和结束日期之间:

    all_dates = []
    for x in range (0, (numdays+1)):
    all_dates.append(start_date + datetime.timedelta(days = x))
    
    然后,通过使用带范围的for循环并将这些日期添加到缺少的日期,检查日期是否在所有日期中,但不在日期中:

    dates_missing = []
    
    for i in range (0, len(all_dates)):
       if (all_dates[i] not in dates):
           dates_missing.append(all_dates[i])
       else:
           pass
    

    现在,您将有一个名为
    dates\u missing
    的列表,其中包含所有缺失的日期。

    您的日期对象是什么类型的?@Mark:date对象的类型是datetime@gnibbler:太好了……那么这个算法在O(n)时间内运行。我的也是O(n)。如果我没有使用date_set,它在最坏情况下的性能将是O(n*n)虽然:)+1:看起来不错。为了清晰起见,在timedelta(days=1)上使用参数名很好。感谢您的回答,我喜欢这个:)谢谢。我花了一分钟才意识到这是个减号。@gwg,好吧,我添加了一些空白。现在更好了?我想
    缺少=排序(日期集-set(d))中不需要
    排序的
    已设置为
    d
    日期sorted@abhiieor,不知道你的意思。集合是无序的
    
    dates_missing = []
    
    for i in range (0, len(all_dates)):
       if (all_dates[i] not in dates):
           dates_missing.append(all_dates[i])
       else:
           pass