from dataclasses import dataclass, field from datetime import datetime, time, timedelta from yuxi.utils.datetime_utils import utc_now_naive @dataclass class TimeWindow: start: time end: time @dataclass class ScheduleConfig: workdays: list[int] = field(default_factory=lambda: [0, 1, 2, 3, 4]) work_hours: TimeWindow = field(default_factory=lambda: TimeWindow(time(9, 0), time(18, 0))) off_hours_reply: str | None = None timezone_offset_hours: int = 8 class SchedulePolicy: DEFAULT_OFF_HOURS_REPLY = "\u5f53\u524d\u4e3a\u975e\u5de5\u4f5c\u65f6\u95f4\uff0c\u6211\u5c06\u5728\u5de5\u4f5c\u65f6\u95f4\u5c3d\u5feb\u56de\u590d\u4f60\u3002" # noqa: E501 def __init__(self): self._config = ScheduleConfig() def configure(self, config: ScheduleConfig) -> None: self._config = config def is_working_hours(self, now: datetime | None = None) -> bool: dt = now or utc_now_naive() offset_delta = timedelta(hours=self._config.timezone_offset_hours) local_dt = dt + offset_delta weekday = local_dt.weekday() if weekday not in self._config.workdays: return False current_time = local_dt.time() window = self._config.work_hours if window.start <= window.end: return window.start <= current_time <= window.end return current_time >= window.start or current_time <= window.end def get_off_hours_reply(self, now: datetime | None = None) -> str | None: if not self.is_working_hours(now=now): return self._config.off_hours_reply or self.DEFAULT_OFF_HOURS_REPLY return None