身份證號碼 15位和18位 驗證

首先先了解 身份證號碼的編碼規則,從百度經驗上找到了別人的分享php

         :http://jingyan.baidu.com/article/7f41ececff944a593d095c8c.htmlhtml

感謝。正則表達式

    

15位長度的驗證正則是從網上找的,但發現並非萬能的(月份能夠出現00,日期能夠出現00等),算法

因此作了以下改良,但仍舊存在一些問題,如880231這樣的生日也能夠驗證功過編碼

因此能夠考慮將身份證號碼的年月日單獨判斷,在此略去。3d

18位長度的就按校驗規則來校驗便可。code

  

function chkIdNo($idNo)
{
    //身份證正則表達式(15位) 
    //isIDCard1=/^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$/; 
    ////身份證正則表達式(18位) 
    //isIDCard2=/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$/; 
    $len = strlen($idNo); 

    //十五位身份證1999 10 01再也不辦理
    if($len == 15) {
        //13 04 03 991001 002
        //$pattern = '/^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{2}[Xx0-9]$/';
        //修復 月份 天 不能同時爲00
        $pattern = '/^[1-9]\d{7}((0[1-9])|(1[0-2]))((0[1-9])|([1-2]\d)|3[0-1])\d{2}[Xx0-9]$/';
        $res = preg_match($pattern, $idNo);
        if($res) return true;
        return false;
    } 
    if($len == 18){
        //前17位對應的權重數字算法 (2<<($len - 2 - n)%11 

        $bits = str_split($idNo); 
        //每位對應的權重數字
        $weights = array();
        //求和
        $sum = 0;
        for($i = 0; $i < 17; $i++) {
            //計算權重
            $weights[$i] = (2 << ($len - 2 - $i)) % 11; 
            $sum += $bits[$i] * $weights[$i];
        }
        
        $mod = $sum % 11;
        //校驗碼array(1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2);
        $chkCodes = array(1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2);
        $code = isset($chkCodes[$mod]) ? $chkCodes[$mod].'' : '';
        if($code !== $bits[$len - 1]) {
            return false;
        }

        return true;
    } 
    return false;
}
相關文章
相關標籤/搜索