分享

Java的身份证号码工具类

 獨醭湉睚 2011-09-23
阿影 发布于 2011年01月13日 10时, 19评/2956阅 ( 75人收藏, 收藏 )


实现从15位~18位的身份证号码转换,校验中国大陆公民身份证、香港居民身份证、澳门身份证和台湾身份证。

代码片段(1)

[代码] [Java]代码

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

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约