我在数据库中有一个存储items
的表,可以租用几天。
现在每当有人租用item
时,他们都会指定一个start_date
和一个end_date
(基本上是date range
,他们想要租用item
)
我想知道什么是有效的算法(在时间复杂度方面)来检查输入date range
是否与数据库中现有的date ranges
不重叠。
插图:
|<------existing 1------->|
|<------existing 2------->|
|<------ input date range ---->| (which clearly, overlaps)
注意:
此问题与this问题不重复。那个检查是否有两个date ranges
重叠。我的问题是输入date range
与多个现有date ranges
另一个注意事项:
如果您对此问题的标记感到困惑,我会对这两种答案持开放态度language-agnostic
以及language-specific
。
对于那些想要给出language-specific
答案的人,请参阅以下详细信息:
我有一个django 1.9
项目在python 3.4
上运行,PostgreSQL
作为数据库。我的模特是:
class Item(models.Model):
name = models.CharField(max_length=100)
class BookingPeriod(models.Model):
item = models.ForeignKey(Item)
start_date = models.DateField()
end_date = models.DateField()
答案 0 :(得分:2)
此答案假设所有先前的输入都是合法的。如果没有,可以改变它以适应其他情况。
在系统中保留两个有序列表 - 一个用于18:05:00
,一个用于start date
。这些列表显然需要有一种方法来查找其他列表中的相关项。
收到新输入后,找到小于新输入“end date
的最大start date
,并检查相关start date
是否也小于新end date
,否则新的输入是非法的。
同样适用于start date
,反之亦然。
我认为可以在end date
中使用树而不是列表来完成。
答案 1 :(得分:0)
以下代码可以达到此目的:
def validate_overlap(periods, count_days=True):
"""
Receives a list with DateRange or DateTimeRange and returns True
if periods overlap.
In this application it is guaranteed that the end of each period is
not inclusive. Therefore if a period ends in 15/5 and another starts
in 15/5, they do not overlap. The same with datetime periods.
"""
periods.sort()
no_overlap = [True]
for each in range(0, len(periods) - 1):
latest_start = max(periods[each].lower, periods[each + 1].lower)
earliest_end = min(periods[each].upper, periods[each + 1].upper)
delta = earliest_end - latest_start
if count_days:
no_overlap.append(max(0, delta.days) == 0)
else:
no_overlap.append(max(0, delta.total_seconds()) == 0)
return False if all(no_overlap) else True