Python重复时间区间实现方案咨询(FastAPI+Pydantic场景)
可行方案推荐
针对你需要的重复时间区间处理(用于不可用时间或重复任务调度),结合FastAPI/Pydantic的需求,有几个现成方案可以避免大量自定义代码:
1. 使用pydantic-recurrence扩展
这个库专门为Pydantic实现了重复规则类型,兼容iCalendar的RRULE格式,完美支持重复时间区间的定义与校验。你可以通过RRULE指定重复周期(如每周日),再搭配当天的时间段偏移来定义完整区间:
- 安装:
pip install pydantic-recurrence - 示例模型:
from pydantic import BaseModel from pydantic_recurrence import Recurrence class RecurringTimeRange(BaseModel): recurrence: Recurrence # 定义重复规则,比如RRULE:FREQ=WEEKLY;BYDAY=SU start_time: str # 当天内的起始时间,如"13:00" end_time: str # 当天内的结束时间,如"14:00" def overlaps_with(self, task_start, task_end): # 生成任务时间窗口内的所有重复区间 for dt in self.recurrence.rrule.between(task_start, task_end, inc=True): range_start = dt.replace(hour=int(self.start_time.split(':')[0]), minute=int(self.start_time.split(':')[1])) range_end = dt.replace(hour=int(self.end_time.split(':')[0]), minute=int(self.end_time.split(':')[1])) # 判断区间重叠 if not (range_end <= task_start or range_start >= task_end): return True return False - 优势:内置RRULE校验,无需自己处理重复规则的解析,直接对接FastAPI接口传参。
2. 结合croniter与自定义Pydantic类型
如果更习惯cron表达式风格,可以用两个cron分别表示区间的起始和结束时间,通过croniter生成连续时间段并做重叠判断:
- 安装:
pip install croniter - 示例模型:
from croniter import croniter from pydantic import BaseModel, validator from datetime import datetime class CronTimeRange(BaseModel): start_cron: str # 区间起始的cron,如"0 13 * * 0"(每周日1PM) end_cron: str # 区间结束的cron,如"0 14 * * 0"(每周日2PM) @validator('start_cron', 'end_cron') def validate_cron_format(cls, v): if not croniter.is_valid(v): raise ValueError("无效的cron表达式") return v def overlaps(self, task_start: datetime, task_end: datetime) -> bool: iter_start = croniter(self.start_cron, task_start) iter_end = croniter(self.end_cron, task_start) while True: range_start = iter_start.get_next(datetime) range_end = iter_end.get_next(datetime) if range_start > task_end: break if range_start < task_end and range_end > task_start: return True return False - 优势:符合熟悉cron的用户使用习惯,逻辑直观,自定义校验成本低。
3. 基于python-dateutil的结构化重复规则
如果希望用更结构化的参数(而非字符串规则),可以用python-dateutil的rrule配合Pydantic模型,让用户直接指定重复频率、星期/日期、时间段:
- 安装:
pip install python-dateutil - 示例模型:
from dateutil.rrule import rrule, WEEKLY, MONTHLY from pydantic import BaseModel, Field from datetime import time, datetime class StructuredRecurringRange(BaseModel): freq: str = Field(enum=["WEEKLY", "MONTHLY"], description="重复频率") target_day: int = Field(description="每周的星期几(0=周一,6=周日)或每月的日期") start_time: time end_time: time def get_overlap(self, task_start: datetime, task_end: datetime) -> bool: freq_map = {"WEEKLY": WEEKLY, "MONTHLY": MONTHLY} # 根据频率生成匹配的日期 rule = rrule(freq_map[self.freq], byweekday=self.target_day if self.freq == "WEEKLY" else None, bymonthday=self.target_day if self.freq == "MONTHLY" else None, dtstart=task_start, until=task_end) for dt in rule: range_start = datetime.combine(dt.date(), self.start_time) range_end = datetime.combine(dt.date(), self.end_time) if range_start < task_end and range_end > task_start: return True return False - 优势:参数更直观,用户无需学习RRULE或cron语法,降低输入门槛。
内容的提问来源于stack exchange,提问作者Aviv Aviv
相关产品推荐
相关产品推荐

