正则学习——身份证号

正则总有一天要学会自己写,虽然以前总是查找粘贴,但是也要不仅看得懂也要能写。

参考文章:https://blog.csdn.net/qiphon3650/article/details/95495629#fnref1

结构和形式

1.号码的结构
  - 公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
  2.地址码
  表示编码对象常住户口所在县(县级市、旗、区)的行政区划代码,按GB/T2260的规定执行。
  3.出生日期码
  表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日代码之间不用分隔符。
  4.顺序码
  表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。
  5.校验码
  根据前面十七位数字码,按照ISO 7064:1983.MOD 11-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。
例如:某男性的身份证号码为【53010219200508011X】, 我们看看这个身份证是不是合法的身份证。
首先我们得出前17位的乘积和【(57)+(39)+(010)+(15)+(08)+(24)+(12)+(91)+(26)+(03)+(07)+(59)+(010)+(85)+(08)+(14)+(1*2)】是189,然后用189除以11得出的结果是189/11=17----2,也就是说其余数是2。最后通过对应规则就可以知道余数2对应的检验码是X。所以,可以判定这是一个正确的身份证号码。

简版的匹配规则

1.1 分部规则
我们首先提出方案1,并分步做如下规则定义:

1.1.1 地址码规则:
地址码长6位
以数字1-9开头
后5位为0-9的数字
根据以上规则,写出地址码的正则表达式: /1\d{5}/

1.1.2 年份码规则:
年份码长4位
以数字18,19或20,30开头
剩余两位为0-9的数字
根据以上规则,写出年份码的正则表达式: /(18|19|20|(3\d))\d{2}/。如果想扩展可以自己添加

1.1.3 月份码规则:
月份码长2位
第一位数字为0,第二位数字为1-9
或者第一位数字为1,第二位数字为0-2
根据以上规则,写出月份码的正则表达式: /((0[1-9])|(1[0-2]))/。

1.1.4 日期码规则:
日期码长2位
第一位数字为0-2,第二位数字为1-9
或者是10,20,30,31
根据以上规则,写出日期码的正则表达式 :/(([0-2][1-9])|10|20|30|31)/。

1.1.5 顺序码规则:
顺序码长3位
顺序码是数字
根据以上规则,写出顺序码的正则表达式 :/\d{3}/。

1.1.6 校验码规则:
校验码长1位
可以是数字,字母x或字母X
根据以上规则,写出校验码的正则表达式 :/[0-9Xx]/。

最后的结果

/^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
/// 15 位
let reg15 = /^[1-9]\d{5}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}$/;

另有详细版,请参考原文

参考地址: https://baike.baidu.com/item/%E5%B1%85%E6%B0%91%E8%BA%AB%E4%BB%BD%E8%AF%81%E5%8F%B7%E7%A0%81/3400358?fr=aladdin
https://juejin.im/post/5aa8d89af265da23866f9669

参考文章:https://www.cnblogs.com/xtqg0304/p/9529721.html

身份证的规则

       根据【中华人民共和国国家标准 GB 11643-1999】中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。 地址码表示编码对象常住户口所在县(市、旗、区)的行政区划代码。 出生日期码表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。 顺序码表示同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。顺序码的奇数分给男性,偶数分给女性。 校验码是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。 出生日期计算方法。

15位的身份证编码首先把出生年扩展为4位,简单的就是增加一个19或18,这样就包含了所有1800-1999年出生的人; 2000年后出生的肯定都是18位的了没有这个烦恼,至于1800年前出生的,那啥那时应该还没身份证号

JS正则表达式

出生日期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[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i

15位校验规则 6位地址编码+6位出生日期+3位顺序号 18位校验规则 6位地址编码+8位出生日期+3位顺序号+1位校验位 校验位规则公式:∑(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 */

//身份证号合法性验证

//支持15位和18位身份证号

//支持地址编码、出生日期、校验位验证

js

function IdentityCodeValid(code) 
{
    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; 
    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; 
    } 
    elseif(!city[code.substr(0,2)])
    { 
        tip = "地址编码错误"; 
        pass = false;
    } 
    else
    {
        //18位身份证需要验证最后一位校验位if(code.length == 18){ code = code.split(''); 
        //∑(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; var ai = 0; var wi = 0; 
        for (var i = 0; i < 17; i++) 
        { 
            ai = code[i]; wi = factor[i]; 
            sum += ai * wi; } var last = parity[sum % 11]; 
            if(parity[sum % 11] != code[17])
            { 
                tip = "校验位错误"; pass =false; 
            } 
        } 
    } 
    if(!pass) 
        alert(tip); 
    return pass; 
} 
var c = '130981199312253466'; var res= IdentityCodeValid(c);

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值