首页 > 解决方案 > 查找日期列表之间的所有交叉期间(对于房间预订)

问题描述

我需要编写一个组织房间预订的软件。
在此,我需要为用于协调房间冲突的日历编写标题栏。
基本上有房间,一个房间一次只能有一个预订,并且在发生冲突时需要突出显示标题。
基本上它需要看起来像这样:

在此处输入图像描述

为此,我需要一个红色日期范围列表,显示一次以上的预订使用相同的时间范围。
我可以使用某种python库吗?
基本上它需要接受一个日期元组列表并吐出一个不重叠日期的元组列表。

标签: pythonalgorithmdatetime

解决方案


...基本上它需要接受一个日期元组列表并吐出一个不重叠日期的元组列表......

套装非常适合这个。以下示例代码将找到所有未采用的日期,从中构建 (ini, end) 元组将是直截了当的,因为当您找到非连续日期时,每个元组都会结束。一探究竟:

from datetime import timedelta, datetime as dt

ranges = [
    ("2018-1-1", "2018-1-31"),   # 1
    ("2018-1-20", "2018-2-10"),  # 2
    ("2018-2-25", "2018-3-15"),  # 3
    ("2018-2-27", "2018-3-20")   # 4
]

# Range 1 and 2 overlaps staring at day (2018-1-20) to day (2018-1-31)
# You have an open window from (2018-2-10) to (2018-2-25)
# And again overlaps in ranges 3 and 4.


# Lets take those ranges specifications in real dates objects.
date_ranges = []
for ini, end in ranges:
    date_ranges.append(
        (
            dt.strptime(ini, "%Y-%m-%d"), 
            dt.strptime(end, "%Y-%m-%d")
        )
    )

# Now in order to be able to use set theory, you need to
# convert those date ranges into sets of data that 
# match your problem.

# I will use set of days, when every element is a different day,
# I,m assuming a day is the unit for meassuring reservation time.

date_sets = []

for ini, end in date_ranges:
    delta = end - ini
    # We don't convert to sets here becouse
    # we want to keep the order til last minunte.
    # Just in case ;)
    dates_ = [ini + timedelta(n) for n in range(delta.days + 1)]
    date_sets.append(dates_)


# Let get also all days invloved in the full date range,
# we need a reference so we can tell what days are free.


all_dates = []
# Assuming date ranges specification are ordered, which is
# the general case.

# Remember that thing about order
# I told earlier?  :)
ini = date_sets[0][0]
end = date_sets[-1][-1]
delta =  end - ini
dates_ = [ini + timedelta(n) for n in range(delta.days + 1)]
all_dates.append(dates_)


# Now we are ready to work with sets.
all_dates = set(*all_dates)
date_sets = map(set, date_sets)

# Having the sets we can operate on them
# see: https://docs.python.org/2/library/sets.html

# Sice you want the days that are free for rental, 
# we are getting symmetric difference (elements in either s or t but not both)
free_for_rental = all_dates ^ (set.union(*date_sets))


# Printing the result so you can check it.
list_of_free_dates = sorted(list(free_for_rental))

for day in list_of_free_dates:
    print(day)

回应:

2018-02-11 00:00:00
2018-02-12 00:00:00
2018-02-13 00:00:00
2018-02-14 00:00:00
2018-02-15 00:00:00
2018-02-16 00:00:00
2018-02-17 00:00:00
2018-02-18 00:00:00
2018-02-19 00:00:00
2018-02-20 00:00:00
2018-02-21 00:00:00
2018-02-22 00:00:00
2018-02-23 00:00:00
2018-02-24 00:00:00

推荐阅读