id_card.py 1013 B

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. """中国大陆身份证号解析(周岁年龄)。"""
  2. from __future__ import annotations
  3. import re
  4. from datetime import date
  5. from typing import Optional
  6. _ID18_RE = re.compile(r"^\d{17}[\dX]$")
  7. def calc_age_from_chinese_id_card(
  8. id_card: Optional[str],
  9. *,
  10. today: Optional[date] = None,
  11. ) -> Optional[int]:
  12. """从 18 位身份证号计算周岁。号码不完整或出生日期无效时返回 None。"""
  13. if not id_card or not isinstance(id_card, str):
  14. return None
  15. s = id_card.strip().upper()
  16. if not _ID18_RE.match(s):
  17. return None
  18. try:
  19. year = int(s[6:10])
  20. month = int(s[10:12])
  21. day = int(s[12:14])
  22. except ValueError:
  23. return None
  24. try:
  25. birth = date(year, month, day)
  26. except ValueError:
  27. return None
  28. ref = today or date.today()
  29. age = ref.year - birth.year
  30. if (ref.month, ref.day) < (birth.month, birth.day):
  31. age -= 1
  32. if age < 0 or age > 120:
  33. return None
  34. return age