场景与实训 - 匹配身份证号 ¶
作者:KK
发表日期:2018.8.9
要点速读 ¶
- 身份证号码的构成是有一定规则的,每几位数有不同的含义,正则表达式只能校验它的格式,但不能准确校验有效性,真正要校验身份证号的有效性那得写一个大函数。
身份证号码的构成 ¶
这是【中华人民共和国国家标准GB11643-1999】(简称 国标11643-1999)对身份证号码构成的规则定义。
正则表达式 ¶
JS和PHP版:/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
测试代码:/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test('你和你家人的身份证号码')
但这只能测试格式是否正确,比如我国并不存在16,26开头的地区,却可通过验证;
日期判定不够精确,例如 19490231 也可通过验证,而2月并不存在31日;
校验码是由17位本体码计算得出,以上表达式并未校验此码。
下面到函数校验
校验函数 ¶
这是一个JS版的函数(来源于github - wusfen/cnIDCardNumberValidation):
(function() {
var map = {
// 省
'1-2': {
// 华北地区
11: '北京市',
12: '天津市',
13: '河北省',
14: '山西省',
15: '内蒙古自治区',
// 东北地区
21: '辽宁省',
22: '吉林省',
23: '黑龙江省',
// 华东地区
31: '上海市',
32: '江苏省',
33: '浙江省',
34: '安徽省',
35: '福建省',
36: '江西省',
37: '山东省',
// 华中地区
41: '河南省',
42: '湖北省',
43: '湖南省',
// 华南地区
44: '广东省',
45: '广西壮族自治区',
46: '海南省',
// 西南地区
51: '四川省',
52: '贵州省',
53: '云南省',
54: '西藏自治区',
50: '重庆市',
// 西北地区
61: '陕西省',
62: '甘肃省',
63: '青海省',
64: '宁夏回族自治区',
65: '新疆维吾尔自治区',
// 特别地区:
71: '台湾地区', //(886)
81: '香港特别行政区', //(852)
82: '澳门特别行政区', //(853)
},
// 市
'3-4': 0,
// 区
'5-6': 0,
// 生日
'7-14': function(dateStr) {
dateStr = dateStr.replace(/(\d{4}|\d{2})(?=\d)/g, '$1-');
var date = new Date(dateStr);
var x = new Date('x') + '';
return date == x ? null : dateStr;
},
// 顺序码 奇数男偶数女
'15-17': function(str3) {
return (+str3) % 2;
},
// 校验码
/*
1、将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。
2、将这17位数字和系数相乘的结果相加。
3、用加出来和除以11,看余数是多少?
4、余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字。其分别对应的最后一位身份证的号码为1-0-X -9-8-7-6-5-4-3-2。(即馀数0对应1,馀数1对应0,馀数2对应X...)
5、通过上面得知如果余数是3,就会在身份证的第18位数字上出现的是9。如果对应的数字是2,身份证的最后一位号码就是罗马数字x。
*/
'18': function(idStr) {
// 1
var x = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
// 2
var sum = 0;
for (var i = 0; i < 17; i++) {
sum += idStr.substr(i, 1) * x[i];
}
// 3
var mod = sum % 11;
// 4
var mx = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2];
// 5
return mx[mod] == idStr.substr(17).toUpperCase();
}
}
/**
* 身份证号码校验
* @param {String} idStr - 身份证号码
* @return {false|Object} - 合法则返回信息(省,生日,性别),否则 false
*/
function validate(idStr) {
// console.log(idStr.substring(7-1, 14));
//
// 省
var province = map['1-2'][idStr.substr(0, 2)];
if (!province) {
return false
};
// 市
// 区
// 生日
var date = map['7-14'](idStr.substr(6, 8));
if (!date) {
return false
};
// 顺序码 奇数男偶数女
var sex = map['15-17'](idStr.substr(14, 3));
// 校验码
if (!map['18'](idStr)) {
return false
};
return {
province: province,
date: date,
sex: sex == 1 ? '男' : '女'
};
}
// export
if (typeof define == 'function' && (define.amd || define.cmd)) {
define(function(require, exports, module) {
return module.exports = validate;
});
} else
if (typeof module != 'undefined') {
module.exports = validate;
} else {
window.cnIDCardNumberValidate = validate;
}
})();
调用代码:
//普通模式的网页把以上JS函数复制到公共JS文件中,然后直接以下代码调用:
cnIDCardNumberValidate('你要测试的身份证号码');
//模块化开发的调用示例:
let cnIDCardNumberValidate = require('函数文件');
cnIDCardNumberValidate('你要测试的身份证号码');