解析身份证号码(附加Java代码)

简单分析

结构

我国的居民身份证号码是特征组合码,由十七位数字本体码和一位校验码组成。
排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。

六位数字地址码

第一、二位表示省级行政区。
第一位数字是以前的大区制代码。第二位是大区所在省市编码。

  1. 华北三省二市
  2. 东北三省
  3. 华东六省一市
  4. 华南六省
  5. 西南四省一市
  6. 西北五省
  7. 台湾省
  8. 香港澳门

具体省(直辖市,自治区,特别行政区)编码如下

  • 11~15 京津冀晋蒙
  • 21~23 辽吉黑
  • 31~37 沪苏浙皖闽赣鲁
  • 41~46 豫鄂湘粤桂琼
  • 50~54 渝川贵云藏
  • 61~65 陕甘青宁新
  • 71 台湾
  • 81~82 港澳

记不住省份简称的可以跳过去看看
https://blog.csdn.net/qq_55342245/article/details/113815397

第三、四位表示地级行政区。01一般表示本省省会

就像车牌,A表示本省省会,B一般是本省的二线城市
辽A是沈阳 辽B是大连,黑A是哈尔滨 黑B是齐齐哈尔,川A是成都 川B是绵阳,云A是昆明 云南没有B的牌照

第五、六位表示县级行政区。01一般表示本市市辖区

210101辽宁省沈阳市市辖区 210201辽宁省大连市市辖区
230101黑龙江省哈尔滨市市辖区 230201黑龙江省齐齐哈尔市市辖区
510101四川省成都市市辖区 510701四川省绵阳市市辖区

八位数字出生日期码

(身份证号码第七位到第十四位)表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。例如:1981年05月11日就用19810511表示。

三位数字顺序码

(身份证号码第十五位到十七位)表示在同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。其中第十七位奇数分给男性,偶数分给女性。(我国古代,奇数为阳,偶数为阴)

一位数字校验码

根据前面十七位数字码,按按一定规则计算出来。
公式:最后一位 = ( 12 − ∑ i = 2 18 a i w i m o d 11 ) m o d 11 = ( 12- \sum_{i=2}^{18}a_{i}w_{i} mod 11) mod11 =(12i=218aiwimod11)mod11

mod 是取余数的意思。 例(36 mod 5)=1, (46 mod 8)=6
ai 是从右往左数第i位,加权因子wi = 2(i-1) mod 11
身份证是18位,所以a2是倒数第二位,正数第17位

因为最后一位是除以11取余数得到,就有0~10这十一种情况,那么就得用X(X是罗马数字的10)来代替10,因为如果用10做尾号,那么此人的身份证就变成了19位,而19位的号码违反了国家标准。

十八位身份证还可以用这个公式验证: ∑ i = 1 18 a i w i ≡ 1 ( m o d 11 ) \sum_{i=1}^{18}a_{i}w_{i} \equiv 1 ( mod 11) i=118aiwi1(mod11)

≡ \equiv ”是同余符号。
例:
16 ≡ \equiv 11 ( mod 5) 16除以5=3…1 11除以5=2…1 余数都是1
25 ≡ \equiv 3 ( mod 11) 25除以11=2…3 3除以11=0…3 余数都是3

这个公式的另一种写法是: ( ∑ i = 1 18 a i w i ) m o d 11 = 1 ( \sum_{i=1}^{18}a_{i}w_{i}) mod 11 = 1 (i=118aiwi)mod11=1

安利几个千年难遇的身份证号(如有冒犯请联系我删除)
这些身份证是有意义的。但形成这样的身份证号,必须要让公安机关分配给你的顺序码是由0和2组成,而且0和2的还得有一个正确的搭配顺序
有兴趣的还可以自己多找几个
220202200002022002 吉林省吉林市昌邑区2000年2月2日出生的女孩
220202200002200200 吉林省吉林市昌邑区2000年2月20日出生的女孩
220202202002020022 吉林省吉林市昌邑区2020年2月2日出生的女孩
220202202002022220 吉林省吉林市昌邑区2020年2月2日出生的女孩
220202202002202002 吉林省吉林市昌邑区2020年2月20日出生的女孩

