35 lines
1.1 KiB
TypeScript
35 lines
1.1 KiB
TypeScript
/**
|
|
* 从中国大陆 18 位身份证号解析出生日期并计算周岁年龄。
|
|
* 号码不足 18 位或出生日期无效时返回 null(不强制校验码,便于输入过程中回填)。
|
|
*/
|
|
export function calcAgeFromChineseIdCard(idCard: string | null | undefined): number | null {
|
|
if (!idCard || typeof idCard !== 'string') return null
|
|
const s = idCard.trim().toUpperCase()
|
|
if (!/^\d{17}[\dX]$/.test(s)) return null
|
|
|
|
const year = Number(s.slice(6, 10))
|
|
const month = Number(s.slice(10, 12))
|
|
const day = Number(s.slice(12, 14))
|
|
if (!Number.isFinite(year) || !Number.isFinite(month) || !Number.isFinite(day)) return null
|
|
if (month < 1 || month > 12 || day < 1 || day > 31) return null
|
|
|
|
const birth = new Date(year, month - 1, day)
|
|
if (
|
|
birth.getFullYear() !== year ||
|
|
birth.getMonth() !== month - 1 ||
|
|
birth.getDate() !== day
|
|
) {
|
|
return null
|
|
}
|
|
|
|
const today = new Date()
|
|
let age = today.getFullYear() - year
|
|
const beforeBirthday =
|
|
today.getMonth() < month - 1 ||
|
|
(today.getMonth() === month - 1 && today.getDate() < day)
|
|
if (beforeBirthday) age -= 1
|
|
|
|
if (age < 0 || age > 120) return null
|
|
return age
|
|
}
|