18位身份证号码规则及js验证

南楼画角 提交于 2020-03-02 17:13:48

一、中国居民身份证号码规则

18位身份证号码编码规则:根据〖中华人民共和国国家标准 GB 11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码一位数字校验码组成。
 

排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。可以用字母表示如为 ABCDEFYYYYMMDDXXXR。其含义如下:

1. 地址码(ABCDEF):表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按 GB/T2260 的规定执行。

2. 出生日期码(YYYYMMDD):表示编码对象出生的年、月、日,按 GB/T7408 的规定执行,年、月、日分别用 4 位、2 位(不足两位加 0)、2(同上)位数字表示,之间不用分隔符。

3. 顺序码(XXX):表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。

4.校验码(R):一位数字,通过前 17 位数字按照 ISO 7064:1983.MOD 11-2 校验码计算得出。

15 位的身份证编码首先把出生年扩展为 4 位,简单的就是增加一个 19,但是这对于 1900 年出生的人不使用(这样的寿星不多了)

地区代码

身份证前六位是地区代码,我们用 ABCDEF 表示。解释规则如下:

A:国内区域

1 华北三省二市

2 东北三省

3 华东六省一市

4 华南六省

5 西南四省一市

6 西北五省

7 台湾

8 港澳

9 国外

B(或者说是 AB,就是前 2 位):省(直辖市,自治区,特别行政区)代码

按照 A 划定的分区定义省代码,有直辖市的,直辖市列前,其余按离直辖市的距离排序,没有直辖市的,按离北京的远近排序

具体省(直辖市,自治区,特别行政区)代码如下:

11-15 京、津、冀、晋、蒙

21-23 辽、吉、黑

31-37 沪、苏、浙、皖、闽、赣、鲁

41-46 豫、鄂、湘、粤、桂、琼

50-54 渝、川、贵、云、藏

61-65 陕、甘、青、宁、新

81-82 港、澳

第3-4位为地市级行政区划代码,第5-6位为县级行政区划代码常有调整

生日期码

(YYYYMMDD)表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。例如:1981 年 5 月 11 日就用 19810511 表示。

 

顺序码

(身份证第十五位到十七位)是县、区级政府所辖派出所的给的顺序号,其中单数为男性,双数为女性,如遇同年同月同日有两人以上时顺延二、三、四、五个分配码。如:007 的就是个男生,而且和他同年月日生的男生至少有两个,他们的后四位是 001* 和 003*。
分配顺序码中“999、998、997、996”四个顺序号分别为男女性百岁以上老人专用的特定编号。

 

校验码

18 位身份证最末位是校验码,是按一定的规则产生的,用于校验身份证真伪,按理这规则属于保密的,X 代表的是其中一个校验码,是罗马数字10。校验码从 0 到 X 共 11 个。

校验码是通过一系列数学计算得出来的,具体校验的计算方式如下:

公式为:∑(Ai×Wi)(mod 11)

i——表示号码字符从右至左包括校验码在内的位置序号;

Ai——表示第 i 位置上的号码字符值;

Wi——示第 i 位置上的加权因子(其值已定),
其数值依据公式 Wi=2^(i-1)(mod 11) 计算得出。其各位对应的值
依次为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2

例如:某男性公民身份号码为 34052419800101001V(V为校验码),对前 17 位数字本体码首先按照上面公式加权求和计算:

i:

18

17

16

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

Ai:

3

4

0

5

2

4

1

9

8

0

0

1

0

1

0

0

1

V

Wi:

7

9

10

5

8

4

2

1

6

3

7

9

10

5

8

4

2

1

∑(Ai×Wi) =( 21 + 36 + 0 + 25 + 16 + 16 + 2 + 9 + 48 + 0 + 0 + 9 + 0 + 5 + 0 + 0 + 2 ) = 189

∑(Ai×Wi)(mod 11) = 189 mod 11 = 2

然后根据计算的结果,从下面的表中查出相应的校验码。其中 X 表示计算结果为 10。

∑(Ai×Wi)(mod 11):

0

1

2

3

4

5

6

7

8

9

10

校验码字符值 V:

1

0

X

9

8

7

6

5

4

3

2

根据上表,查出计算结果为 2 的校验码为 X,所以该人员的公民身份号码
应该为 34052419800101001X。

如果校验码不符合这个规则,则肯定是假号码。

 

有了以上规则的了解我们就可以开始校验身份证号码了。

二、JS代码验证

/**
 * 身份证号码校验
 * @param string num
 * @returns 完全通过:true, string为错误提示 ,判断请用 === 
 * @author jingxing05
 */
function isIdCardNo(num) {
    //权重值
    var factorArr = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1);

    //校验码
    var parityBit = new Array("1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2");

    //地区码省级  @todo市级地级代码也可以枚举
    var provinces = {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 varArray = new Array();    
    var intweightSum = 0;
    var intCheckDigit;

    var intStrLen = num.length;
    var idNumber = num.toString().toUpperCase();

    // 基本位数判断
    if ((intStrLen != 15) && (intStrLen != 18)) {
        return '身份证号为18位!';
    }
    
    //省级信息 @todo 可以枚举市级 和 县级 区域的
    if (provinces[parseInt(idNumber.substr(0, 2))] == null) {
        return '身份证号前六位地区码有误!';
    }

    // 判断每一位字符,顺便计算加权值
    for (i = 0; i < intStrLen; i++) {
        varArray[i] = idNumber.charAt(i);
        if ((varArray[i] < '0' || varArray[i] > '9') && (i != 17)) {
            return '身份证号有错误字符!';
        } else if (i < 17) {
            varArray[i] = varArray[i] * factorArr[i];
            intweightSum = intweightSum + varArray[i];
        }
    }
    
    if (intStrLen == 18) {         
        //生日期校验
        var date8 = idNumber.substring(6, 14);
        if (isDate8(date8) == false) {
            return '身份证出生日期错误!';
        }
        
        // 校验码验证  余数在校验数组中的值
        intCheckDigit = parityBit[intweightSum % 11];
        
        // 最后一位和计算出的校验码是否一致
        if (varArray[17] != intCheckDigit) {
            return '身份证号有误,校验失败!';
        }
    } else {
        var date6 = idNumber.substring(6, 12);
        if (isDate6(date6) == false) {
            return '身份证出生日期错误!';
        }
    }
    return true;
}

function isDate8(sDate) {
    if (!/^[0-9]{8}$/.test(sDate)) {
        return false;
    }
    var year, month, day;
    year = sDate.substring(0, 4);
    month = sDate.substring(4, 6);
    day = sDate.substring(6, 8);
    var iaMonthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
    if (year < 1700 || year > 2500)
        return false
    if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
        iaMonthDays[1] = 29;
    if (month < 1 || month > 12)
        return false
    if (day < 1 || day > iaMonthDays[month - 1])
        return false
    return true
}

function isDate6(sDate) {
    if (!/^[0-9]{6}$/.test(sDate)) {
        return false;
    }
    var year, month, day;
    year = sDate.substring(0, 4);
    month = sDate.substring(4, 6);
    if (year < 1700 || year > 2500)
        return false
    if (month < 1 || month > 12)
        return false
    return true
}

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!