/**
* 验证中国大陆身份证号码
* @param {string} idCard 身份证号码
* @returns {boolean} 是否有效
*/
function validateIdCard(idCard) {
// 1. 输入验证
if (typeof idCard !== 'string') return false;
// 2. 清理和标准化输入
const cleanedId = idCard.trim().toUpperCase();
// 3. 长度验证
if (cleanedId.length !== 15 && cleanedId.length !== 18) return false;
// 4. 正则表达式验证
const reg18 = /^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dX]$/;
const reg15 = /^[1-9]\d{5}\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}$/;
if (!(reg18.test(cleanedId) || reg15.test(cleanedId))) {
return false;
}
// 5. 18位身份证详细验证
if (cleanedId.length === 18) {
// 5.1 校验码验证
const weightFactors = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
const checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
const sum = weightFactors.reduce((acc, factor, index) =>
acc + parseInt(cleanedId[index], 10) * factor, 0);
const checkBit = cleanedId[17];
if (checkCodes[sum % 11] !== checkBit) {
return false;
}
// 5.2 日期验证
const year = parseInt(cleanedId.substring(6, 10));
const month = parseInt(cleanedId.substring(10, 12)) - 1;
const day = parseInt(cleanedId.substring(12, 14));
// 创建日期对象并验证
const date = new Date(year, month, day);
// 检查日期是否有效
if (
date.getFullYear() !== year ||
date.getMonth() !== month ||
date.getDate() !== day
) {
return false;
}
// 5.3 特殊日期检查(如2月29日)
if (month === 1) { // 2月
const isLeapYear = (year % 400 === 0) || (year % 100 !== 0 && year % 4 === 0);
if (day > (isLeapYear ? 29 : 28)) return false;
}
// 5.4 其他月份天数检查
const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
if (day > daysInMonth[month]) {
return false;
}
// 5.5 地区代码验证
const provinceCode = cleanedId.substring(0, 2);
const validProvinceCodes = new Set([
'11', '12', '13', '14', '15', '21', '22', '23',
'31', '32', '33', '34', '35', '36', '37', '41',
'42', '43', '44', '45', '46', '50', '51', '52',
'53', '54', '61', '62', '63', '64', '65', '71',
'81', '82', '91'
]);
if (!validProvinceCodes.has(provinceCode)) {
return false;
}
}
// 6. 15位身份证验证
if (cleanedId.length === 15) {
const month = parseInt(cleanedId.substring(8, 10)) - 1;
const day = parseInt(cleanedId.substring(10, 12));
// 简单日期验证
if (month < 0 || month > 11 || day < 1 || day > 31) {
return false;
}
}
return true;
}