揭開身份證驗證的神祕面紗
正則驗證身份證號碼
HTML5學堂:曾經一直覺得用正則驗證身份證號碼是很簡單的~但是,當真正挖掘身份證號碼的規則之後,才發現,想要寫好一個正則驗證也沒有那麼容易。最近一週利利出差,所以,只能週六跟大家一起分享一下自己的研究結果啦~
身份證的規則
書寫一個正則之前,需要先了解一下身份證的基本規則
- /*
- * 身份證18位編碼規則:dddddd yyyymmdd xxx y
- * dddddd:6位地區編碼
- * yyyymmdd: 出生年(四位年)月日,如:19910215
- * xxx:順序編碼,系統產生,無法確定,奇數為男,偶數為女
- * y: 校驗碼,該位數值可通過前17位計算獲得
- * HTML5學堂出品 http://www.h5course.com 請尊重原創
- * 前17位號碼加權因子為 Wi = [ 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 ]
- * 驗證位 Y = [ 1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2 ]
- * 如果驗證碼恰好是10,為了保證身份證是十八位,那麼第十八位將用X來代替
- */
校驗位計算方法:身份證前17位,每一位數字和相應位數的加權因子進行乘法運算,之後求和(17項之和),再用這個和對11取餘,所得的餘數作為“驗證位陣列Y”的下標,也就是Y[餘數],找到“驗證位陣列Y”中的相應數字,如果身份證最後一位和這個數字吻合,則身份證號碼合法(如果最後一位是X/x,就對應於“驗證位陣列Y”中的10這個數字)
簡單的號碼計算小例子
假如是這個身份證號碼(這個身份證號碼是我瞎編的):110203198811120342。
於是,複雜的計算開始了。取出身份證前17位,與[7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]中對應的位分別進行乘法運算,於是乎:
sum = 1 * 7 + 1 * 9 + 0 * 10 + 2 * 5 + ... + 3 * 4 + 4 * 2。
我們能夠計算出來,總和為177。之後用177對11取餘,餘數為1。那麼在[1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2]陣列中,下標為1的元素就是第二個元素,也就是數值為0。此時將0與身份證號的最後一位(2)做比較,很明顯,錯誤,那麼也證明了這個號碼是我瞎編的了……
驗證身份證號碼的正則如何寫?
身份證規則
我們將一個身份證號碼拆開:身份證18位編碼規則:dddddd yyyymmdd xxx y
1) dddddd:6位地區編碼,地區編碼沒有以0開頭的,舉一個例子,北京用的就是110開頭,河北用的就是130開頭,福建省用的是350開頭,此類。
2) yyyymmdd: 出生年(四位年)月日,前四位是年份,沒啥可說的,月份只能是01~12,日期只能是01~31
3) xxx:三位數字
4) y: 校驗碼,0~9以及X(有時有人會寫成x)
相對應的正則出爐嘍
1) 地區編碼:[1-9]d{5}
2) 出生年份:[1-9]d{3}
3) 出生月份:((0[1-9])|(1[0-2]))
4) 出生日期:((0[1-9])|([1-2]d)|(3[0-1]))
5) 最後四位:((d{4})|(d{3}[Xx]))
完整匹配身份證號碼的正則
於是乎,完整匹配身份證號碼的正則華麗麗的誕生了~~~
- var reg = /^[1-9]d{5}[1-9]d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2]d)|(3[0-1]))((d{4})|(d{3}[Xx]))$/;
完了嗎?別急,往下接著看~~~
使用JS增強號碼的可控性
利利此處採用的是返回物件的設定方式,主要是便於獲取完整的資訊,需要注意的就是要在返回時提供比較合理的API了,不然對方是看不懂滴~~~
我們希望使用者通過呼叫驗證身份證號碼的方法,不僅僅能夠得到是否正確,還能夠得到更加詳細的資訊。所以,一起先來看程式碼嘍~
/*
* 功能:驗證身份證是否可用,如果可用,則提取生日、性別等資訊
* 引數:傳入一個字串或者一個數字均可
* 返回:包含基本資訊的物件
* 作者:HTML5學堂 http://www.h5course.com
*/
function regIDAllInf(str){
str = str.toString();
var reg = /^[1-9]d{5}[1-9]d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2]d)|(3[0-1]))((d{4})|(d{3}[Xx]))$/;
// 用於儲存結果
var result = {};
if (reg.test(str)) {
var sum = 0;
var arrID = str.split("");
var arrWi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
var arrY = [1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2];
for (var i = 0; i < arrWi.length; i++) {
sum += arrID[i] * arrWi[i];
};
sum %= 11;
var lastID = arrID[arrID.length - 1];
if (lastID == "X" || lastID == "x") {
lastID = 10;
};
if (arrY[sum] == lastID) {
result["check"] = true;
result["birthday"] = str.substr(6, 8);
result["cityCode"] = str.substr(0, 6);
result["gender"] = (str.substr(14, 3) % 2 == 0) ? "女" : "男";
} else {
result["check"] = false;
result["error"] = "身份證號碼輸入錯誤";
}
} else {
result["check"] = false;
result["error"] = "身份證號碼格式有誤";
}
return result;
}
console.log(regIDAllInf(str)); // 此處請將str替換為身份證號碼進行測試
如果格式正確,會返回匹配正確,並返回性別、區域、生日的資訊。如果錯誤,也會根據情況返回不同的錯誤提示資訊。
本文章內容小編:HTML5學堂-利利。耗時4h~