无需连网的身份证号码校验

身份证号码可以说是大家生活中最常用的证件了,但是如何验证却成了难题,毕竟大家不是都有权限接入公安系统的,所以我们只能再本地用算法校验。

常用的规则是位数校验,一般是15位或者18位,最后一位还可能是x,我觉得只是这样就太简单了点,所以我们还需要校验下出生日期是否正确,对于18位的身份证,我们还应该按照国家标准进行身份证最后一位的检验吗的计算和对比,这样下来才感觉更安全一点。因为15位升级18位这么长时间了,绝大部分已经更新为18位的身份证了,所以我们优先检查18位,其次再检查15 位。

本次我准备了三种格式的代码,分别为php、python、js,好了,废话不多说了,上代码:

php版本:

<?php
function isIdcard($idcard_str = '')
{
    //    先预处理字符串,转化为大写
    $idcard_str = strtoupper($idcard_str);
    $pattern = "/(^\d{15}$)|(^\d{17}([0-9]|X)$)/";
    $arr_split = [];
    if (!preg_match($pattern, $idcard_str)) {
        // 如果位数不对,或者含有其他字符,直接返回false
        return false;
    }
    if (strlen($idcard_str) == 18) {
        //  如果是18位的,开始处理
        $pattern = "/^(\d{6})+(\d{4})+(\d{2})+(\d{2})+(\d{3})([0-9]|X)$/";
        @preg_match($pattern, $idcard_str, $arr_split);
        $idcard_birth = $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4];
        //用转化日期的方式来检查生日日期是否正确
        if (!strtotime($idcard_birth)) {
            return false;
        } else {
            //先按照ISO 7064:1983.MOD 11-2的规定生成校验码,然后校验18位身份证的校验码是不是正确。
            $arr_int = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
            $arr_ch = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
            $sign = 0;
            for ($i = 0; $i < 17; $i++) {
                $b = (int)$idcard_str[$i];
                $w = $arr_int[$i];
                $sign += $b * $w;
            }
            $n = $sign % 11;
            $val_num = $arr_ch[$n];
            if ($val_num != substr($idcard_str, 17, 1)) {
                return false;
            } else {
                return true;
            }
        }


    } else {
        $pattern = "/^(\d{6})+(\d{2})+(\d{2})+(\d{2})+(\d{3})$/";
        @preg_match($pattern, $idcard_str, $arr_split);
        //检查生日日期是否正确
        $idcard_birth = "19" . $arr_split[2] . '/' . $arr_split[3] . '/' . $arr_split[4];
        if (!strtotime($idcard_birth)) {
            return false;
        } else {
            return true;
        }


    }
}

python版本:

import re


def isIdcard(idcard_str):
    idcard_str = idcard_str.upper()
    pattern = r"(^\d{15}$)|(^\d{17}([0-9]|X)$)"

    if not re.match(pattern, idcard_str):
        return False

    if len(idcard_str) == 18:
        pattern = r"^(\d{6})+(\d{4})+(\d{2})+(\d{2})+(\d{3})([0-9]|X)$"
        arr_split = re.findall(pattern, idcard_str)
        idcard_birth = arr_split[0][1] + '/' + arr_split[0][2] + '/' + arr_split[0][3]

        if not idcard_birth:
            return False
        else:
            arr_int = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
            arr_ch = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
            sign = 0

            for i in range(17):
                b = int(idcard_str[i])
                w = arr_int[i]
                sign += b * w

            n = sign % 11
            val_num = arr_ch[n]

            if val_num != idcard_str[17]:
                return False
            else:
                return True
    else:
        pattern = r"^(\d{6})+(\d{2})+(\d{2})+(\d{2})+(\d{3})$"
        arr_split = re.findall(pattern, idcard_str)
        idcard_birth = "19" + arr_split[0][1] + '/' + arr_split[0][2] + '/' + arr_split[0][3]

        if not idcard_birth:
            return False
        else:
            return True

js版本:

function isIdcard(idcard_str) {
    idcard_str = idcard_str.toUpperCase();
    var pattern = /(^\d{15}$)|(^\d{17}([0-9]|X)$)/;

    if (!pattern.test(idcard_str)) {
        return false;
    }

    if (idcard_str.length === 18) {
        var pattern = /^(\d{6})+(\d{4})+(\d{2})+(\d{2})+(\d{3})([0-9]|X)$/;
        var arr_split = idcard_str.match(pattern);
        var idcard_birth = arr_split[2] + '/' + arr_split[3] + '/' + arr_split[4];

        if (!Date.parse(idcard_birth)) {
            return false;
        } else {
            var arr_int = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
            var arr_ch = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
            var sign = 0;

            for (var i = 0; i < 17; i++) {
                var b = parseInt(idcard_str[i]);
                var w = arr_int[i];
                sign += b * w;
            }

            var n = sign % 11;
            var val_num = arr_ch[n];

            if (val_num !== idcard_str.charAt(17)) {
                return false;
            } else {
                return true;
            }
        }
    } else {
        var pattern = /^(\d{6})+(\d{2})+(\d{2})+(\d{2})+(\d{3})$/;
        var arr_split = idcard_str.match(pattern);
        var idcard_birth = "19" + arr_split[2] + '/' + arr_split[3] + '/' + arr_split[4];

        if (!Date.parse(idcard_birth)) {
            return false;
        } else {
            return true;
        }
    }
}

喜欢的朋友可以自行取走,好了,诸位爱卿可以退下了

版权声明:
作者:崔圣杰
链接:https://www.cuishengjie.com/1001.html
来源:论剑阁-崔圣杰博客
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
无需连网的身份证号码校验
身份证号码可以说是大家生活中最常用的证件了,但是如何验证却成了难题,毕竟大家不是都有权限接入公安系统的,所以我们只能再本地用算法校验。 常用的规则是位数校验,一般是15位或者18位,最后一位还可能是x,我觉得只是这样就太简单了点,所以我们还需要校验下出生日期是否正确,对于18位的身份证,我们还应该按照国家标准进行身份证最后一位的检验吗的计算和对比,这样下来才感觉更安全一点。因为15位升级18位这么长时间了,绝大部分已经更新为18位的身份证了,所以我们优先检查18位,其次再检查15 位。 本次我准备了三种格式的代码,分别为php、python、js,好了,废话不多说了,上代码:
<<上一篇
下一篇>>
文章目录
关闭
目 录