certflow.views.common.qdate_utils 源代码

"""QDate 安全构造与解析工具(UI 层)

Qt 的 ``QDate`` 在参数非法时不会抛异常,而是返回一个「无效」日期;
``QDateEdit.setDate()` 收到无效 QDate 后会静默显示 Qt 最小有效日期
1752-09-14。本模块把这类陷阱收敛为「失败返回 None」的显式语义,
让调用方能给出提示而不是把控件显示成 1752 年。

归属说明:本模块直接依赖 PySide6,按架构蓝图 §2.3 层间规则不得置于
``utils``/``services``/``handlers`` 等无 Qt 层,故归入 ``views/common``。
``certflow.utils.date_utils`` 中保留同名向后兼容垫片。

Examples:
    >>> from certflow.views.common.qdate_utils import parse_qdate, safe_qdate
    >>> safe_qdate(2024, 2, 30) is None
    True
    >>> parse_qdate("not-a-date") is None
    True
"""

from __future__ import annotations

from PySide6.QtCore import QDate

# Qt 的最小有效日期(格里高利历在英美国家的起点),
# 也是 QDateEdit.setDate() 收到无效 QDate 时的「回退零日期」。
# 任何日期解析都绝不能静默回退到这个值。
QT_MIN_VALID_DATE = (1752, 9, 14)


[文档] def safe_qdate(year: int, month: int, day: int) -> QDate | None: """以校验方式构造 QDate,避免静默回退到 Qt 的零日期(1752-09-14) QDate(year, month, day) 在参数非法(如 2 月 30 日、year 越界)时会 返回一个「无效」日期,而 QDateEdit.setDate() 收到无效日期后默认显示 1752-09-14。本方法在构造后显式校验 isValid(),失败时返回 None。 Args: year: 年份 month: 月份 (1-12) day: 日 (1-31,需符合该月实际天数) Returns: QDate | None: 有效的 QDate 实例,参数非法时返回 None """ if not (1 <= month <= 12): return None qd = QDate(year, month, day) if not qd.isValid(): return None return qd
[文档] def parse_qdate(text: str, fmt: str = "yyyy-MM-dd") -> QDate | None: """用指定格式解析日期字符串为 QDate,失败时返回 None QDate.fromString() 解析失败时会返回无效 QDate(setDate 后显示 1752-09-14),这里显式校验 isValid() 后再返回。 Args: text: 日期字符串,如 "2026-07-01" fmt: Qt 日期格式,默认 "yyyy-MM-dd" Returns: QDate | None: 有效的 QDate 实例,解析失败时返回 None """ qd = QDate.fromString(text, fmt) if not qd.isValid(): return None return qd