代码实现

获取身份证号里的信息

//获取身份证号里的信息
    public static void getInfo(String s){

        String area=s.substring(0,6);
        String year=s.substring(6,10);
        String month=s.substring(10,12);
        String day=s.substring(12,14);
        String num=s.substring(14,17);
        String checkCode=s.substring(17);

        System.out.println("地区码:"+area);
        System.out.println("出生日期:"+year+"年"+month+"月"+day+"日");
        System.out.println("顺序码:"+num);
        System.out.println("校验码:"+checkCode);

        if (Integer.parseInt(s.substring(16,17))%2==0){
            System.out.println("性别:女");
        }else{
            System.out.println("性别:男");
        }
    }

获取身份证中的省份

public static String getArea(String id){
        Map<String,String> map=new HashMap<String,String>(){{
            put("11","北京市");put("12","天津市");put("13","河北省");put("14","山西省");put("15","内蒙古自治区");
            put("21","辽宁省");put("22","吉林省");put("23","黑龙江省");
            put("31","上海市");put("32","江苏省");put("33","浙江省");put("34","安徽省");put("35","福建省");put("36","江西省");put("37","山东省");
            put("41","河南省");put("42","湖北省");put("43","湖南省");put("44","广东省");put("45","广西壮族自治区");put("46","海南省");
            put("50","重庆市");put("51","四川省");put("52","贵州省");put("53","云南省");put("54","西藏自治区");
            put("61","陕西省");put("62","甘肃省");put("63","青海省");put("64","宁夏回族自治区");put("65","新疆维吾尔自治区");
            put("71","台湾省");
            put("81","香港特别行政区");put("82","澳门特别行政区");
        }};
        String area=id.substring(0,2);
        if (map.containsKey(area)){
            return map.get(area);
        }else{
            return "地区码无效";
        }

    }

计算身份证校验位

简单的

