身份证验证算法

现在的身份证一般有两种类型:
15位校验规则 6位地址编码+6位出生日期+3位顺序号
18位校验规则 6位地址编码+8位出生日期+3位顺序号+1位校验位
排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
地址码表示编码对象常住户口所在县(市、旗、区)的行政区划代码。
出生日期码表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。
顺序码表示同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。顺序码的奇数分给男性,偶数分给女性。
校验码是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。
15位的身份证编码首先把出生年扩展为4位,简单的就是增加一个19或18,这样就包含了所有1800-1999年出生的人;
2000年后出生的肯定都是18位的了没有这个烦恼,至于1800年前出生的,还没身份证号
出生日期1800-2099 (18|19|20)?\d{2}(0[1-9]|1[12])(0[1-9]|[12]\d|3[01])
身份证正则表达式 /^\d{6}(18|19|20)?\d{2}(0[1-9]|1[12])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i。
其中最重要的就是校验位的规则,根据最后一位来判断该身份证号码是否符合条件,这个判断非常有用,前端可以做非常好的限制,且不需要请求后台。
校验位规则 公式:∑(ai×Wi)(mod 11)……………………………………(1)
公式(1)中:
i----表示号码字符从由至左包括校验码在内的位置序号;
ai----表示第i位置上的号码字符值;
Wi----示第i位置上的加权因子,其数值依据公式Wi=2^(n-1)(mod 11)计算得出。
i :18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
Wi :7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1

 //主要利用到的正则表达式
var  reg =  /^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|
(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$/;

//主要的提示模块:
var errorTip = {
     birthday : {
         zh : '此报名人身份证信息与所填生日不符',
         en : 'ID card information does not match the date of birth'
     },
     gender : {
         zh : '此报名人身份证信息与所填性别不符',
         en : 'ID card information does not match the gender'
     },
     id : {
         zh : '身份证号格式错误',
         en : 'ID card information in the wrong format'
     }
 };
//主要的地址模块city,可以更具需求添加
//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:"国外 "

 /**
 判断是否为同一天
  *  +new Date('1992-1-1')
     694195200000
     +new Date('1992-01-01')
     694224000000
  * @param d1
  * @param d2
  */
 function sameDay(d1, d2) {
  //~~转换成数字类型,并且为整数
     return ! (~~ ((new Date(d1).getTime() - new Date(d2).getTime()) / 86400000))
 }
 var _langType = window.$CONFIG && window.$CONFIG.lang || 'zh';
 //写上自己的表达式
 var dateReg = /^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-
 (?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|
 (?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|
 (?:0[48]|[2468][048]|[13579][26])00)-02-29)$/;    
 /**
  * @param param 身份证号
  * @param birthday 需要比对的生日
  * @param gender 需要比对的性别
  * @returns {*}
  */
 function identityCodeValid(param, birthday, gender) {
     var code = param.toString().toUpperCase();
     if (!code){ //这里不对为空的字符串判断, form表单会对require元素做必填验证, 允许非必填时身份证为空, 业务需求
         return {
             valid : true
         };
     }
     var city={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:"国外 "};
     var tip = "";
     var pass= true;
     var longType = code.length == 18;
     var _birthday = longType ? code.substr(6,8) : '19' + code.substr(6,6);
     var _gender = longType ? code[16] : code[14];

     _birthday = _birthday.substr(0,4) + '-' + _birthday.substr(4,2) + '-' + _birthday.substr(6,2);
     _gender = (_gender % 2) ? 'M' : 'F'; // 奇数为男

     if(!code || !/^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i.test(code)){
         // tip = "身份证号格式错误";
         pass = false;
     } else if(!city[code.substr(0,2)]){
         // tip = "地址编码错误";
         pass = false;
     } else if(!checkBirthday(_birthday)){
         // tip = "出生日期格式有误";
         pass = false;
     } else if (birthday && !sameDay(birthday, _birthday)) {
         tip = errorTip.birthday[_langType];
         pass = false;
     } else if (gender && _gender != gender) {
         tip = errorTip.gender[_langType];
         pass = false;
     } else {
         //18位身份证需要验证最后一位校验位
         if(longType){
             //∑(ai×Wi)(mod 11)
             //加权因子
             var factor = [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 ];
             //校验位
             var parity = [ 1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2 ];
             var sum = 0;
             for (var i = 0; i < 17; i++) {
                 sum += code[i] * factor[i];
             }
             var last = parity[sum % 11];
             if(last != code[17]){
                 // tip = "校验位错误";
                 pass =false;
             }
         }
     }
     if(!pass) console.log(tip);
     return {
         valid : pass,
         msg : pass ? '' : (tip || errorTip.id[_langType])
     };
 }

 function checkBirthday(birthday){
     return dateReg.test(birthday);
 }
 function sameDay(d1, d2) {
     return ! (~~ ((new Date(d1).getTime() - new Date(d2).getTime()) / 86400000));
  //可以直接利用之前写的,当然也可以自己添加一些属于自己的验证写法
  //...
     //return true;
 }

上面的代码,我稍微改了一下下,可能不能一拷贝就用,但是稍微调试一下应该就可以了

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页