确定输入日期范围是否与现有范围重叠

时间:2016-06-21 07:46:42

标签: django algorithm date python-3.x language-agnostic

我在数据库中有一个存储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()

2 个答案:

答案 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