现在的身份证一般有两种类型:
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;
}
上面的代码,我稍微改了一下下,可能不能一拷贝就用,但是稍微调试一下应该就可以了