首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 實現身份證號碼合法性驗證與信息提取完整工具類

     編輯:Java 相關知識

標準依據與號碼結構

依據 GB 11643-1999《公民身份號碼》 國家標準,身份證號碼為特徵組合碼:

  • 18 位:6 位地址碼 + 8 位出生日期(YYYYMMDD) + 3 位順序碼 + 1 位校驗碼
  • 15 位(舊版):6 位地址碼 + 6 位出生日期(YYMMDD) + 3 位順序碼

校驗碼計算採用 ISO 7064:1983.MOD 11-2 算法:
Σ(前17位數字 × 加權因子) mod 11 → 對應校驗碼映射表

核心工具類:IdcardValidator

1. 靜態常量定義

// 省級行政區劃代碼映射(含港澳台、國外)
private String[][] codeAndCity = {{"11","北京"},{"12","天津"},...{"91","國外"}};
private String[] cityCode = {"11","12",...,"91"};

// 加權因子(前17位)
private int[] power = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};

// 校驗碼映射:索引 = 模11餘數 → 值 = 校驗碼
private String[] verifyCode = {"1","0","X","9","8","7","6","5","4","3","2"};

2. 統一驗證入口

public boolean isValidatedAllIdcard(String idcard) {
    if (idcard.length() == 15) {
        idcard = convertIdcarBy15bit(idcard); // 15位轉18位再驗證
    }
    return isValidate18Idcard(idcard);
}

3. 18 位核心驗證邏輯

public boolean isValidate18Idcard(String idcard) {
    if (idcard.length() != 18) return false;
    String id17 = idcard.substring(0, 17);
    String id18 = idcard.substring(17, 18);
    
    // 1. 前17位必須全為數字
    if (!isDigital(id17)) return false;
    
    // 2. 加權求和
    int sum = 0;
    for (int i = 0; i < 17; i++) {
        sum += (id17.charAt(i) - '0') * power[i];
    }
    
    // 3. 校驗碼比對
    String expected = verifyCode[sum % 11];
    return expected.equalsIgnoreCase(id18);
}

4. 15 位轉 18 位算法

public String convertIdcarBy15bit(String id15) {
    // 1. 補全出生年份:19YY 或 20YY(邏輯判斷)
    String birth = id15.substring(6, 12); // YYMMDD
    Date date = new SimpleDateFormat("yyMMdd").parse(birth);
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    String year = String.valueOf(cal.get(Calendar.YEAR)); // 獲取4位年份
    
    // 2. 組裝前17位:地址碼(6) + 年份(4) + 月日順序碼(7)
    String id17 = id15.substring(0, 6) + year + id15.substring(8);
    
    // 3. 計算校驗碼
    int sum = 0;
    for (int i = 0; i < 17; i++) sum += (id17.charAt(i)-'0') * power[i];
    return id17 + verifyCode[sum % 11];
}

信息提取類:IdcardInfoExtractor

public class IdcardInfoExtractor {
    private String province, gender;
    private int year, month, day;
    private Date birthday;
    private Map cityMap = new HashMap<>(); // 代碼→名稱
    
    public IdcardInfoExtractor(String idcard) {
        IdcardValidator v = new IdcardValidator();
        if (!v.isValidatedAllIdcard(idcard)) return;
        
        if (idcard.length() == 15) idcard = v.convertIdcarBy15bit(idcard);
        
        // 省份
        province = cityMap.get(idcard.substring(0, 2));
        // 性別:第17位奇男偶女
        gender = (Integer.parseInt(idcard.substring(16,17)) % 2 == 1) ? "男" : "女";
        // 出生日期
        birthday = new SimpleDateFormat("yyyyMMdd").parse(idcard.substring(6, 14));
        Calendar c = Calendar.getInstance();
        c.setTime(birthday);
        year = c.get(Calendar.YEAR);
        month = c.get(Calendar.MONTH) + 1;
        day = c.get(Calendar.DAY_OF_MONTH);
    }
    // Getter 方法...
}

使用示例

public static void main(String[] args) {
    String id18 = "11010119900307783X"; // 示例
    IdcardValidator validator = new IdcardValidator();
    System.out.println("驗證結果: " + validator.isValidatedAllIdcard(id18)); // true
    
    IdcardInfoExtractor extractor = new IdcardInfoExtractor(id18);
    System.out.println("省份: " + extractor.getProvince()); // 北京
    System.out.println("性別: " + extractor.getGender());   // 男
    System.out.println("生日: " + extractor.getBirthday()); // 1990-03-07
}

注意事項與擴展

  • 地址碼更新:行政區劃代碼會隨時間變更(如區劃調整),需定期同步最新 GB/T 2260 數據。
  • 校驗碼 'X' 處理:大小寫不敏感比對,轉字符串時統一大寫。
  • 性能優化:靜態常量單例化、預編譯正則、避免重複創建 Calendar/SimpleDateFormat(非線程安全)。
  • 港澳台/外籍:地址碼 81/82/91 無詳細省市區映射,業務層需單獨處理。

總結

本工具類完整實現了身份證號碼的格式校驗、校驗碼算法、15/18 位互轉、地址解析、出生日期與性別提取,代碼結構清晰、邏輯嚴謹,可直接集成至實名認證、用戶註冊、數據清洗等業務場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved