如何判断DateTime是否属于RRULE定义的谷歌日历重复事件时间范围?
RRULE重复事件时间相交校验最优方案(复杂度角度)
最高效的实现是零实例生成的数学规则匹配法,时间复杂度为O(1) 单次查询、O(1) 预处理,远优于生成全量实例再遍历的O(n)方案,完全不受重复事件总次数的影响。
一次性预处理阶段(仅执行1次)
提前解析固定参数,避免每次查询重复计算:
- 解析
RRULE字符串为结构化字段,提取核心规则:FREQ(重复频率:日/周/月/年)、INTERVAL(重复间隔)、UNTIL/COUNT(终止条件)、BYDAY/BYMONTH等自定义过滤规则 - 存储事件基础属性:首次实例开始时间
dtStart、单实例持续时长duration - 预计算全局时间边界:最早可匹配时间为
dtStart,最晚可匹配时间根据终止条件计算(若为UNTIL则取UNTIL + duration,若为COUNT则提前算出最后一个实例的结束时间) - 若RRULE附带
EXDATE(排除日期),则存为哈希集合,保证O(1)查找效率
单次时间校验阶段(每次查询固定开销)
按顺序做快速判断,绝大多数无效请求会在前两步被直接过滤:
- 边界校验:待校验的
DateTime早于dtStart或晚于全局最晚结束时间,直接返回不相交 - 周期匹配:按
FREQ计算待校验时间和dtStart的周期差,对INTERVAL取模,结果不为0则返回不相交 - 规则匹配:校验待校验时间是否符合
BYDAY/BYMONTH等自定义过滤规则,不符合则返回不相交 - 排除项校验:当前匹配到的实例开始时间在
EXDATE集合中,返回不相交 - 区间校验:计算当前实例的时间区间
[实例开始时间, 实例开始时间 + duration],待校验DateTime落在区间内则返回相交,否则返回不相交
方案优势
传统方案需要先生成RRULE对应的所有重复实例,再遍历匹配待校验时间,时间复杂度随重复次数线性上涨,若RRULE跨度长达数年、重复间隔小,实例数可能达到数万级,性能损耗极大。本方案所有运算都是固定开销,无论RRULE跨度多大,单次查询速度完全一致。
内容的提问来源于stack exchange,提问作者tokechu
相关产品推荐
相关产品推荐

