如何对PostgreSQL DateRange字段查询重叠日期及内存列表重叠校验
实现DateRange列表与目标日期/范围的重叠校验
psycopg提供的DateRange对象本身没有内置overlap方法,我们可以通过它暴露的端点属性自行实现重叠判断逻辑,完全和Django ORM的date_range__overlap查询逻辑对齐。
核心判断逻辑
两个时间范围不存在重叠的唯一条件为:其中一个范围的结束时间早于等于另一个范围的开始时间,取反即为重叠。
DateRange对象可直接读取三个核心属性:
.lower:范围左端点值.upper:范围右端点值.bounds:范围开闭规则,默认值为'[)'(左闭右开,符合绝大多数业务场景的日期范围定义)
实现代码
1. 编写通用重叠校验工具函数
import datetime from psycopg2.extras import DateRange def check_range_overlap(range_a: DateRange, range_b: DateRange | datetime.date) -> bool: # 若校验目标为单个日期,先转为左闭右开的单日范围 if isinstance(range_b, datetime.date): range_b = DateRange(range_b, range_b + datetime.timedelta(days=1)) # 排除不重叠的两种情况 if range_a.upper <= range_b.lower or range_b.upper <= range_a.lower: return False return True
2. 业务场景调用示例
# 初始化DateRange列表(注意:必须传入datetime.date对象,不能直接写数字数组) mylist = [ DateRange(datetime.date(2021,10,4), datetime.date(2021,10,5)), DateRange(datetime.date(2022,10,4), datetime.date(2022,10,5)) ] # 校验目标为单个日期 query_date = datetime.date(2021,10,4) has_overlap = any(check_range_overlap(dr, query_date) for dr in mylist) print(has_overlap) # 输出True # 校验目标也为DateRange query_range = DateRange(datetime.date(2021,10,3), datetime.date(2021,10,4)) has_overlap = any(check_range_overlap(dr, query_range) for dr in mylist) print(has_overlap) # 输出False(默认左闭右开,两个范围端点重合不算重叠)
自定义边界规则适配
如果你的DateRange使用了非默认的开闭规则(比如全闭'[]'),可以根据业务需求调整判断条件的运算符即可,比如将<=改为<适配全闭边界的重叠判定。
内容的提问来源于stack exchange,提问作者alias51
相关产品推荐
相关产品推荐

