天天看点

严格的身份证校验(JavaScript版)

拜读了不动声色的蜗牛老师的博客《最严格的身份证校验(JavaScript版)》,觉得非常好用,参考着写下这篇博客,作为记录。代码部分基本都是不动声色的蜗牛老师原来的,根据实际项目情况以及自己的代码习惯修改了些,逻辑修改微乎其微。

简单说明一下居民身份证号码的规则:

由18位组成:前六位为行政区划代码,第七至第十四位为出生日期码,第15至17位为顺序码,第17位代表性别(奇数为男,偶数为女),第18位为校验码。作为尾号的校验码,是由号码编制单位按统一的公式计算出来的,如果某人的尾号是0-9,都不会出现X,但如果尾号是10,那么就得用X来代替。

身份证中第十八位数字的计算方法为:

  (一)、将前面的身份证号码17位数分别乘以不同的系数(加权因子)。从第一位到第十七位的系数分别为:7、9、10、5、8、4、2、1、6、3、7、9、10、5、8、4、2。

  (二)、将这17位数字和系数相乘的结果相加。

  (三)、用加出来和除以11,看余数是多少?

  (四)、余数只可能有0 、1、 2、 3、 4、 5、 6、 7、 8、 9、 10这11个数字。其分别对应的最后一位身份证的号码为1、0、X、9、8、7、6、5、4、3、2.。比如说,如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2。

  倒数第二位是用来表示性别的

  例如:某男性的身份证号码是34052419800101001X。我们要看看这个身份证是不是合法的身份证。

  首先:我们得出,前17位的加权乘积和是189

  然后:用189除以11得出的结果是17 + 2/11,也就是说余数是2。

  最后:通过对应规则就可以知道余数2对应的数字是x。所以,这是一个合格的身份证号码。

js代码:

function validateCertificateNo(certificateNo) {
  if (!certificateNo) {
    console.log("身份证号码不可以为空!");
    return false;
  }
  if (certificateNo.length == 18) {
    let address = certificateNo.substring(0, 6); // 6位,地区代码
    let birthday = certificateNo.substring(6, 14); // 8位,出生日期
    let sequenceCode = certificateNo.substring(14, 17); // 3位,顺序码:奇为男,偶为女
    let checkCode = certificateNo.substring(17); // 1位,校验码:检验位
    console.log("身份证号码:" + certificateNo + "、地区代码:" + address + "、出生日期:" + birthday + "、顺序码:" + sequenceCode + "、校验码:" + checkCode);

    const province = {
      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 (!province[parseInt(address.substr(0, 2))]) {
      console.log("前两位地区代码无效,请重新输入!!!");
      return false;
    }

    let year = birthday.substring(0, 4);
    let month = birthday.substring(4, 6);
    let day = birthday.substring(6);
    let tempDate = new Date(year, parseFloat(month) - 1, parseFloat(day));

    // 这里用getFullYear()获取年份,避免千年虫问题
    if ((tempDate.getFullYear() != parseFloat(year) || tempDate.getMonth() != parseFloat(month) - 1 || tempDate.getDate() != parseFloat(day))) {
      console.log("出生日期无效,请重新输入!!!");
      return false;
    }

    const weightedFactors = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1]; // 加权因子   
    const valideCode = [1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2]; // 身份证校验码值,其中10代表X

    let certificateNoArray = certificateNo.split(""); // 得到身份证数组

    let sum = 0; // 声明加权求和变量

    if (certificateNoArray[17].toLowerCase() == 'x') {
      certificateNoArray[17] = 10; // 将最后位为x的验证码替换为10  
    }
    for (let i = 0; i < 17; i++) {
      sum += weightedFactors[i] * certificateNoArray[i]; // 加权求和   
    }
    valCodePosition = sum % 11; // 得到验证码所在位置
    if (certificateNoArray[17] == valideCode[valCodePosition]) {
      console.log("身份证号码有效,性别为:" + ((sequenceCode % 2 == 0) ? "女" : "男") + "!");
      return true;
    } else {
      console.log("校验码无效,请重新输入!!!");
      return false;
    }
  }
  console.log("身份证号码位数不正确,请重新输入!!!");
  return false;
}
           

继续阅读