# ============================================================ # 日期时间工具(moduleId: server-timeutil, 可重生 ✅) # 与 legacy aps-frontend/js/data.js 的 $utils 语义一致: # 字符串格式统一 "YYYY-MM-DD" 与 "YYYY-MM-DD HH:MM" # ============================================================ from __future__ import annotations # 前向类型引用 from datetime import datetime, timedelta # 标准日期时间类型 def fmt_date(d: datetime) -> str: """格式化为日期字符串 YYYY-MM-DD(与 data.js fmtDate 对齐)。""" return d.strftime("%Y-%m-%d") # 固定零填充格式 def fmt_dt(d: datetime) -> str: """格式化为日期时间字符串 YYYY-MM-DD HH:MM(与 data.js fmtDateTime 对齐)。""" return d.strftime("%Y-%m-%d %H:%M") # 分钟精度(排产粒度 15 分钟足够) def parse_dt(s: str) -> datetime: """解析日期/日期时间字符串(兼容三种格式,与 data.js parseDate 对齐)。 除标准 "YYYY-MM-DD" 与 "YYYY-MM-DD HH:MM" 外,兼容导入资料里常见的 ISO 形态 "YYYY-MM-DDTHH:MM[:SS]"(MES/MOM 导出常见)。少了这层兼容, 只要导入过一条 ISO 时间,方案对比等读取路径就会整页报错。 """ text = str(s).strip().replace("T", " ") # ISO 分隔符归一 if len(text) <= 10: # 仅日期(10 个字符) return datetime.strptime(text, "%Y-%m-%d") # 解析为当日零点 if text.count(":") == 1: # 含时分(无秒) return datetime.strptime(text, "%Y-%m-%d %H:%M") return datetime.strptime(text[:16], "%Y-%m-%d %H:%M") # 带秒/时区时取到分钟 # 含时分的完整解析 def add_minutes(d: datetime, minutes: float) -> datetime: """时间加分钟(与 data.js addMinutes 对齐)。""" return d + timedelta(minutes=minutes) # timedelta 直接支持浮点分钟 def today0() -> datetime: """今天零点(与 data.js today 对齐),作为种子/排产的相对基准。""" now = datetime.now() # 当前本地时间 return now.replace(hour=0, minute=0, second=0, microsecond=0) # 归零到当日 00:00