You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

南非身份证号出生日期校验异常问题及代码审查请求

南非身份证号出生日期校验代码问题排查与修复

问题根源

你的代码存在几个关键错误,导致二月天数超过29时仍返回true:

  1. 无效的条件分支赋值:第一个if块中,当检测到无效日期(比如二月day>29)时,仅写了isDOBValid;,没有将其赋值为false。而else分支会将isDOBValid设为true,后续的正则判断又会覆盖这个结果。
  2. 冗余且错误的正则判断逻辑:第二个if-else块完全多余,而且只要日期格式符合正则(比如2024-02-30格式合法但实际无效),就会强制将isDOBValid设为true,直接忽略了之前的天数校验。
  3. 字符串比较隐患:month和day是从身份证号截取的字符串,直接用>比较可能出现非预期结果,转为数字比较更严谨。
  4. 缺失闰年判断:原代码允许二月最多29天,但未区分平年和闰年,平年二月最多28天,这也是一个逻辑漏洞。

修复后的代码

function checkDateOfBirth(idNumber) {
    // 截取日期部分并转为数字
    const yearStr = idNumber.substring(0, 2);
    const month = parseInt(idNumber.substring(2, 4), 10);
    const day = parseInt(idNumber.substring(4, 6), 10);
    
    // 确定完整年份(南非身份证号两位年份规则:小于当前年份-2000则归为20xx,否则19xx)
    const currentYear = new Date().getFullYear();
    const cutOff = currentYear - 2000;
    const fullYear = parseInt(yearStr, 10) > cutOff ? 1900 + parseInt(yearStr, 10) : 2000 + parseInt(yearStr, 10);

    // 初始化校验结果为false
    let isDOBValid = false;

    // 基础范围校验
    if (month < 1 || month > 12 || day < 1 || day > 31) {
        return isDOBValid;
    }

    // 处理小月(4、6、9、11月最多30天)
    if ([4, 6, 9, 11].includes(month) && day > 30) {
        return isDOBValid;
    }

    // 处理二月,区分闰年
    if (month === 2) {
        // 闰年判断规则:能被4整除但不能被100整除,或者能被400整除
        const isLeapYear = (fullYear % 4 === 0 && fullYear % 100 !== 0) || (fullYear % 400 === 0);
        if ((isLeapYear && day > 29) || (!isLeapYear && day > 28)) {
            return isDOBValid;
        }
    }

    // 所有校验通过,设为true
    isDOBValid = true;
    return isDOBValid;
}

修复说明

  • 将month和day转为数字,避免字符串比较的潜在问题。
  • 移除冗余的正则判断,改用实际的日期逻辑校验,确保格式和有效性都正确。
  • 新增闰年判断,严格校验二月的天数(平年28天,闰年29天)。
  • 简化分支逻辑,一旦检测到无效条件直接返回false,避免后续逻辑覆盖结果。
  • 优化年份计算逻辑,直接转为完整数字年份,便于闰年判断。

内容的提问来源于stack exchange,提问作者PalesaDev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 14:25:19