身份证号校验工具类

package com.just.common.util;

import com.just.common.constant.RegexConstant;
import com.just.common.entity.IdCardInfo;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author liuguozhen
 * @date 2019-08-24 13:52
 * @description 身份证工具类
 */
public class IdCardUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(IdCardUtil.class);

    /**
     * 身份证号最大长度
     */
    private static final int ID_CARD_NUMBER_MAX_LENGTH = 18;

    /**
     * 身份证号最小长度
     */
    private static final int ID_CARD_NUMBER_MIN_LENGTH = 15;

    /**
     * 加权因子
     */
    private static final int[] WEIGHT_FACTOR = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};

    /**
     * 校验码
     */
    private static final String[] CHECK_CODE = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};

    /**
     * 省(直辖市、自治区)的代码
     */
    private static final String[] CITY_CODE = {"11", "12", "13", "14", "15", "21", "22", "23", "31", "32", "33", "34", "35", "36", "37", "41",
            "42", "43", "44", "45", "46", "50", "51", "52", "53", "54", "61", "62", "63", "64", "65", "71",
            "81", "82", "91"};

    private IdCardUtil() {

    }

    /**
     * 是否不是身份证号
     *
     * @param idCard 身份证号
     * @return true不是 false是
     */
    public static boolean isNotIdCard(String idCard) {

        LOGGER.info("idCard-->{}", idCard);

        if (StringUtils.isEmpty(idCard)) {
            return true;
        }

        idCard = idCard.toUpperCase();

        if (idCard.length() == ID_CARD_NUMBER_MIN_LENGTH) {
            idCard = idCardFrom15To18(idCard);
        }

        if (idCard.length() == ID_CARD_NUMBER_MAX_LENGTH) {

            if (isNotAllNumber(idCard)) {
                return true;
            }

            if (isNotCityCode(idCard)) {
                return true;
            }
            String lastOneNum = idCard.substring(idCard.length() - 1);
            String countLastOneNum = countIdCardLastOneNum(idCard.substring(0, idCard.length() - 1));
            return !lastOneNum.equals(countLastOneNum);
        }

        return true;
    }

    /**
     * 根据身份证号获取身份证信息
     *
     * @param idCard 身份证号
     * @return 身份证信息
     */
    public static IdCardInfo getIdCardInfo(String idCard) {
        if (isNotIdCard(idCard)) {
            return null;
        }

        idCard = idCard.toUpperCase();

        if (idCard.length() == ID_CARD_NUMBER_MIN_LENGTH) {
            idCard = idCardFrom15To18(idCard);
        }

        IdCardInfo idCardInfo = new IdCardInfo();
        idCardInfo.setIdCard(idCard);
        idCardInfo.setSexCode(getSexCode(idCard));
        idCardInfo.setSex(getSex(idCardInfo.getSexCode()));
        idCardInfo.setBirthStr(getBirthStr(idCard));
        idCardInfo.setBirth(getBirth(idCardInfo.getBirthStr()));
        idCardInfo.setAge(getAge(idCardInfo.getBirth()));
        return idCardInfo;
    }

    /**
     * 15位身份证号转18位身份证号
     *
     * @param idCard 15位身份证号
     * @return 18位身份证
     */
    public static String idCardFrom15To18(String idCard) {
        String prefix = "19";
        StringBuilder sb = new StringBuilder(idCard);
        sb.insert(6, prefix);
        sb.append(countIdCardLastOneNum(sb.toString()));
        return sb.toString();
    }

    /**
     * 计算17身份证号最后一位数
     *
     * @param idCard 身份证号
     * @return 最后一位身份证号
     */
    private static String countIdCardLastOneNum(String idCard) {
        StringBuilder sb = new StringBuilder(idCard);
        int sum = 0;
        int size = sb.length();
        for (int i = 0; i < size; i++) {
            sum += (Integer.parseInt(sb.substring(i, i + 1)) * WEIGHT_FACTOR[i]);
        }
        int divisor = 11;
        return (CHECK_CODE[sum % divisor]);
    }

    /**
     * 身份证不是纯数字(18位,前17位都是数字)
     *
     * @param idCard 身份证号
     * @return true不是 false是
     */
    private static boolean isNotAllNumber(String idCard) {
        Pattern pattern = Pattern.compile(RegexConstant.ALL_NUMBER_REGEX);
        Matcher matcher = pattern.matcher(idCard.substring(0, 17));
        return !matcher.matches();
    }

    /**
     * 检查不是省(直辖市、自治区)的代码
     *
     * @param idCard 身份证号
     * @return true不是 false是
     */
    private static boolean isNotCityCode(String idCard) {
        int start = 0;
        int end = 2;
        int errorIndex = -1;
        return Arrays.binarySearch(CITY_CODE, idCard.substring(start, end)) == errorIndex;
    }

    /**
     * 根据身份证获取性别编码
     *
     * @param idCard 身份证号
     * @return 性别编码
     */
    private static String getSexCode(String idCard) {
        int sexCode = (Integer.parseInt(idCard.substring(16, idCard.length() - 1))) % 2;
        return (sexCode == 0) ? "1" : "0";
    }

    /**
     * 获取性别中文
     *
     * @param sexCode 性别编码
     * @return 性别中文
     */
    private static String getSex(String sexCode) {
        switch (sexCode) {
            case "0":
                return "男";
            case "1":
                return "女";
            default:
                return "其他";
        }
    }

    /**
     * 根据身份证号获取生日字符串
     *
     * @param idCard 身份证号
     * @return 生日字符串
     */
    private static String getBirthStr(String idCard) {
        int start = 6;
        int end = 14;
        StringBuilder sb = new StringBuilder(idCard.substring(start, end));
        int index = 4;
        char value = '-';
        sb.insert(index, value);
        index = 7;
        sb.insert(index, value);
        return sb.toString();
    }

    /**
     * 生日字符串转生日日期 (yyyy-MM-dd)
     *
     * @param birthStr 生日字符串
     * @return 生日日期
     */
    private static Date getBirth(String birthStr) {
        try {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            format.setLenient(false);
            return format.parse(birthStr);
        } catch (Exception ex) {
            return null;
        }
    }

    /**
     * 根据生日日期获取年龄
     *
     * @param birth 生日日期
     * @return 年龄
     */
    private static int getAge(Date birth) {
        Calendar certificateCal = Calendar.getInstance();
        Calendar currentTimeCal = Calendar.getInstance();
        certificateCal.setTime(birth);
        int yearAge = (currentTimeCal.get(Calendar.YEAR)) - (certificateCal.get(Calendar.YEAR));
        certificateCal.set(currentTimeCal.get(Calendar.YEAR), certificateCal.get(Calendar.MONTH), certificateCal.get(Calendar.DAY_OF_MONTH));
        int monthFloor = (currentTimeCal.before(certificateCal) ? 1 : 0);
        return (yearAge - monthFloor);
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值