//(简单)
    public static void doVerify(String id) {
        char pszSrc[] = id.toCharArray();
        int sum = 0;
        //身份证的前十七位分别乘以相应的加权因子
        int wi[] = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
        //根据余数去匹配对应的数字
        char rem[] ={'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};

        for (int i = 0; i < 17; i++) {
            sum += (int)(pszSrc[i]-'0') * wi[i];
        }
        int j = sum % 11;
        System.out.println("校验位是:"+rem[j]);
    }

专业的
公式:最后一位 = ( 12 − ∑ i = 2 18 a i w i m o d 11 ) m o d 11 = ( 12- \sum_{i=2}^{18}a_{i}w_{i} mod 11) mod11 =(12i=218aiwimod11)mod11

public static void Judge(String str){
        int sum = 0;
        for(int i=0;i<17;i++){
            char c = str.charAt(i);
            int n =c-'0';//数字字符转对应的数字
            int wi=1;
            //加权因子wi = 2^(i-1) mod 11 从右往左数
            //也就是 w1=(2^17)%11 w2=(2^16)%11 w17=(2^1)%11
           	wi=wi<<(17-i)//左移,这里相当于乘以2的(17-i)次方
            wi=wi%11;//加权因子计算完成
            sum+=n*wi;
        }

        int x=(12-sum%11)%11;
        System.out.println("校验位是:"+x);
    }

验证并提取信息

import java.util.Calendar;
import java.util.Scanner;

public class Shen {
    public static void main(String[] args){
        Scanner input=new Scanner(System.in);
        System.out.println("请输入的你身份证号:");
        String s= input.next();
        if (s.length()==18 && isNumString(s)){

            String a=s.substring(0,6);
            String y=s.substring(6,10);;
            String m=s.substring(10,12);;
            String d=s.substring(12,14);;
            String n=s.substring(14,17);;
            String checkCode=s.substring(17);;

            Integer area = new Integer(a);
            Integer year = new Integer(y);
            Integer month = new Integer(m);
            Integer day = new Integer(d);
            Integer num = new Integer(n);

            if (isNumString(s) && Judge(s)){
                if(Year(year)){
                    if (Month(month)){
                        if (Day(year,month,day)){
                            System.out.println("身份证号有效");
                            System.out.println("地区码:"+area);
                            System.out.println("出生日期:"+year+"年"+month+"月"+day+"日");
                            System.out.println("顺序码:"+num);
                            System.out.println("校验码:"+checkCode);
                            if (Integer.parseInt(s.substring(16,17))%2==0){
                                System.out.println("性别:女");
                            }else{
                                System.out.println("性别:男");
                            }
                        }else{
                            System.out.println("身份证号上的日期有误");
                        }
                    }else{
                        System.out.println("身份证号上的月份有误");
                    }
                }else{
                    System.out.println("身份证号上的年份有误");
                }
            }else{
                System.out.println("身份证号无效");
            }

        }else{
            System.out.println("身份证号码必须是由数字组成的十八位");
        }

    }

    //判断身份证号是否合法
    public static boolean Judge(String str){
        int sum = 0;
        int[] arr=new int[18];
        char ch = str.charAt(17);
        if (ch=='X' || ch=='x'){
            arr[17]=10;
        }else{
            arr[17]=ch-'0';
        }
        for(int i=0;i<17;i++){
            char c = str.charAt(i);
            arr[i]=c-'0';//数字字符转对应的数字
        }

        for(int i=0;i<18;i++){
            //ai 表示的是从右往左身份证的第i位数字
            int wi=1;
            //加权因子wi = 2^(i-1) mod 11
            for (int j = 0; j < i; j++) {//计算加权因子
                wi=wi*2;
            }
            wi=wi%11;
            sum+=arr[17-i]*wi;
        }

        if (sum%11==1){
            return true;
        }else{
            return false;
        }
        /*或者是
        //身份证最后一个数字=(12-前十七位的sum然后模11)模11,
        if (arr[17]==(12-(sum-arr[17])%11)%11){
            return true;
        }else{
            return false;
        }*/

    }

    //判断时间是否合法
    public static boolean Year(Integer year){
        Calendar now = Calendar.getInstance();
        if (year>=1900 && year<=now.get(Calendar.YEAR)) {
            return true;
        }else{
            return false;
        }
    }

    public static boolean Month(Integer month){
        if (month>=1 && month<=12) {
            return true;
        }else{
            return false;
        }
    }

    public static boolean Day(Integer year,Integer month,Integer day){
        if (month>=1 && month<=12) {
            switch (month){
                case 1:
                case 3:
                case 5:
                case 7:
                case 8:
                case 10:
                case 12:
                    if (day>=1 && day <=31) {
                        return true;
                    }else{
                        return false;
                    }
                case 4:
                case 6:
                case 9:
                case 11:
                    if (day>=1 && day <=30) {
                        return true;
                    }else{
                        return false;
                    }
                case 2:
                    if (year%4==0&&year%100!=0||year%400==0) {
                        if (day>=1 && day<=29){
                            return true;
                        }else{
                            return false;
                        }
                    }else{
                        if (day>=1 && day<=28){
                            return true;
                        }else{
                            return false;
                        }
                    }
                default:
                    return false;
            }
        }else{
            return false;
        }
    }

    //判断前17位是不是数字
    private static boolean isNumString(String str) {
        if (str.length() == 0 || str == null)
            return false;
        for (int i = 0; i < 17; i++) {
            char ch = str.charAt(i);
            if (!(ch >= '0' && ch <= '9')) {
                return false;
            }
        }
        return true;
    }

}



  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值