"""中国大陆身份证号解析(周岁年龄)。""" from __future__ import annotations import re from datetime import date from typing import Optional _ID18_RE = re.compile(r"^\d{17}[\dX]$") def calc_age_from_chinese_id_card( id_card: Optional[str], *, today: Optional[date] = None, ) -> Optional[int]: """从 18 位身份证号计算周岁。号码不完整或出生日期无效时返回 None。""" if not id_card or not isinstance(id_card, str): return None s = id_card.strip().upper() if not _ID18_RE.match(s): return None try: year = int(s[6:10]) month = int(s[10:12]) day = int(s[12:14]) except ValueError: return None try: birth = date(year, month, day) except ValueError: return None ref = today or date.today() age = ref.year - birth.year if (ref.month, ref.day) < (birth.month, birth.day): age -= 1 if age < 0 or age > 120: return None return age