根據(jù)國人身份證校驗(yàn)規(guī)則調(diào)整外國人身份證校驗(yàn)
根據(jù)國家移民管理局公布的新版外國人永久居留身份證適配性改造要點(diǎn)。核心點(diǎn)如果下圖:
你會(huì)發(fā)現(xiàn)18位身份證,我們的身份證和外國人永居證的差別只是前6位的校驗(yàn)不同访敌。
- 身份證校驗(yàn)規(guī)則:
//身份證
function checkSFZ(_sfz) {
var vcity = {
11: "北京",
12: "天津",
13: "河北",
14: "山西",
15: "內(nèi)蒙古",
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: "臺(tái)灣",
81: "香港",
82: "澳門",
91: "國外"
};
// 檢查號碼是否符合規(guī)范豹绪,包括長度茎刚,類型
var isCardNo = function (card) {
// 身份證號碼為15位或者18位梧却,15位時(shí)全為數(shù)字缘挑,18位前17位為數(shù)字鸣剪,最后一位是校驗(yàn)位沟突,可能為數(shù)字或字符X
var reg = /(^\d{15}$)|(^\d{17}(\d|X)$)/;
if (reg.test(card) === false) {
return false;
}
return true;
};
// 取身份證前兩位,校驗(yàn)省份
var checkProvince = function (card) {
var province = card.substr(0, 2);
if (vcity[province] == undefined) {
return false;
}
return true;
};
// 檢查生日是否正確
var checkBirthday = function (card) {
var len = card.length;
// 身份證15位時(shí)花颗,次序?yàn)槭。?位)市(3位)年(2位)月(2位)日(2位)校驗(yàn)位(3位)惠拭,皆為數(shù)字
if (len == '15') {
var re_fifteen = /^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/;
var arr_data = card.match(re_fifteen);
var year = arr_data[2];
var month = arr_data[3];
var day = arr_data[4];
var birthday = new Date('19' + year + '/' + month + '/' + day);
return verifyBirthday('19' + year, month, day, birthday);
}
// 身份證18位時(shí)扩劝,次序?yàn)槭。?位)市(3位)年(4位)月(2位)日(2位)校驗(yàn)位(4位)职辅,校驗(yàn)位末尾可能為X
if (len == '18') {
var re_eighteen = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/;
var arr_data = card.match(re_eighteen);
var year = arr_data[2];
var month = arr_data[3];
var day = arr_data[4];
var birthday = new Date(year + '/' + month + '/' + day);
return verifyBirthday(year, month, day, birthday);
}
return false;
};
// 校驗(yàn)日期
var verifyBirthday = function (year, month, day, birthday) {
var now = new Date();
var now_year = now.getFullYear();
// 年月日是否合理
if (birthday.getFullYear() == year
&& (birthday.getMonth() + 1) == month
&& birthday.getDate() == day) {
// 判斷年份的范圍(3歲到100歲之間)
var time = now_year - year;
if (time <= 120) {
return true;
}
return false;
}
return false;
};
// 校驗(yàn)位的檢測
var checkParity = function (card) {
// 15位轉(zhuǎn)18位
card = changeFivteenToEighteen(card);
var len = card.length;
if (len == '18') {
var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10,
5, 8, 4, 2);
var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5',
'4', '3', '2');
var cardTemp = 0, i, valnum;
for (i = 0; i < 17; i++) {
cardTemp += card.substr(i, 1) * arrInt[i];
}
valnum = arrCh[cardTemp % 11];
if (valnum == card.substr(17, 1)) {
return true;
}
return false;
}
return false;
};
// 15位轉(zhuǎn)18位身份證號
var changeFivteenToEighteen = function (card) {
if (card.length == '15') {
var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10,
5, 8, 4, 2);
var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5',
'4', '3', '2');
var cardTemp = 0, i;
card = card.substr(0, 6) + '19'
+ card.substr(6, card.length - 6);
for (i = 0; i < 17; i++) {
cardTemp += card.substr(i, 1) * arrInt[i];
}
card += arrCh[cardTemp % 11];
return card;
}
return card;
};
var checkCode = function (_sfz) {
// 是否為空
if (_sfz === '') {
// alert('請輸入身份證號棒呛,身份證號不能為空');
return false;
}
// 校驗(yàn)長度,類型
if (isCardNo(_sfz) === false) {
// alert('您輸入的身份證號碼不正確域携,請重新輸入');
return false;
}
// 檢查省份
if (checkProvince(_sfz) === false) {
// alert('您輸入的身份證號碼不正確,請重新輸入');
return false;
}
// 校驗(yàn)生日
if (checkBirthday(_sfz) === false) {
// alert('您輸入的身份證號碼生日不正確,請重新輸入');
return false;
}
// 檢驗(yàn)位的檢測
if (checkParity(_sfz) === false) {
// alert('您的身份證校驗(yàn)位不正確,請重新輸入');
return false;
}
return true;
}
return checkCode(_sfz);
}
- 外國人永居證校驗(yàn)規(guī)則:
//外國人身份證(新版永居證證件號碼18位)
function checkOutSFZ(_sfz) {
//參考移民管理局的文檔:https://www.nia.gov.cn/20231013/2.pdf
//格式:9(身份標(biāo)識碼) 32(受理地代碼) 682(國家和地區(qū)代碼) 19850101(出生日期) 001(順序碼) 7(校驗(yàn)碼)簇秒。
var vcity = {
11: "北京",
12: "天津",
13: "河北",
14: "山西",
15: "內(nèi)蒙古",
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: "臺(tái)灣",
81: "香港",
82: "澳門",
91: "國外"
};
// 檢查號碼是否符合規(guī)范,包括長度秀鞭,類型
var isCardNo = function (card) {
//18位前17位為數(shù)字趋观,最后一位是校驗(yàn)位,可能為數(shù)字或字符X
var reg = /(^\d{17}(\d|X)$)/;
if (reg.test(card) === false) {
return false;
}
return true;
};
// 取身份證前1位,校驗(yàn)身份標(biāo)識锋边,1-8位國內(nèi)人士皱坛,9為外國人。
var personMark = function (card){
var mark = card.substring(0,1);
return mark==9;//是外國人
};
// 取身份證前2,3位,校驗(yàn)省份
var checkProvince = function (card) {
var province = card.substring(1,3);
if (vcity[province] == undefined) {
return false;
}
return true;
};
// 檢查生日是否正確
var checkBirthday = function (card) {
var len = card.length;
// 身份證15位時(shí)豆巨,次序?yàn)槭剩辟。?位)市(3位)年(2位)月(2位)日(2位)校驗(yàn)位(3位),皆為數(shù)字
if (len == '15') {
var re_fifteen = /^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/;
var arr_data = card.match(re_fifteen);
var year = arr_data[2];
var month = arr_data[3];
var day = arr_data[4];
var birthday = new Date('19' + year + '/' + month + '/' + day);
return verifyBirthday('19' + year, month, day, birthday);
}
// 身份證18位時(shí)往扔,次序?yàn)槭贩猎。?位)市(3位)年(4位)月(2位)日(2位)校驗(yàn)位(4位),校驗(yàn)位末尾可能為X
if (len == '18') {
var re_eighteen = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/;
var arr_data = card.match(re_eighteen);
var year = arr_data[2];
var month = arr_data[3];
var day = arr_data[4];
var birthday = new Date(year + '/' + month + '/' + day);
return verifyBirthday(year, month, day, birthday);
}
return false;
};
// 校驗(yàn)日期
var verifyBirthday = function (year, month, day, birthday) {
var now = new Date();
var now_year = now.getFullYear();
// 年月日是否合理
if (birthday.getFullYear() == year
&& (birthday.getMonth() + 1) == month
&& birthday.getDate() == day) {
// 判斷年份的范圍(3歲到100歲之間)
var time = now_year - year;
if (time <= 120) {
return true;
}
return false;
}
return false;
};
// 校驗(yàn)位的檢測
var checkParity = function (card) {
// 15位轉(zhuǎn)18位
card = changeFivteenToEighteen(card);
var len = card.length;
if (len == '18') {
var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10,
5, 8, 4, 2);
var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5',
'4', '3', '2');
var cardTemp = 0, i, valnum;
for (i = 0; i < 17; i++) {
cardTemp += card.substr(i, 1) * arrInt[i];
}
valnum = arrCh[cardTemp % 11];
if (valnum == card.substr(17, 1)) {
return true;
}
return false;
}
return false;
};
// 15位轉(zhuǎn)18位身份證號
var changeFivteenToEighteen = function (card) {
if (card.length == '15') {
var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10,
5, 8, 4, 2);
var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5',
'4', '3', '2');
var cardTemp = 0, i;
card = card.substr(0, 6) + '19'
+ card.substr(6, card.length - 6);
for (i = 0; i < 17; i++) {
cardTemp += card.substr(i, 1) * arrInt[i];
}
card += arrCh[cardTemp % 11];
return card;
}
return card;
};
var checkCode = function (_sfz) {
// 是否為空
if (_sfz === '') {
// alert('請輸入身份證號萍膛,身份證號不能為空');
return false;
}
// 校驗(yàn)長度吭服,類型
if (isCardNo(_sfz) === false) {
// alert('您輸入的身份證號碼不正確,請重新輸入');
return false;
}
// 檢查身份標(biāo)識蝗罗,國內(nèi)人噪馏,還是外國人
if (personMark(_sfz) === false) {
// alert('您輸入的身份證號碼不正確,請重新輸入');
return false;
}
if (checkProvince(_sfz) === false) {
// alert('您輸入的身份證號碼不正確,請重新輸入');
return false;
}
// 校驗(yàn)生日
if (checkBirthday(_sfz) === false) {
// alert('您輸入的身份證號碼生日不正確,請重新輸入');
return false;
}
// 檢驗(yàn)位的檢測
if (checkParity(_sfz) === false) {
// alert('您的身份證校驗(yàn)位不正確,請重新輸入');
return false;
}
return true;
}
return checkCode(_sfz);
}
注:如果你想校驗(yàn)得更詳細(xì),可以把國家代碼校驗(yàn)(證號的前4-6位绿饵,參考全球所有的國家代碼/國家區(qū)號欠肾,添加枚舉校驗(yàn)),性別校驗(yàn)(證號的倒數(shù)第2位拟赊,1-男刺桃,2-女)加上。甚至2017 版外國人永久居留身份證也能做一些基礎(chǔ)校驗(yàn)吸祟。這個(gè)自行添加瑟慈。