"""日期工具:距到期日天数、月份匹配、ISO 字符串解析。""" from __future__ import annotations from datetime import date, datetime from typing import Tuple def parse_iso_date(s: str) -> date: """解析 'YYYY-MM-DD' ISO 日期字符串。 容错: - 已经是 date 实例 → 直接返回 - 含 'T' 的 ISO datetime → 取 date 部分 """ if isinstance(s, date): return s s = str(s).strip() if "T" in s: s = s.split("T", 1)[0] return datetime.strptime(s, "%Y-%m-%d").date() def days_to(target: date, today: date | None = None) -> int: """计算距 target 还有多少天(负数 = 已过期)。""" today = today or date.today() return (target - today).days def classify_alert(days: int, thresholds: Tuple[int, int, int] = (90, 60, 30)) -> str | None: """根据距到期天数返回预警等级。 thresholds = (yellow_max, orange_max, red_max),须 yellow_max > orange_max > red_max。 返回:'yellow' / 'orange' / 'red' / None(不在预警范围)。 """ yellow_max, orange_max, red_max = thresholds if days > yellow_max: return None if days <= red_max: return "red" if days <= orange_max: return "orange" return "yellow" def month_match(date_to_check: date, month_str: str) -> bool: """判断日期是否落在 month_str('YYYY-MM')月份内。""" if not month_str: return True try: y, m = month_str.strip().split("-") return date_to_check.year == int(y) and date_to_check.month == int(m) except (ValueError, AttributeError): return False def today_iso() -> str: """返回今天日期的 ISO 字符串。""" return date.today().isoformat() def now_iso() -> str: """返回当前时间的 ISO 字符串。""" return datetime.now().isoformat(timespec="seconds")