42 lines
1013 B
Python
42 lines
1013 B
Python
"""中国大陆身份证号解析(周岁年龄)。"""
|
|
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
|