"""月份参数校验(YYYY-MM)——叶子模块。 报表、月结与调整单共用同一套校验:只校验长度会放过 `2026-13` 这类 非法月份,一路传到 `calendar.monthrange` 才抛 ValueError,最终被全局 处理器当成服务端异常(500)。月份范围必须在入口处拦住,才能返回 400。 """ import re _MONTH_RE = re.compile(r"^\d{4}-(0[1-9]|1[0-2])$") def validate_month(value: str) -> str: """校验 YYYY-MM 且月份 01-12;非法抛 ValueError(Pydantic 友好)。 年份 0000 也拒绝:`date(0, ...)` 同样会抛 ValueError,且业务上不存在。 """ if not _MONTH_RE.match(value) or int(value[:4]) == 0: raise ValueError("月份格式须为 YYYY-MM(01-12)") return value def parse_month(value: str) -> tuple[int, int]: """校验并返回 (year, month),供服务层计算月末等使用。""" validate_month(value) return int(value[:4]), int(value[5:7])