GB11643-1999 標準結構
18 位 = 6 位地址碼 + 8 位出生日期 (YYYYMMDD) + 3 位順序碼 + 1 位校驗碼
├─ 行政區劃 (GB/T2260)
├─ 出生日期 (GB/T7408)
├─ 順序碼 (奇男偶女)
└─ 校驗碼 (ISO 7064 MOD 11-2)
校驗碼計算標準化流程
- 權重碼
Wi = [7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2]
- 加權求和
S = Σ(ai × Wi)
- 模 11
Y = S % 11
- 對照表
Y: 0 1 2 3 4 5 6 7 8 9 10 → 校驗碼: 1 0 X 9 8 7 6 5 4 3 2
企業級驗證元件完整實現
public static class IdCardValidator {
private static readonly int[] Weight = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
private static readonly char[] CheckMap = {'1','0','X','9','8','7','6','5','4','3','2'};
private static readonly string[] AreaCode = {
null,null,null,null,null,null,null,null,null,null,null,
"北京","天津","河北","山西","內蒙古",null,null,null,null,null,
"遼寧","吉林","黑龍江",null,null,null,null,null,null,null,
"上海","江蘇","浙江","安徽","福建","江西","山東",null,null,null,
"河南","湖北","湖南","廣東","廣西","海南",null,null,null,
"重慶","四川","貴州","雲南","西藏",null,null,null,null,null,null,
"陝西","甘肅","青海","寧夏","新疆",null,null,null,null,null,
"台灣",null,null,null,null,null,null,null,null,null,
"香港","澳門",null,null,null,null,null,null,null,"國外"
};
/// 驗證並解析身份證,回傳 (是否合法, 省份, 出生日期, 性別)
public static (bool Valid, string Province, DateTime Birthday, string Gender) Validate(string id) {
if (string.IsNullOrWhiteSpace(id) || id.Length != 18) return (false, "", default, "");
id = id.ToUpper();
// 1. 格式正則:前 17 位數字,最後 1 位數字或 X
if (!System.Text.RegularExpressions.Regex.IsMatch(id, @"^\d{17}[\dX]$"))
return (false, "", default, "");
// 2. 地址碼檢核
int area = int.Parse(id.Substring(0, 2));
if (area >= AreaCode.Length || AreaCode[area] == null)
return (false, "", default, "");
// 3. 出生日期檢核
if (!DateTime.TryParseExact(id.Substring(6, 8), "yyyyMMdd", null, System.Globalization.DateTimeStyles.None, out DateTime birth))
return (false, "", default, "");
if (birth > DateTime.Today || birth < new DateTime(1900,1,1))
return (false, "", default, "");
// 4. 校驗碼計算
int sum = 0;
for (int i = 0; i < 17; i++)
sum += (id[i] - '0') * Weight[i];
char expected = CheckMap[sum % 11];
if (id[17] != expected)
return (false, "", default, "");
// 5. 性別判斷 (第 17 位順序碼奇偶)
string gender = (id[16] - '0') % 2 == 1 ? "男" : "女";
return (true, AreaCode[area], birth, gender);
}
}
使用範例與測試
var tests = new[] {
"11010519491231002X", // 北京
"440524198001010014", // 廣東
"340524198002300019", // 非法日期 (2月30日)
"34052419800101001X" // 正確
};
foreach (var id in tests) {
var (valid, prov, birth, gender) = IdCardValidator.Validate(id);
Console.WriteLine($"{id} => {(valid ? "合法" : "非法")} | {prov} | {birth:yyyy-MM-dd} | {gender}");
}
擴充建議
- 快取行政區劃表至記憶體/資料庫,支援歷史區劃代碼查詢。
- 整合
System.ComponentModel.DataAnnotations 屬性,方便 MVC/WebAPI 模型驗證。
- 新版標準 (GB11643-2017) 已擴展支援港澳台居民身份證、外國人永久居留證,需補充對應規則。