验证中国大陆身份证号码
/** * 验证中国大陆身份证号码 * @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; }