1. 程式人生 > >根據身份證號,使用Java編寫程式獲取年齡、性別、出生日期

根據身份證號,使用Java編寫程式獲取年齡、性別、出生日期

轉自:http://blog.csdn.net/dabing69221/article/details/9150819

程式設計師必須要有一個好的思想,程式碼有時候就體現了一個人的靈魂,所以理解需求比技術更重要!

IdcardValidator類

[java] view plaincopyprint?
  1. import java.text.ParseException;  
  2. import java.text.SimpleDateFormat;  
  3. import java.util.Calendar;  
  4. import java.util.Date;  
  5. import java.util.GregorianCalendar;  
  6. import java.util.regex.Pattern;  
  7. publicclass IdcardValidator {  
  8.     /** 
  9.      * 省,直轄市程式碼表: { 11:"北京",12:"天津",13:"河北",14:"山西",15:"內蒙古", 
  10.      * 21:"遼寧",22:"吉林",23:"黑龍江",31:"上海",32:"江蘇", 
  11.      * 33:"浙江",34:"安徽",35:"福建",36:"江西",37:"山東",41:"河南", 
  12.      * 42:"湖北",43:"湖南",44:"廣東",45:"廣西",46:"海南",50:"重慶", 
  13.      * 51:"四川",52:"貴州",53:"雲南",54:"西藏",61:"陝西",62:"甘肅",
     
  14.      * 63:"青海",64:"寧夏",65:"新疆",71:"臺灣",81:"香港",82:"澳門",91:"國外"} 
  15.      */
  16.     protected String codeAndCity[][] = { { "11""北京" }, { "12""天津" },  
  17.             { "13""河北" }, { "14""山西" }, { "15""內蒙古" }, { "21""遼寧" },  
  18.             { "22""吉林" }, { "23""黑龍江" }, { "31""上海" }, { "32""江蘇" },  
  19.             { "33""浙江" }, { "34""安徽" }, { "35""福建" }, { "36""江西" },  
  20.             { "37""山東" }, { "41""河南" }, { "42""湖北" }, { "43""湖南" },  
  21.             { "44""廣東" }, { "45""廣西" }, { "46""海南" }, { "50""重慶" },  
  22.             { "51""四川" }, { "52""貴州" }, { "53""雲南" }, { "54""西藏" },  
  23.             { "61""陝西" }, { "62""甘肅" }, { "63""青海" }, { "64""寧夏" },  
  24.             { "65""新疆" }, { "71""臺灣" }, { "81""香港" }, { "82""澳門" },  
  25.             { "91""國外" } };  
  26.     private String cityCode[] = { "11""12""13""14""15""21""22",  
  27.             "23""31""32""33""34""35""36""37""41""42""43",  
  28.             "44""45""46""50""51""52""53""54""61""62""63",  
  29.             "64""65""71""81""82""91" };  
  30.     // 每位加權因子
  31.     privateint power[] = { 7910584216379105842 };  
  32.     // 第18位校檢碼
  33.     private String verifyCode[] = { "1""0""X""9""8""7""6""5",  
  34.             "4""3""2" };  
  35.     /** 
  36.      * 驗證所有的身份證的合法性 
  37.      *  
  38.      * @param idcard 
  39.      * @return 
  40.      */
  41.     publicboolean isValidatedAllIdcard(String idcard) {  
  42.         if (idcard.length() == 15) {  
  43.             idcard = this.convertIdcarBy15bit(idcard);  
  44.         }  
  45.         returnthis.isValidate18Idcard(idcard);  
  46.     }  
  47.     /** 
  48.      * <p> 
  49.      * 判斷18位身份證的合法性 
  50.      * </p> 
  51.      * 根據〖中華人民共和國國家標準GB11643-1999〗中有關公民身份號碼的規定,公民身份號碼是特徵組合碼,由十七位數字本體碼和一位數字校驗碼組成。 
  52.      * 排列順序從左至右依次為:六位數字地址碼,八位數字出生日期碼,三位數字順序碼和一位數字校驗碼。 
  53.      * <p> 
  54.      * 順序碼: 表示在同一地址碼所標識的區域範圍內,對同年、同月、同 日出生的人編定的順序號,順序碼的奇數分配給男性,偶數分配 給女性。 
  55.      * </p> 
  56.      * <p> 
  57.      * 1.前1、2位數字表示:所在省份的程式碼; 2.第3、4位數字表示:所在城市的程式碼; 3.第5、6位數字表示:所在區縣的程式碼; 
  58.      * 4.第7~14位數字表示:出生年、月、日; 5.第15、16位數字表示:所在地的派出所的程式碼; 
  59.      * 6.第17位數字表示性別:奇數表示男性,偶數表示女性; 
  60.      * 7.第18位數字是校檢碼:也有的說是個人資訊碼,一般是隨計算機的隨機產生,用來檢驗身份證的正確性。校檢碼可以是0~9的數字,有時也用x表示。 
  61.      * </p> 
  62.      * <p> 
  63.      * 第十八位數字(校驗碼)的計算方法為: 1.將前面的身份證號碼17位數分別乘以不同的係數。從第一位到第十七位的係數分別為:7 9 10 5 8 4 
  64.      * 2 1 6 3 7 9 10 5 8 4 2 
  65.      * </p> 
  66.      * <p> 
  67.      * 2.將這17位數字和係數相乘的結果相加。 
  68.      * </p> 
  69.      * <p> 
  70.      * 3.用加出來和除以11,看餘數是多少? 
  71.      * </p> 
  72.      * 4.餘數只可能有0 1 2 3 4 5 6 7 8 9 10這11個數字。其分別對應的最後一位身份證的號碼為1 0 X 9 8 7 6 5 4 3 
  73.      * 2。 
  74.      * <p> 
  75.      * 5.通過上面得知如果餘數是2,就會在身份證的第18位數字上出現羅馬數字的Ⅹ。如果餘數是10,身份證的最後一位號碼就是2。 
  76.      * </p> 
  77.      *  
  78.      * @param idcard 
  79.      * @return 
  80.      */
  81.     publicboolean isValidate18Idcard(String idcard) {  
  82.         // 非18位為假
  83.         if (idcard.length() != 18) {  
  84.             returnfalse;  
  85.         }  
  86.         // 獲取前17位
  87.         String idcard17 = idcard.substring(017);  
  88.         // 獲取第18位
  89.         String idcard18Code = idcard.substring(1718);  
  90.         char c[] = null;  
  91.         String checkCode = "";  
  92.         // 是否都為數字
  93.         if (isDigital(idcard17)) {  
  94.             c = idcard17.toCharArray();  
  95.         } else {  
  96.             returnfalse;  
  97.         }  
  98.         if (null != c) {  
  99.             int bit[] = newint[idcard17.length()];  
  100.             bit = converCharToInt(c);  
  101.             int sum17 = 0;  
  102.             sum17 = getPowerSum(bit);  
  103.             // 將和值與11取模得到餘數進行校驗碼判斷
  104.             checkCode = getCheckCodeBySum(sum17);  
  105.             if (null == checkCode) {  
  106.                 returnfalse;  
  107.             }  
  108.             // 將身份證的第18位與算出來的校碼進行匹配,不相等就為假
  109.             if (!idcard18Code.equalsIgnoreCase(checkCode)) {  
  110.                 returnfalse;  
  111.             }  
  112.         }  
  113.         returntrue;  
  114.     }  
  115.     /** 
  116.      * 驗證15位身份證的合法性,該方法驗證不準確,最好是將15轉為18位後再判斷,該類中已提供。 
  117.      *  
  118.      * @param idcard 
  119.      * @return 
  120.      */
  121.     publicboolean isValidate15Idcard(String idcard) {  
  122.         // 非15位為假
  123.         if (idcard.length() != 15) {  
  124.             returnfalse;  
  125.         }  
  126.         // 是否全都為數字
  127.         if (isDigital(idcard)) {  
  128.             String provinceid = idcard.substring(02);  
  129.             String birthday = idcard.substring(612);  
  130.             int year = Integer.parseInt(idcard.substring(68));  
  131.             int month = Integer.parseInt(idcard.substring(810));  
  132.             int day = Integer.parseInt(idcard.substring(1012));  
  133.             // 判斷是否為合法的省份
  134.             boolean flag = false;  
  135.             for (String id : cityCode) {  
  136.                 if (id.equals(provinceid)) {  
  137.                     flag = true;  
  138.                     break;  
  139.                 }  
  140.             }  
  141.             if (!flag) {  
  142.                 returnfalse;  
  143.             }  
  144.             // 該身份證生出日期在當前日期之後時為假
  145.             Date birthdate = null;  
  146.             try {  
  147.                 birthdate = new SimpleDateFormat("yyMMdd").parse(birthday);  
  148.             } catch (ParseException e) {  
  149.                 e.printStackTrace();  
  150.             }  
  151.             if (birthdate == null || new Date().before(birthdate)) {  
  152.                 returnfalse;  
  153.             }  
  154.             // 判斷是否為合法的年份
  155.             GregorianCalendar curDay = new GregorianCalendar();  
  156.             int curYear = curDay.get(Calendar.YEAR);  
  157.             int year2bit = Integer.parseInt(String.valueOf(curYear)  
  158.                     .substring(2));  
  159.             // 判斷該年份的兩位表示法,小於50的和大於當前年份的,為假
  160.             if ((year < 50 && year > year2bit)) {  
  161.                 returnfalse;  
  162.             }  
  163.             // 判斷是否為合法的月份
  164.             if (month < 1 || month > 12) {  
  165.                 returnfalse;  
  166.             }  
  167.             // 判斷是否為合法的日期
  168.             boolean mflag = false;  
  169.             curDay.setTime(birthdate); // 將該身份證的出生日期賦於物件curDay
  170.             switch (month) {  
  171.             case1:  
  172.             case3:  
  173.             case5:  
  174.             case7:  
  175.             case8:  
  176.             case10:  
  177.             case12:  
  178.                 mflag = (day >= 1 && day <= 31);  
  179.                 break;  
  180.             case2// 公曆的2月非閏年有28天,閏年的2月是29天。
  181.                 if (curDay.isLeapYear(curDay.get(Calendar.YEAR))) {  
  182.                     mflag = (day >= 1 && day <= 29);  
  183.                 } else {  
  184.                     mflag = (day >= 1 && day <= 28);  
  185.                 }  
  186.                 break;  
  187.             case4:  
  188.             case6:  
  189.             case9:  
  190.             case11:  
  191.                 mflag = (day >= 1 && day <= 30);  
  192.                 break;  
  193.             }  
  194.             if (!mflag) {  
  195.                 returnfalse;  
  196.             }  
  197.         } else {  
  198.             returnfalse;  
  199.         }  
  200.         returntrue;  
  201.     }  
  202.     /** 
  203.      * 將15位的身份證轉成18位身份證 
  204.      *  
  205.      * @param idcard 
  206.      * @return 
  207.      */
  208.     public String convertIdcarBy15bit(String idcard) {  
  209.         String idcard17 = null;  
  210.         // 非15位身份證
  211.         if (idcard.length() != 15) {  
  212.             returnnull;  
  213.         }  
  214.         if (isDigital(idcard)) {  
  215.             // 獲取出生年月日
  216.             String birthday = idcard.substring(612);  
  217.             Date birthdate = null;  
  218.             try {  
  219.                 birthdate = new SimpleDateFormat("yyMMdd").parse(birthday);  
  220.             } catch (ParseException e) {  
  221.                 e.printStackTrace();  
  222.             }  
  223.             Calendar cday = Calendar.getInstance();  
  224.             cday.setTime(birthdate);  
  225.             String year = String.valueOf(cday.get(Calendar.YEAR));  
  226.             idcard17 = idcard.substring(06) + year + idcard.substring(8);  
  227.             char c[] = idcard17.toCharArray();  
  228.             String checkCode = "";  
  229.             if (null != c) {  
  230.                 int bit[] = newint[idcard17.length()];  
  231.                 // 將字元陣列轉為整型陣列
  232.                 bit = converCharToInt(c);  
  233.                 int sum17 = 0;  
  234.                 sum17 = getPowerSum(bit);  
  235.                 // 獲取和值與11取模得到餘數進行校驗碼
  236.                 checkCode = getCheckCodeBySum(sum17);  
  237.                 // 獲取不到校驗位
  238.                 if (null == checkCode) {  
  239.                     returnnull;  
  240.                 }  
  241.                 // 將前17位與第18位校驗碼拼接
  242.                 idcard17 += checkCode;  
  243.             }  
  244.         } else { // 身份證包含數字
  245.             returnnull;  
  246.         }  
  247.         return idcard17;  
  248.     }  
  249.     /** 
  250.      * 15位和18位身份證號碼的基本數字和位數驗校 
  251.      *  
  252.      * @param idcard 
  253.      * @return 
  254.      */
  255.     publicboolean isIdcard(String idcard) {  
  256.         return idcard == null || "".equals(idcard) ? false : Pattern.matches(  
  257.                 "(^\\d{15}$)|(\\d{17}(?:\\d|x|X)$)", idcard);  
  258.     }  
  259.     /** 
  260.      * 15位身份證號碼的基本數字和位數驗校 
  261.      *  
  262.      * @param idcard 
  263.      * @return 
  264.      */
  265.     publicboolean is15Idcard(String idcard) {  
  266.         return idcard == null || "".equals(idcard) ? false : Pattern.matches(  
  267.                 "^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$",  
  268.                 idcard);  
  269.     }  
  270.     /** 
  271.      * 18位身份證號碼的基本數字和位數驗校 
  272.      *  
  273.      * @param idcard 
  274.      * @return 
  275.      */
  276.     publicboolean is18Idcard(String idcard) {  
  277.         return Pattern  
  278.                 .matches(  
  279.                         "^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([\\d|x|X]{1})$",  
  280.                         idcard);  
  281.     }  
  282.     /** 
  283.      * 數字驗證 
  284.      *  
  285.      * @param str 
  286.      * @return 
  287.      */
  288.     publicboolean isDigital(String str) {  
  289.         return str == null || "".equals(str) ? false : str.matches("^[0-9]*$");  
  290.     }  
  291.     /** 
  292.      * 將身份證的每位和對應位的加權因子相乘之後,再得到和值 
  293.      *  
  294.      * @param bit 
  295.      * @return 
  296.      */
  297.     publicint getPowerSum(int[] bit) {  
  298.         int sum = 0;  
  299.         if (power.length != bit.length) {  
  300.             return sum;  
  301.         }  
  302.         for (int i = 0; i < bit.length; i++) {  
  303.             for (int j = 0; j < power.length; j++) {  
  304.                 if (i == j) {  
  305.                     sum = sum + bit[i] * power[j];  
  306.                 }  
  307.             }  
  308.         }  
  309.         return sum;  
  310.     }  
  311.     /** 
  312.      * 將和值與11取模得到餘數進行校驗碼判斷 
  313.      *  
  314.      * @param checkCode 
  315.      * @param sum17 
  316.      * @return 校驗位 
  317.      */
  318.     public String getCheckCodeBySum(int sum17) {  
  319.         String checkCode = null;  
  320.         switch (sum17 % 11) {  
  321.         case10:  
  322.             checkCode = "2";  
  323.             break;  
  324.         case9:  
  325.             checkCode = "3";  
  326.             break;  
  327.         case8:  
  328.             checkCode = "4";  
  329.             break;  
  330.         case7:  
  331.             checkCode = "5";  
  332.             break;  
  333.         case6:  
  334.             checkCode = "6";  
  335.             break;  
  336.         case5:  
  337.             checkCode = "7";  
  338.             break;  
  339.         case4:  
  340.             checkCode = "8";  
  341.             break;  
  342.         case3:  
  343.             checkCode = "9";  
  344.             break;  
  345.         case2:  
  346.             checkCode = "x";  
  347.             break;  
  348.         case1:  
  349.             checkCode = "0";  
  350.             break;  
  351.         case0:  
  352.             checkCode = "1";  
  353.             break;  
  354.         }  
  355.         return checkCode;  
  356.     }  
  357.     /** 
  358.      * 將字元陣列轉為整型陣列 
  359.      *  
  360.      * @param c 
  361.      * @return 
  362.      * @throws NumberFormatException 
  363.      */
  364.     publicint[] converCharToInt(char[] c) throws NumberFormatException {  
  365.         int[] a = newint[c.length];  
  366.         int k = 0;  
  367.         for (char temp : c) {  
  368.             a[k++] = Integer.parseInt(String.valueOf(temp));  
  369.         }  
  370.         return a;  
  371.     }  
  372.     publicstaticvoid main(String[] args) throws Exception {  
  373.         String idcard15 = "";  
  374.         String idcard18 = "";  
  375.         IdcardValidator iv = new IdcardValidator();  
  376.         boolean flag = false;  
  377.         flag = iv.isValidate18Idcard(idcard18);  
  378.         System.out.println(flag);  
  379.         flag = iv.isValidate15Idcard(idcard15);  
  380.         System.out.println(flag);  
  381.         System.out.println(iv.convertIdcarBy15bit(idcard15));  
  382.         flag = iv.isValidate18Idcard(iv.convertIdcarBy15bit(idcard15));  
  383.         System.out.println(flag);  
  384.         System.out.println(iv.isValidatedAllIdcard(idcard18));  
  385.     }  
  386. }  

