1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="UTF-8"> 6 <title></title> 7 <style type="text/css"> 8 #main { 9 padding: 100px 0 0 100px; 10 } 11 12 input { 13 font-size: 20px; 14 } 15 </style> 16 <script type="text/javascript" src="js/IDCardValid.js"></script> 17 <script type="text/javascript"> 18 function valid(){ 19 let code = document.getElementById("idinf").value; 20 let message = IDCardV(code); 21 alert(message) 22 } 23 </script> 24 </head> 25 26 <body> 27 <div id="main"> 28 <form action="" onsubmit=""> 29 <input type="text" id="idinf" value="" placeholder="身份证" /> 30 <input type="button" onclick="valid()" value="查看" /> 31 </form> 32 </div> 33 </body> 34 35 </html>
1 /* 2 根据〖中华人民共和国国家标准 GB 11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。 3 地址码表示编码对象常住户口所在县(市、旗、区)的行政区划代码。 4 出生日期码表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。 5 顺序码表示同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。顺序码的奇数分给男性,偶数分给女性。 6 校验码是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。 7 8 出生日期计算方法。 9 15位的身份证编码首先把出生年扩展为4位,简单的就是增加一个19或18,这样就包含了所有1800-1999年出生的人; 10 2000年后出生的肯定都是18位的了没有这个烦恼,至于1800年前出生的,那啥那时应该还没身份证号这个东东,⊙﹏⊙b汗... 11 下面是正则表达式: 12 出生日期1800-2099 (18|19|20)?\d{2}(0[1-9]|1[12])(0[1-9]|[12]\d|3[01]) 13 身份证正则表达式 /^\d{6}(18|19|20)?\d{2}(0[1-9]|1[12])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i 14 15位校验规则 6位地址编码+6位出生日期+3位顺序号 15 18位校验规则 6位地址编码+8位出生日期+3位顺序号+1位校验位 16 17 校验位规则 公式:∑(ai×Wi)(mod 11)……………………………………(1) 18 公式(1)中: 19 i----表示号码字符从由至左包括校验码在内的位置序号; 20 ai----表示第i位置上的号码字符值; 21 Wi----示第i位置上的加权因子,其数值依据公式Wi=2^(n-1)(mod 11)计算得出。 22 i 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 23 Wi 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1 24 25 */ 26 //身份证号合法性验证 27 //支持15位和18位身份证号 28 //支持地址编码、出生日期、校验位验证 29 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: "国外 " }; 30 31 function IDCardV(card) { 32 //是否为空 33 if(card === '') { 34 return "请输入信息"; 35 } 36 //校验长度,类型 37 if(isCardNo(card) === false) { 38 return "请输入正确信息"; 39 } 40 //检查省份 41 if(checkProvince(card) === false) { 42 return "省份信息有误,请检查"; 43 } 44 //校验生日 45 if(checkBirthday(card) === false) { 46 return "生日信息有误,请检查"; 47 } 48 //检验位的检测 49 if(checkParity(card) === false) { 50 return "校验位有误,请检查"; 51 } 52 return IDCardInf("210124199204181015"); 53 } 54 55 //检查号码是否符合规范,包括长度,类型 56 isCardNo = function(card) { 57 //身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X 58 var reg = /(^\d{15}$)|(^\d{17}(\d|X)$)/; 59 if(reg.test(card) === false) { 60 return false; 61 } 62 return true; 63 }; 64 //取身份证前两位,校验省份 65 checkProvince = function(card) { 66 var province = card.substr(0, 2); 67 if(city[province] === undefined) { 68 return false; 69 } 70 return true; 71 }; 72 73 //获取生日 74 checkBirthday = function(card) { 75 var len = card.length; 76 //身份证15位时,次序为省(3位)市(3位)年(2位)月(2位)日(2位)校验位(3位),皆为数字 77 if(len == '15') { 78 var re_fifteen = /^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/; 79 var arr_data = card.match(re_fifteen); 80 var year = arr_data[2]; 81 var month = arr_data[3]; 82 var day = arr_data[4]; 83 var birthday = new Date('19' + year + '/' + month + '/' + day); 84 return verifyBirthday('19' + year, month, day, birthday); 85 } 86 //身份证18位时,次序为省(3位)市(3位)年(4位)月(2位)日(2位)校验位(4位),校验位末尾可能为X 87 if(len == '18') { 88 var re_eighteen = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/; 89 var arr_data = card.match(re_eighteen); 90 var year = arr_data[2]; 91 var month = arr_data[3]; 92 var day = arr_data[4]; 93 var birthday = new Date(year + '/' + month + '/' + day); 94 return verifyBirthday(year, month, day, birthday); 95 } 96 return false; 97 } 98 99 //校验日期 100 verifyBirthday = function(year, month, day, birthday) { 101 var now = new Date(); 102 var now_year = now.getFullYear(); 103 //年月日是否合理 104 if(birthday.getFullYear() == year && (birthday.getMonth() + 1) == month && birthday.getDate() == day) { 105 //判断年份的范围(3岁到100岁之间) 106 var time = now_year - year; 107 if(time >= 0 && time <= 100) { 108 return true; 109 } 110 return false; 111 } 112 return false; 113 }; 114 //校验位的检测 115 checkParity = function(card) { 116 //15位转18位 117 card = changeFivteenToEighteen(card); 118 var len = card.length; 119 if(len == '18') { 120 var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); 121 var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); 122 var cardTemp = 0, 123 i, valnum; 124 for(i = 0; i < 17; i++) { 125 cardTemp += card.substr(i, 1) * arrInt[i]; 126 } 127 valnum = arrCh[cardTemp % 11]; 128 if(valnum == card.substr(17, 1)) { 129 return true; 130 } 131 return false; 132 } 133 return false; 134 }; 135 //15位转18位身份证号 136 changeFivteenToEighteen = function(card) { 137 if(card.length == '15') { 138 var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); 139 var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); 140 var cardTemp = 0, 141 i; 142 card = card.substr(0, 6) + '19' + card.substr(6, card.length - 6); 143 for(i = 0; i < 17; i++) { 144 cardTemp += card.substr(i, 1) * arrInt[i]; 145 } 146 card += arrCh[cardTemp % 11]; 147 return card; 148 } 149 return card; 150 }; 151 152 //获取生日,性别,省份 153 IDCardInf = function(card) { 154 var year; 155 var month; 156 var day; 157 var sex; 158 var province; 159 if(card.length == 15) { 160 year = card.substr(6, 2); 161 month = card.substr(8, 2); 162 day = card.substr(10, 2); 163 sex = parseInt(card.substr(14, 1)) % 2 ? "男" : "女"; 164 province=city[card.substring(0, 2)]; 165 return "19" + year + "-" + month + "-" + day + " | " + sex + " | " + province; 166 } else if(card.length == 18) { 167 year = card.substr(6, 4); 168 month = card.substr(10, 2); 169 day = card.substr(12, 2); 170 sex = parseInt(card.substr(16, 1)) % 2 ? "男" : "女"; 171 province=city[card.substring(0, 2)]; 172 return year + "-" + month + "-" + day + " | " + sex + " | " + province; 173 } else { 174 return "未知"; 175 } 176 }
URL校验正则表达式,自己测了一下 ,基本满足大部分url地址的校验:
(((ht|f)tp(s?))\://)? ([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)* ( (25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[1-9])\. ((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.){2} (25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]{1}|[0-9]) |localhost|([a-zA-Z0-9\-]+\.)* [a-zA-Z0-9\-]+\. (com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}) ) (\:[0-9]+)* (/($|[a-zA-Z0-9\.\,\?\:\"\/\'\\\+&%\$#\=~_\-]+))*
说明一下:当校验的值较长,例如“http://mpension.taikang.com/PubOauthYL/OauthCOdeServlet?wechat_card_js=1&redirectUrl=http://mpension.taikang.com/wxCardCouponYL/GetuserInfoByOauth¶m=”时,会等待较长时间。个人测得时候同时校验八个URL地址,chorme浏览器大约在二十多秒到三十多秒之间,Firefox和ie都卡死了。
当校验的值出现问题时,有可能会造成搜索引擎回溯的问题,个人理解就是匹配正则进入了死循环,参见:https://segmentfault.com/q/1010000008473664.
其中html5新特性setCustomValidity(‘’)方法需要提交后才会生效。
html5新特性参考http://www.cnblogs.com/chenhaoqiang/p/6288059.html