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