IdcardInfoExtractor類: [java] view plaincopyprint?
  1. import java.text.SimpleDateFormat;  
  2. import java.util.Calendar;  
  3. import java.util.Date;  
  4. import java.util.GregorianCalendar;  
  5. import java.util.HashMap;  
  6. import java.util.Map;  
  7. import java.util.Set;  
  8. publicclass IdcardInfoExtractor {  
  9.      // 省份  
  10.     private String province;    
  11.     // 城市  
  12.     private String city;    
  13.     // 區縣  
  14.     private String region;    
  15.     // 年份  
  16.     privateint year;    
  17.     // 月份  
  18.     privateint month;    
  19.     // 日期  
  20.     privateint day;    
  21.     // 性別  
  22.     private String gender;    
  23.     // 出生日期  
  24.     private Date birthday;   
  25.     //年齡
  26.     privateint age;  
  27.     private Map<String, String> cityCodeMap = new HashMap<String, String>() {    
  28.         {    
  29.             this.put("11""北京");    
  30.             this.put("12""天津");    
  31.             this.put("13""河北");    
  32.             this.put("14""山西");    
  33.             this.put("15""內蒙古");    
  34.             this.put("21""遼寧");    
  35.             this.put("22""吉林");    
  36.             this.put("23""黑龍江");    
  37.             this.put("31""上海");    
  38.             this.put("32""江蘇");    
  39.             this.put("33""浙江");    
  40.             this.put("34""安徽");    
  41.             this.put("35""福建");    
  42.             this.put("36""江西");    
  43.             this.put("37""山東");    
  44.             this.put("41""河南");    
  45.             this.put("42""湖北");    
  46.             this.put("43""湖南");    
  47.             this.put("44""廣東");    
  48.             this.put("45""廣西");    
  49.             this.put("46""海南");    
  50.             this.put("50""重慶");    
  51.             this.put("51""四川");    
  52.             this.put("52""貴州");    
  53.             this.put("53""雲南");    
  54.             this.put("54""西藏");    
  55.             this.put("61""陝西");    
  56.             this.put("62""甘肅");    
  57.             this.put("63""青海");    
  58.             this.put("64""寧夏");    
  59.             this.put("65""新疆");    
  60.             this.put("71""臺灣");    
  61.             this.put("81""香港");    
  62.             this.put("82""澳門");    
  63.             this.put("91""國外");    
  64.         }    
  65.     };    
  66.     private IdcardValidator validator = null;    
  67.     /**  
  68.      * 通過構造方法初始化各個成員屬性  
  69.      */
  70.     public IdcardInfoExtractor(String idcard) {    
  71.         try {    
  72.             validator = new IdcardValidator();    
  73.             if (validator.isValidatedAllIdcard(idcard)) {    
  74.                 if (idcard.length() == 15) {    
  75.                     idcard = validator.convertIdcarBy15bit(idcard);    
  76.                 }    
  77.                 // 獲取省份  
  78.                 String provinceId = idcard.substring(02);    
  79.                 Set<String> key = this.cityCodeMap.keySet();    
  80.                 for (String id : key) {    
  81.                     if (id.equals(provinceId)) {    
  82.                         this.province = this.cityCodeMap.get(id);    
  83.                         break;