Java的身份证号码工具类

  1 package com.liukedong.test;
  2 
  3 
  4 import java.text.ParseException;
  5 import java.text.SimpleDateFormat;
  6 import java.util.Calendar;
  7 import java.util.Date;
  8 import java.util.HashMap;
  9 import java.util.Map;
 10 
 11 import org.apache.commons.lang.StringUtils;
 12 
 13 /**
 14  * 身份证工具类
 15  * 
 16  * @author June
 17  * @version 1.0, 2010-06-17
 18  */
 19 /**
 20      * 将15位身份证号码转换为18位    conver15CardTo18
 21      * 验证身份证是否合法        validateCard
 22      * 验证18位身份编码是否合法    validateIdCard18
 23      * 验证15位身份编码是否合法    validateIdCard15
 24      * 验证10位身份编码是否合法    validateIdCard10
 25      * 验证台湾身份证号码        validateTWCard
 26      * 验证香港身份证号码        validateHKCard
 27      * 
 28      * 将字符数组转换成数字数组        converCharToInt
 29      * 将身份证的每位和对应位的加权因子相乘之后,再得到和值        getPowerSum
 30      * 将power和值与11取模获得余数进行校验码判断        getCheckCode18
 31      * 
 32      * 根据身份编号获取年龄    getAgeByIdCard
 33      * 根据身份编号获取生日    getBirthByIdCard
 34      * 根据身份编号获取生日年        getYearByIdCard
 35      * 根据身份编号获取生日月        getMonthByIdCard
 36      * 根据身份编号获取生日天        getDateByIdCard
 37      * 根据身份编号获取性别    getGenderByIdCard
 38      * 根据身份编号获取户籍省份        getProvinceByIdCard
 39      * 
 40      * 数字验证        isNum
 41      * 验证小于当前日期 是否有效        valiDate
 42      */
 43 public class IdCardUtil  extends StringUtils {
 44 
 45     /** 中国公民身份证号码最小长度。 */
 46     public static final int CHINA_ID_MIN_LENGTH = 15;
 47 
 48     /** 中国公民身份证号码最大长度。 */
 49     public static final int CHINA_ID_MAX_LENGTH = 18;
 50 
 51     /** 省、直辖市代码表 */
 52     public static final String cityCode[] = {
 53             "11", "12", "13", "14", "15", "21", "22", "23", "31", "32", "33", "34", "35", "36", "37", "41",
 54             "42", "43", "44", "45", "46", "50", "51", "52", "53", "54", "61", "62", "63", "64", "65", "71",
 55             "81", "82", "91"
 56     };
 57 
 58     /** 每位加权因子 */
 59     public static final int power[] = {
 60             7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2
 61     };
 62 
 63     /** 第18位校检码 */
 64     public static final String verifyCode[] = {
 65             "1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"
 66     };
 67     /** 最低年限 */
 68     public static final int MIN = 1930;
 69     public static Map<String, String> cityCodes = new HashMap<String, String>();
 70     /** 台湾身份首字母对应数字 */
 71     public static Map<String, Integer> twFirstCode = new HashMap<String, Integer>();
 72     /** 香港身份首字母对应数字 */
 73     public static Map<String, Integer> hkFirstCode = new HashMap<String, Integer>();
 74     static {
 75         cityCodes.put("11", "北京");
 76         cityCodes.put("12", "天津");
 77         cityCodes.put("13", "河北");
 78         cityCodes.put("14", "山西");
 79         cityCodes.put("15", "内蒙古");
 80         cityCodes.put("21", "辽宁");
 81         cityCodes.put("22", "吉林");
 82         cityCodes.put("23", "黑龙江");
 83         cityCodes.put("31", "上海");
 84         cityCodes.put("32", "江苏");
 85         cityCodes.put("33", "浙江");
 86         cityCodes.put("34", "安徽");
 87         cityCodes.put("35", "福建");
 88         cityCodes.put("36", "江西");
 89         cityCodes.put("37", "山东");
 90         cityCodes.put("41", "河南");
 91         cityCodes.put("42", "湖北");
 92         cityCodes.put("43", "湖南");
 93         cityCodes.put("44", "广东");
 94         cityCodes.put("45", "广西");
 95         cityCodes.put("46", "海南");
 96         cityCodes.put("50", "重庆");
 97         cityCodes.put("51", "四川");
 98         cityCodes.put("52", "贵州");
 99         cityCodes.put("53", "云南");
100         cityCodes.put("54", "西藏");
101         cityCodes.put("61", "陕西");
102         cityCodes.put("62", "甘肃");
103         cityCodes.put("63", "青海");
104         cityCodes.put("64", "宁夏");
105         cityCodes.put("65", "新疆");
106         cityCodes.put("71", "台湾");
107         cityCodes.put("81", "香港");
108         cityCodes.put("82", "澳门");
109         cityCodes.put("91", "国外");
110         twFirstCode.put("A", 10);
111         twFirstCode.put("B", 11);
112         twFirstCode.put("C", 12);
113         twFirstCode.put("D", 13);
114         twFirstCode.put("E", 14);
115         twFirstCode.put("F", 15);
116         twFirstCode.put("G", 16);
117         twFirstCode.put("H", 17);
118         twFirstCode.put("J", 18);
119         twFirstCode.put("K", 19);
120         twFirstCode.put("L", 20);
121         twFirstCode.put("M", 21);
122         twFirstCode.put("N", 22);
123         twFirstCode.put("P", 23);
124         twFirstCode.put("Q", 24);
125         twFirstCode.put("R", 25);
126         twFirstCode.put("S", 26);
127         twFirstCode.put("T", 27);
128         twFirstCode.put("U", 28);
129         twFirstCode.put("V", 29);
130         twFirstCode.put("X", 30);
131         twFirstCode.put("Y", 31);
132         twFirstCode.put("W", 32);
133         twFirstCode.put("Z", 33);
134         twFirstCode.put("I", 34);
135         twFirstCode.put("O", 35);
136         hkFirstCode.put("A", 1);
137         hkFirstCode.put("B", 2);
138         hkFirstCode.put("C", 3);
139         hkFirstCode.put("R", 18);
140         hkFirstCode.put("U", 21);
141         hkFirstCode.put("Z", 26);
142         hkFirstCode.put("X", 24);
143         hkFirstCode.put("W", 23);
144         hkFirstCode.put("O", 15);
145         hkFirstCode.put("N", 14);
146     }
147 
148     /**
149      * 将15位身份证号码转换为18位
150      * 
151      * @param idCard
152      *            15位身份编码
153      * @return 18位身份编码
154      */
155     public static String conver15CardTo18(String idCard) {
156         String idCard18 = "";
157         if (idCard.length() != CHINA_ID_MIN_LENGTH) {
158             return null;
159         }
160         if (isNum(idCard)) {
161             // 获取出生年月日
162             String birthday = idCard.substring(6, 12);
163             Date birthDate = null;
164             try {
165                 birthDate = new SimpleDateFormat("yyMMdd").parse(birthday);
166             } catch (ParseException e) {
167                 e.printStackTrace();
168             }
169             Calendar cal = Calendar.getInstance();
170             if (birthDate != null)
171                 cal.setTime(birthDate);
172             // 获取出生年(完全表现形式,如:2010)
173             String sYear = String.valueOf(cal.get(Calendar.YEAR));
174             idCard18 = idCard.substring(0, 6) + sYear + idCard.substring(8);
175             // 转换字符数组
176             char[] cArr = idCard18.toCharArray();
177             if (cArr != null) {
178                 int[] iCard = converCharToInt(cArr);
179                 int iSum17 = getPowerSum(iCard);
180                 // 获取校验位
181                 String sVal = getCheckCode18(iSum17);
182                 if (sVal.length() > 0) {
183                     idCard18 += sVal;
184                 } else {
185                     return null;
186                 }
187             }
188         } else {
189             return null;
190         }
191         return idCard18;
192     }
193 
194     /**
195      * 验证身份证是否合法
196      */
197     public static boolean validateCard(String idCard) {
198         String card = idCard.trim();
199         if (validateIdCard18(card)) {
200             return true;
201         }
202         if (validateIdCard15(card)) {
203             return true;
204         }
205         String[] cardval = validateIdCard10(card);
206         if (cardval != null) {
207             if (cardval[2].equals("true")) {
208                 return true;
209             }
210         }
211         return false;
212     }
213 
214     /**
215      * 验证18位身份编码是否合法
216      * 
217      * @param idCard 身份编码
218      * @return 是否合法
219      */
220     public static boolean validateIdCard18(String idCard) {
221         boolean bTrue = false;
222         if (idCard.length() == CHINA_ID_MAX_LENGTH) {
223             // 前17位
224             String code17 = idCard.substring(0, 17);
225             // 第18位
226             String code18 = idCard.substring(17, CHINA_ID_MAX_LENGTH);
227             if (isNum(code17)) {
228                 char[] cArr = code17.toCharArray();
229                 if (cArr != null) {
230                     int[] iCard = converCharToInt(cArr);
231                     int iSum17 = getPowerSum(iCard);
232                     // 获取校验位
233                     String val = getCheckCode18(iSum17);
234                     if (val.length() > 0) {
235                         if (val.equalsIgnoreCase(code18)) {
236                             bTrue = true;
237                         }
238                     }
239                 }
240             }
241         }
242         return bTrue;
243     }
244 
245     /**
246      * 验证15位身份编码是否合法
247      * 
248      * @param idCard
249      *            身份编码
250      * @return 是否合法
251      */
252     public static boolean validateIdCard15(String idCard) {
253         if (idCard.length() != CHINA_ID_MIN_LENGTH) {
254             return false;
255         }
256         if (isNum(idCard)) {
257             String proCode = idCard.substring(0, 2);
258             if (cityCodes.get(proCode) == null) {
259                 return false;
260             }
261             String birthCode = idCard.substring(6, 12);
262             Date birthDate = null;
263             try {
264                 birthDate = new SimpleDateFormat("yy").parse(birthCode.substring(0, 2));
265             } catch (ParseException e) {
266                 e.printStackTrace();
267             }
268             Calendar cal = Calendar.getInstance();
269             if (birthDate != null)
270                 cal.setTime(birthDate);
271             if (!valiDate(cal.get(Calendar.YEAR), Integer.valueOf(birthCode.substring(2, 4)),
272                     Integer.valueOf(birthCode.substring(4, 6)))) {
273                 return false;
274             }
275         } else {
276             return false;
277         }
278         return true;
279     }
280 
281     /**
282      * 验证10位身份编码是否合法
283      * 
284      * @param idCard 身份编码
285      * @return 身份证信息数组
286      *         <p>
287      *         [0] - 台湾、澳门、香港 [1] - 性别(男M,女F,未知N) [2] - 是否合法(合法true,不合法false)
288      *         若不是身份证件号码则返回null
289      *         </p>
290      */
291     public static String[] validateIdCard10(String idCard) {
292         String[] info = new String[3];
293         String card = idCard.replaceAll("[\\(|\\)]", "");
294         if (card.length() != 8 && card.length() != 9 && idCard.length() != 10) {
295             return null;
296         }
297         if (idCard.matches("^[a-zA-Z][0-9]{9}$")) { // 台湾
298             info[0] = "台湾";
299             System.out.println("11111");
300             String char2 = idCard.substring(1, 2);
301             if (char2.equals("1")) {
302                 info[1] = "M";
303                 System.out.println("MMMMMMM");
304             } else if (char2.equals("2")) {
305                 info[1] = "F";
306                 System.out.println("FFFFFFF");
307             } else {
308                 info[1] = "N";
309                 info[2] = "false";
310                 System.out.println("NNNN");
311                 return info;
312             }
313             info[2] = validateTWCard(idCard) ? "true" : "false";
314         } else if (idCard.matches("^[1|5|7][0-9]{6}\\(?[0-9A-Z]\\)?$")) { // 澳门
315             info[0] = "澳门";
316             info[1] = "N";
317             // TODO
318         } else if (idCard.matches("^[A-Z]{1,2}[0-9]{6}\\(?[0-9A]\\)?$")) { // 香港
319             info[0] = "香港";
320             info[1] = "N";
321             info[2] = validateHKCard(idCard) ? "true" : "false";
322         } else {
323             return null;
324         }
325         return info;
326     }
327 
328     /**
329      * 验证台湾身份证号码
330      * 
331      * @param idCard
332      *            身份证号码
333      * @return 验证码是否符合
334      */
335     public static boolean validateTWCard(String idCard) {
336         String start = idCard.substring(0, 1);
337         String mid = idCard.substring(1, 9);
338         String end = idCard.substring(9, 10);
339         Integer iStart = twFirstCode.get(start);
340         Integer sum = iStart / 10 + (iStart % 10) * 9;
341         char[] chars = mid.toCharArray();
342         Integer iflag = 8;
343         for (char c : chars) {
344             sum = sum + Integer.valueOf(c + "") * iflag;
345             iflag--;
346         }
347         return (sum % 10 == 0 ? 0 : (10 - sum % 10)) == Integer.valueOf(end) ? true : false;
348     }
349 
350     /**
351      * 验证香港身份证号码(存在Bug,部份特殊身份证无法检查)
352      * <p>
353      * 身份证前2位为英文字符,如果只出现一个英文字符则表示第一位是空格,对应数字58 前2位英文字符A-Z分别对应数字10-35
354      * 最后一位校验码为0-9的数字加上字符"A","A"代表10
355      * </p>
356      * <p>
357      * 将身份证号码全部转换为数字,分别对应乘9-1相加的总和,整除11则证件号码有效
358      * </p>
359      * 
360      * @param idCard 身份证号码
361      * @return 验证码是否符合
362      */
363     public static boolean validateHKCard(String idCard) {
364         String card = idCard.replaceAll("[\\(|\\)]", "");
365         Integer sum = 0;
366         if (card.length() == 9) {
367             sum = (Integer.valueOf(card.substring(0, 1).toUpperCase().toCharArray()[0]) - 55) * 9
368                     + (Integer.valueOf(card.substring(1, 2).toUpperCase().toCharArray()[0]) - 55) * 8;
369             card = card.substring(1, 9);
370         } else {
371             sum = 522 + (Integer.valueOf(card.substring(0, 1).toUpperCase().toCharArray()[0]) - 55) * 8;
372         }
373         String mid = card.substring(1, 7);
374         String end = card.substring(7, 8);
375         char[] chars = mid.toCharArray();
376         Integer iflag = 7;
377         for (char c : chars) {
378             sum = sum + Integer.valueOf(c + "") * iflag;
379             iflag--;
380         }
381         if (end.toUpperCase().equals("A")) {
382             sum = sum + 10;
383         } else {
384             sum = sum + Integer.valueOf(end);
385         }
386         return (sum % 11 == 0) ? true : false;
387     }
388 
389     /**
390      * 将字符数组转换成数字数组
391      * 
392      * @param ca
393      *            字符数组
394      * @return 数字数组
395      */
396     public static int[] converCharToInt(char[] ca) {
397         int len = ca.length;
398         int[] iArr = new int[len];
399         try {
400             for (int i = 0; i < len; i++) {
401                 iArr[i] = Integer.parseInt(String.valueOf(ca[i]));
402             }
403         } catch (NumberFormatException e) {
404             e.printStackTrace();
405         }
406         return iArr;
407     }
408 
409     /**
410      * 将身份证的每位和对应位的加权因子相乘之后,再得到和值
411      * 
412      * @param iArr
413      * @return 身份证编码。
414      */
415     public static int getPowerSum(int[] iArr) {
416         int iSum = 0;
417         if (power.length == iArr.length) {
418             for (int i = 0; i < iArr.length; i++) {
419                 for (int j = 0; j < power.length; j++) {
420                     if (i == j) {
421                         iSum = iSum + iArr[i] * power[j];
422                     }
423                 }
424             }
425         }
426         return iSum;
427     }
428 
429     /**
430      * 将power和值与11取模获得余数进行校验码判断
431      * 
432      * @param iSum
433      * @return 校验位
434      */
435     public static String getCheckCode18(int iSum) {
436         String sCode = "";
437         switch (iSum % 11) {
438         case 10:
439             sCode = "2";
440             break;
441         case 9:
442             sCode = "3";
443             break;
444         case 8:
445             sCode = "4";
446             break;
447         case 7:
448             sCode = "5";
449             break;
450         case 6:
451             sCode = "6";
452             break;
453         case 5:
454             sCode = "7";
455             break;
456         case 4:
457             sCode = "8";
458             break;
459         case 3:
460             sCode = "9";
461             break;
462         case 2:
463             sCode = "x";
464             break;
465         case 1:
466             sCode = "0";
467             break;
468         case 0:
469             sCode = "1";
470             break;
471         }
472         return sCode;
473     }
474 
475     /**
476      * 根据身份编号获取年龄
477      * 
478      * @param idCard
479      *            身份编号
480      * @return 年龄
481      */
482     public static int getAgeByIdCard(String idCard) {
483         int iAge = 0;
484         if (idCard.length() == CHINA_ID_MIN_LENGTH) {
485             idCard = conver15CardTo18(idCard);
486         }
487         String year = idCard.substring(6, 10);
488         Calendar cal = Calendar.getInstance();
489         int iCurrYear = cal.get(Calendar.YEAR);
490         iAge = iCurrYear - Integer.valueOf(year);
491         return iAge;
492     }
493 
494     /**
495      * 根据身份编号获取生日
496      * 
497      * @param idCard 身份编号
498      * @return 生日(yyyyMMdd)
499      */
500     public static String getBirthByIdCard(String idCard) {
501         Integer len = idCard.length();
502         if (len < CHINA_ID_MIN_LENGTH) {
503             return null;
504         } else if (len == CHINA_ID_MIN_LENGTH) {
505             idCard = conver15CardTo18(idCard);
506         }
507         return idCard.substring(6, 14);
508     }
509 
510     /**
511      * 根据身份编号获取生日年
512      * 
513      * @param idCard 身份编号
514      * @return 生日(yyyy)
515      */
516     public static Short getYearByIdCard(String idCard) {
517         Integer len = idCard.length();
518         if (len < CHINA_ID_MIN_LENGTH) {
519             return null;
520         } else if (len == CHINA_ID_MIN_LENGTH) {
521             idCard = conver15CardTo18(idCard);
522         }
523         return Short.valueOf(idCard.substring(6, 10));
524     }
525 
526     /**
527      * 根据身份编号获取生日月
528      * 
529      * @param idCard
530      *            身份编号
531      * @return 生日(MM)
532      */
533     public static Short getMonthByIdCard(String idCard) {
534         Integer len = idCard.length();
535         if (len < CHINA_ID_MIN_LENGTH) {
536             return null;
537         } else if (len == CHINA_ID_MIN_LENGTH) {
538             idCard = conver15CardTo18(idCard);
539         }
540         return Short.valueOf(idCard.substring(10, 12));
541     }
542 
543     /**
544      * 根据身份编号获取生日天
545      * 
546      * @param idCard
547      *            身份编号
548      * @return 生日(dd)
549      */
550     public static Short getDateByIdCard(String idCard) {
551         Integer len = idCard.length();
552         if (len < CHINA_ID_MIN_LENGTH) {
553             return null;
554         } else if (len == CHINA_ID_MIN_LENGTH) {
555             idCard = conver15CardTo18(idCard);
556         }
557         return Short.valueOf(idCard.substring(12, 14));
558     }
559 
560     /**
561      * 根据身份编号获取性别
562      * 
563      * @param idCard 身份编号
564      * @return 性别(M-男,F-女,N-未知)
565      */
566     public static String getGenderByIdCard(String idCard) {
567         String sGender = "N";
568         if (idCard.length() == CHINA_ID_MIN_LENGTH) {
569             idCard = conver15CardTo18(idCard);
570         }
571         String sCardNum = idCard.substring(16, 17);
572         if (Integer.parseInt(sCardNum) % 2 != 0) {
573             sGender = "M";
574         } else {
575             sGender = "F";
576         }
577         return sGender;
578     }
579 
580     /**
581      * 根据身份编号获取户籍省份
582      * 
583      * @param idCard 身份编码
584      * @return 省级编码。
585      */
586     public static String getProvinceByIdCard(String idCard) {
587         int len = idCard.length();
588         String sProvince = null;
589         String sProvinNum = "";
590         if (len == CHINA_ID_MIN_LENGTH || len == CHINA_ID_MAX_LENGTH) {
591             sProvinNum = idCard.substring(0, 2);
592         }
593         sProvince = cityCodes.get(sProvinNum);
594         return sProvince;
595     }
596 
597     /**
598      * 数字验证
599      * 
600      * @param val
601      * @return 提取的数字。
602      */
603     public static boolean isNum(String val) {
604         return val == null || "".equals(val) ? false : val.matches("^[0-9]*$");
605     }
606 
607     /**
608      * 验证小于当前日期 是否有效
609      * 
610      * @param iYear
611      *            待验证日期(年)
612      * @param iMonth
613      *            待验证日期(月 1-12)
614      * @param iDate
615      *            待验证日期(日)
616      * @return 是否有效
617      */
618     public static boolean valiDate(int iYear, int iMonth, int iDate) {
619         Calendar cal = Calendar.getInstance();
620         int year = cal.get(Calendar.YEAR);
621         int datePerMonth;
622         if (iYear < MIN || iYear >= year) {
623             return false;
624         }
625         if (iMonth < 1 || iMonth > 12) {
626             return false;
627         }
628         switch (iMonth) {
629         case 4:
630         case 6:
631         case 9:
632         case 11:
633             datePerMonth = 30;
634             break;
635         case 2:
636             boolean dm = ((iYear % 4 == 0 && iYear % 100 != 0) || (iYear % 400 == 0))
637                     && (iYear > MIN && iYear < year);
638             datePerMonth = dm ? 29 : 28;
639             break;
640         default:
641             datePerMonth = 31;
642         }
643         return (iDate >= 1) && (iDate <= datePerMonth);
644     }
645 }

 

posted @ 2013-10-07 21:43  刘可冬  阅读(1062)  评论(0编辑  收藏  举报