You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何统计日历列的事件数并判断hour_start、hour_end对应事件是否相交

问题1:计算日历某一列上的事件总数量

首先明确日历列的划分逻辑,常规日历列一般按「日期」「资源ID(如人员、会议室)」两类维度划分,对应统计方式如下:

前端场景(直接操作日历组件数据)

以常用的FullCalendar组件为例,逻辑如下:

  • 确定目标列的唯一标识,如日期列的标识为YYYY-MM-DD格式的日期值,资源列的标识为resourceId
  • 遍历所有日历事件,匹配对应标识后计数
    示例代码:
// FullCalendar 场景示例
const targetColumnId = '2024-05-20' // 目标列ID
const allEvents = calendar.getEvents()
const columnEventCount = allEvents.filter(event => 
  event.startStr.split('T')[0] === targetColumnId
).length

后端场景(从数据库统计)

  • 过滤条件匹配目标列的关联字段,直接执行count统计即可
    示例SQL:
-- 按日期列统计
SELECT COUNT(*) FROM calendar_events WHERE event_date = '2024-05-20';
-- 按资源列统计
SELECT COUNT(*) FROM calendar_events WHERE resource_id = 1001;

注意:如果存在跨列事件(如跨天事件),需要先将跨列事件按覆盖的列拆分后再统计,避免漏算

问题2:找出存在时间交集的事件

核心判断逻辑

两个事件A、B存在时间交集的充要条件是:
A.hour_start < B.hour_end AND B.hour_start < A.hour_end
如果需要把「A结束时间等于B开始时间」的相邻场景也判定为交集,将小于号替换为小于等于即可。

小数据集实现(x<10000,时间复杂度O(n²))

直接两两配对判断即可,逻辑简单不易出错:

from datetime import datetime
def find_overlapping_pairs(events: list) -> list:
    overlapping_pairs = []
    event_count = len(events)
    # 统一转时间戳避免格式问题
    for event in events:
        event["start_ts"] = datetime.fromisoformat(event["hour_start"]).timestamp()
        event["end_ts"] = datetime.fromisoformat(event["hour_end"]).timestamp()
    # 两两比较不重复计算
    for i in range(event_count):
        a = events[i]
        for j in range(i + 1, event_count):
            b = events[j]
            if a["start_ts"] < b["end_ts"] and b["start_ts"] < a["end_ts"]:
                overlapping_pairs.append((a["id"], b["id"]))
    return overlapping_pairs

大数据集实现(x≥10000,时间复杂度O(nlogn))

用扫描线算法优化,避免暴力两两比较:

  • 将所有事件拆分为「开始时间点(标记为+1,绑定事件ID)」和「结束时间点(标记为-1,绑定事件ID)」
  • 所有时间点按时间升序排序,时间相同时结束点排在开始点前面(避免相邻事件判定为交集)
  • 遍历排序后的时间点,维护当前活跃事件集合:遇到开始点时,当前事件与活跃集合内所有事件都有交集,记录配对后将当前事件加入活跃集合;遇到结束点时将对应事件移出活跃集合
    示例代码片段:
def find_overlapping_events_optimized(events: list) -> list:
    points = []
    for e in events:
        start_ts = datetime.fromisoformat(e["hour_start"]).timestamp()
        end_ts = datetime.fromisoformat(e["hour_end"]).timestamp()
        points.append((start_ts, 1, e["id"]))
        points.append((end_ts, -1, e["id"]))
    # 排序规则:先按时间,再按类型(结束点-1排在开始点1前面)
    points.sort(key=lambda x: (x[0], x[1]))
    active_events = set()
    overlaps = []
    for ts, typ, event_id in points:
        if typ == 1:
            # 所有活跃事件和当前事件有交集
            for active_id in active_events:
                overlaps.append((active_id, event_id))
            active_events.add(event_id)
        else:
            active_events.discard(event_id)
    return overlaps

注意:所有时间需要统一时区,避免跨时区事件的交集判断错误


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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 22:15:04