Java的身份证号码工具类

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

代码片段(1)

017package my.tools;
018 
019import java.text.ParseException;
020import java.text.SimpleDateFormat;
021import java.util.Calendar;
022import java.util.Date;
023import java.util.HashMap;
024import java.util.Map;
025 
026import org.apache.commons.lang.StringUtils;
027 
028/**
029 * 身份证工具类
030 *
031 * @author June
032 * @version 1.0, 2010-06-17
033 */
034public 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}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值