如何从开始日期和结束日期列表中识别缺失的日期?
How to identify missing days from a list of start and end dates?
如何从 (start_date, end_date)
元组列表中识别缺失的日期?
例如,如何识别以下列表中缺失的日期:
dates = [('2011-01-01', '2011-01-14'), ('2011-01-15','2011-01-31'),
('2011-02-01', '2011-02-14'), ('2011-03-01', '2011-03-14'),
('2011-03-16', '2011-03-31')]
以上示例缺少以下日期:
2011-02-15
到 2011-02-28
2011-03-15
如何从开始日期和结束日期元组列表中识别所有缺失的日期?
有点冗长,但你明白了
编辑: 清理了一下
from datetime import date, timedelta
dates = [('2011-01-01', '2011-01-14'), ('2011-01-15','2011-01-31'),
('2011-02-01', '2011-02-14'), ('2011-03-01', '2011-03-14'),
('2011-03-16', '2011-03-31')]
def d_range(d1,d2):
delta = d2 - d1 #assumes second date is always after first
return [d1 + timedelta(days=i) for i in range(delta.days + 1)]
my_days = []
#calc the date range between each tuple
for d in dates:
d1 = datetime.strptime(d[0],'%Y-%m-%d')
d2 = datetime.strptime(d[1],'%Y-%m-%d')
my_days.extend(d_range(d1,d2))
#now do the same for the max and min dates
my_range = d_range(min(my_days), max(my_days))
missing_dates = set(my_range).difference(set(my_days))
并解决您的评论:
missing_dates_list = list(missing_dates)
或回到原来的格式:
missing_dates_str = [datetime.strftime(date, '%Y-%m-%d') for date in missing_dates]
更面向对象的解决方案:
from functools import total_ordering
from datetime import timedelta, datetime
@total_ordering
class DateRange(object):
def __init__(self, start, end):
assert start <= end
self.start = start
self.end = end
def __contains__(self, other):
return self.start <= other and self.end >= other
def __lt__(self, other):
if self.start == other.start:
return self.end < other.end
return self.start < other.start
def __eq__(self, other):
return self.start == other.start and self.end == other.end
def __str__(self):
return '<%s, %s>' % (self.start.strftime('%Y-%m-%d'), self.end.strftime('%Y-%m-%d'))
def __iter__(self):
class DateIterator(object):
def __init__(self, start, end):
self.current = start
self.end = end
def next(self):
if self.current > self.end:
raise StopIteration()
self.current += timedelta(days=1)
return self.current
return DateIterator(self.start, self.end)
__repr__ = __str__
dates = [('2011-01-01', '2011-01-14'), ('2011-01-15','2011-01-31'), ('2011-02-01','2011-02-14'), ('2011-03-01','2011-03-14'), ('2011-03-16','2011-03-31')]
dates = [DateRange(datetime.strptime(start, '%Y-%m-%d'), datetime.strptime(end, '%Y-%m-%d')) for start, end in dates]
dates = sorted(dates)
missing = []
previous = None
for date_range in dates:
if previous is not None and previous < date_range.start:
missing.append(DateRange(previous, date_range.start + timedelta(days=-1)))
previous = date_range.end + timedelta(days=1)
print missing
如何从 (start_date, end_date)
元组列表中识别缺失的日期?
例如,如何识别以下列表中缺失的日期:
dates = [('2011-01-01', '2011-01-14'), ('2011-01-15','2011-01-31'),
('2011-02-01', '2011-02-14'), ('2011-03-01', '2011-03-14'),
('2011-03-16', '2011-03-31')]
以上示例缺少以下日期:
2011-02-15
到2011-02-28
2011-03-15
如何从开始日期和结束日期元组列表中识别所有缺失的日期?
有点冗长,但你明白了
编辑: 清理了一下
from datetime import date, timedelta
dates = [('2011-01-01', '2011-01-14'), ('2011-01-15','2011-01-31'),
('2011-02-01', '2011-02-14'), ('2011-03-01', '2011-03-14'),
('2011-03-16', '2011-03-31')]
def d_range(d1,d2):
delta = d2 - d1 #assumes second date is always after first
return [d1 + timedelta(days=i) for i in range(delta.days + 1)]
my_days = []
#calc the date range between each tuple
for d in dates:
d1 = datetime.strptime(d[0],'%Y-%m-%d')
d2 = datetime.strptime(d[1],'%Y-%m-%d')
my_days.extend(d_range(d1,d2))
#now do the same for the max and min dates
my_range = d_range(min(my_days), max(my_days))
missing_dates = set(my_range).difference(set(my_days))
并解决您的评论:
missing_dates_list = list(missing_dates)
或回到原来的格式:
missing_dates_str = [datetime.strftime(date, '%Y-%m-%d') for date in missing_dates]
更面向对象的解决方案:
from functools import total_ordering
from datetime import timedelta, datetime
@total_ordering
class DateRange(object):
def __init__(self, start, end):
assert start <= end
self.start = start
self.end = end
def __contains__(self, other):
return self.start <= other and self.end >= other
def __lt__(self, other):
if self.start == other.start:
return self.end < other.end
return self.start < other.start
def __eq__(self, other):
return self.start == other.start and self.end == other.end
def __str__(self):
return '<%s, %s>' % (self.start.strftime('%Y-%m-%d'), self.end.strftime('%Y-%m-%d'))
def __iter__(self):
class DateIterator(object):
def __init__(self, start, end):
self.current = start
self.end = end
def next(self):
if self.current > self.end:
raise StopIteration()
self.current += timedelta(days=1)
return self.current
return DateIterator(self.start, self.end)
__repr__ = __str__
dates = [('2011-01-01', '2011-01-14'), ('2011-01-15','2011-01-31'), ('2011-02-01','2011-02-14'), ('2011-03-01','2011-03-14'), ('2011-03-16','2011-03-31')]
dates = [DateRange(datetime.strptime(start, '%Y-%m-%d'), datetime.strptime(end, '%Y-%m-%d')) for start, end in dates]
dates = sorted(dates)
missing = []
previous = None
for date_range in dates:
if previous is not None and previous < date_range.start:
missing.append(DateRange(previous, date_range.start + timedelta(days=-1)))
previous = date_range.end + timedelta(days=1)
print missing