功能特性
- 支援 15 位(舊版)與 18 位(新版)身分證字號
- 驗證地區碼(省/直轄市/港澳台/國外)
- 驗證出生日期合法性(含閏年邏輯)
- 18 位校驗碼計算(ISO 7064:1983.MOD 11-2)
- 回傳中文錯誤訊息
完整程式碼
<script>
function validateIdCard(idcard) {
const errors = [
"驗證通過!",
"身分證號碼位數錯誤!",
"出生日期超出範圍或含非法字元!",
"身分證號碼校驗錯誤!",
"身分證地區非法!"
];
const area = {
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:"國外"
};
// 地區碼檢查
if (!area[parseInt(idcard.substr(0, 2))]) return errors[4];
switch (idcard.length) {
case 15: // 15 位:出生年份 19xx
const year15 = 1900 + parseInt(idcard.substr(6, 2));
const isLeap15 = (year15 % 4 === 0 && year15 % 100 !== 0) || (year15 % 400 === 0);
const regex15 = isLeap15
? /^[1-9]\d{5}\d{2}((0[13578]|1[02])(0[1-9]|[12]\d|3[01])|(0[469]|11)(0[1-9]|[12]\d|30)|02(0[1-9]|[12]\d))\d{3}$/
: /^[1-9]\d{5}\d{2}((0[13578]|1[02])(0[1-9]|[12]\d|3[01])|(0[469]|11)(0[1-9]|[12]\d|30)|02(0[1-9]|1\d|2[0-8]))\d{3}$/;
return regex15.test(idcard) ? errors[0] : errors[2];
case 18: // 18 位:出生年份 19xx/20xx,含校驗碼
const year18 = parseInt(idcard.substr(6, 4));
const isLeap18 = (year18 % 4 === 0 && year18 % 100 !== 0) || (year18 % 400 === 0);
const regex18 = isLeap18
? /^[1-9]\d{5}19\d{2}((0[13578]|1[02])(0[1-9]|[12]\d|3[01])|(0[469]|11)(0[1-9]|[12]\d|30)|02(0[1-9]|[12]\d))\d{3}[\dXx]$/
: /^[1-9]\d{5}19\d{2}((0[13578]|1[02])(0[1-9]|[12]\d|3[01])|(0[469]|11)(0[1-9]|[12]\d|30)|02(0[1-9]|1\d|2[0-8]))\d{3}[\dXx]$/;
if (!regex18.test(idcard)) return errors[2];
// 校驗碼計算
const weights = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2];
const checkCodes = "10X98765432";
let sum = 0;
for (let i = 0; i < 17; i++) {
sum += parseInt(idcard.charAt(i)) * weights[i];
}
const checkCode = checkCodes.charAt(sum % 11);
return checkCode === idcard.charAt(17).toUpperCase() ? errors[0] : errors[3];
default:
return errors[1];
}
}
// 測試
const input = prompt("請輸入身分證號碼(15/18 位)", "");
if (input) document.write(validateIdCard(input));
</script>
校驗碼算法說明
- 前 17 位分別乘以權重
[7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2] 求和。
- 和對 11 取餘
Y = sum % 11。
- 對應字串
"10X98765432" 第 Y 字元為校驗碼。
- 比對第 18 位(不分大小寫)。
使用提醒
- 僅做格式與邏輯驗證,無法確認身分真實性(需接入公安資料庫)。
- 正則表達式針對 19xx 年份,若需支援 20xx 請調整正則。
- 生產環境建議移除
prompt/document.write,改為模組化函數匯出。