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);
}
}