You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

面试题:判断两个周期性预约是否存在时间重叠

嘿,这个问题我之前做企业日历预约系统的时候正好碰到过,当时踩了不少重复规则解析和边界处理的坑,分享下我实际验证过的解决方案思路:

周期性预约冲突检测完整方案

核心逻辑

本质是要找到两个重复时间序列中,是否存在至少一个时间区间满足重叠条件。因为是周期性的,不可能无限遍历所有可能的预约,所以核心是要圈定有限的检查范围,同时用高效的逻辑判断冲突。

具体实施步骤

1. 先把重复规则解析成可计算的逻辑

首先得把自然语言的重复规则转换成程序能识别的生成规则,比如:

  • 每日重复:比如「每2天」,就是从起始时间开始,每次加2天的时间间隔
  • 每周重复:比如「每3周的周二」,就是每隔21天(3×7),筛选出周二的日期
  • 每月重复:分两种场景单独处理:
    • 固定日期:比如「每2个月的17日」,每隔N个月取当月17日(要注意月末边界,比如2月没有30日,得和业务确认是调整到月末还是跳过)
    • 固定周几:比如「每月第三个周二」,需要写逻辑计算当月第K个星期X的具体日期
  • 每年重复:比如「每2年的4月17日」,就是每隔2年,取当年4月17日的日期

2. 确定合理的检查范围

因为是无限重复的预约,不可能一直检查下去,通常的做法是:

  • 如果两个预约都有结束时间,就取它们的有效时间交集作为检查范围
  • 如果其中一个或两个没有结束时间,就设定一个业务合理的最大检查周期(比如10年,毕竟很少有人会预约10年后的重复事项)
  • 在这个范围内如果没找到冲突,就认为长期内不会冲突,后续可以根据业务需求调整阈值

3. 时间区间重叠的判断逻辑

不管是单次还是重复预约,时间区间重叠的判断公式是通用的:

对于区间A(startA, endA)和区间B(startB, endB),当 startA < endB 且 startB < endA 时,两个区间存在重叠。

这里要注意一个容易踩的坑:如果预约没有填写结束时间,必须先和业务方确认默认时长——是持续全天,还是默认1小时?这个规则不明确的话,后续的冲突判断全是错的。

4. 优化:用数学方法缩小检查范围

如果直接生成所有时间区间再遍历,大周期下会很耗时,可以用周期最小公倍数来优化:

  • 比如两个每日重复的预约,间隔分别是2天和3天,最小公倍数是6天,只需要检查6天内的情况——如果有冲突,之后每6天都会重复冲突;如果没有,就永远不会冲突
  • 每周、每月、每年的重复规则,也可以用类似的方法计算周期的最小公倍数,大幅减少需要检查的时间点

5. 边界情况必须处理

  • 特殊日期:比如2月29日的年度重复预约,非闰年要调整到2月28日还是直接跳过?得和业务对齐
  • 跨时区:所有时间必须统一转换到同一个时区(比如UTC)再计算,避免时区差导致的误判
  • 单次预约:如果重复规则是「不重复」(虽然问题说的是周期性,但实际场景可能存在),直接判断单次时间区间是否重叠即可

伪代码示例

def check_recurring_overlap(appt1, appt2, max_check_years=5):
    # 解析重复规则,生成指定范围内的所有时间区间
    appt1_intervals = generate_recurring_time_ranges(appt1, max_check_years)
    appt2_intervals = generate_recurring_time_ranges(appt2, max_check_years)
    
    # 遍历检查每个区间是否重叠
    for start1, end1 in appt1_intervals:
        # 优化:只检查和当前时间区间接近的appt2区间,避免全量遍历
        for start2, end2 in appt2_intervals:
            if start1 < end2 and start2 < end1:
                return True
        # 重置appt2的区间生成器,避免重复遍历
        appt2_intervals = generate_recurring_time_ranges(appt2, max_check_years)
    return False

内容的提问来源于stack exchange,提问作者tienph

火山引擎 最新活动