身份证号编码规则
第一、二位表示省(自治区、直辖市、特别行政区)。
第三、四位表示市(地级市、自治州、盟及国家直辖市所属市辖区和县的汇总码)。其中,01-20,51-70表示省直辖市;21-50表示地区(自治州、盟)。
第五、六位表示县(市辖区、县级市、旗)。01-18表示市辖区或地区(自治州、盟)辖县级市;21-80表示县(旗);81-99表示省直辖县级市。
第七、十四位表示出生年月日(单数字月日左侧用0补齐)。其中年份用四位数字表示,年、月、日之间不用分隔符。例如:1981年05月11日就用19810511表示。
第十五、十七位表示顺序码。对同地区、同年、月、日出生的人员编定的顺序号。其中第十七位奇数分给男性,偶数分给女性。
第十八位表示校验码。作为尾号的校验码,是由号码编制单位按统一的公式计算出来的,校验码如果出现数字10,就用X(罗马字符)来代替。
- 15位:6位地址码+6位出生年月日(900101代表1990年1月1日出生)+3位顺序码
- 18位:6位地址码+8位出生年月日(19900101代表1990年1月1日出生)+3位顺序码+1位校验码
身份证号脱敏
/**
* 身份证号脱敏
* 保留前六后三, 适用于15位和18位身份证号
*
* @param idCard
* @return String
**/
public static String desensitizedIdCard(String idCard){
if (StringUtils.isNotBlank(idCard)) {
if (idCard.length() == 15){
idCard = idCard.replaceAll("(\\w{6})\\w*(\\w{3})", "$1******$2");
}
if (idCard.length() == 18){
idCard = idCard.replaceAll("(\\w{6})\\w*(\\w{3})", "$1*********$2");
}
}
return idCard;
}
身份证号合法性校验
/**
* 身份证号合法性校验
*
* @param idCard
* @return String
*/
public static boolean isLegalIDCard(String idCard) {
boolean res = false;
// 校验规则(15或是18位身份证号码)
if (isMatches(idCard)) {
if (idCard.length() == 18) {
char[] idCardArray = idCard.toCharArray();
// 前十七位加权因子
int[] idCardWi = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
// 除以11后,可能产生的11位余数对应的验证码
String[] idCardY = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};
int total = 0;
for (int i = 0; i < idCardWi.length; i++) {
int count = Integer.parseInt(String.valueOf(idCardArray[i])) * idCardWi[i];
total += count;
}
// 最后一位校验码
int idCardModify = total % 11;
if (idCardY[idCardModify].toUpperCase().equals(String.valueOf(idCardArray[17]).toUpperCase())) {
res = true;
} else {
System.out.println(idCardY[idCardModify].toUpperCase());
res = false;
}
} else {
res = true;
}
}
return res;
}
private static boolean isMatches(String idCard) {
if (StringUtils.isBlank(idCard)) {
return false;
}
String regex = "(^[1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$)|"
+ "(^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}$)";
return idCard.matches(regex);
}
根据身份证号获取年龄
/**
* 根据身份证号获取年龄
*
* @param idCard
* @return Integer
*/
public static Integer getAgeByIdCard(String idCard) {
boolean legalIDCard = isLegalIDCard(idCard);
if (!legalIDCard) return null;
Integer age = null;
int year = Calendar.getInstance().get(Calendar.YEAR);
if (idCard.length() == 15) {
age = (year - Integer.parseInt("19" + idCard.substring(6, 8)));
} else if (idCard.length() == 18) {
age = (year - Integer.parseInt(idCard.substring(6, 10)));
}
return age;
}
根据生日日期获取年龄
根据生日当天为分界线来计算年龄。
private static int getAgeByBirthday(LocalDate birthday) {
int age = 0;
try {
Calendar now = Calendar.getInstance();
now.setTime(new Date());// 当前时间
now.setTimeInMillis(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli());
Calendar birth = Calendar.getInstance();
birth.setTimeInMillis(birthday.atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli());
if (birth.after(now)) {// 如果传入的时间,在当前时间的后面,返回0岁
age = 0;
} else {
age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR) - 1;
if (now.get(Calendar.MONTH) >= birth.get(Calendar.MONTH)) {
if (now.get(Calendar.DAY_OF_MONTH) >= birth.get(Calendar.DAY_OF_MONTH)) {
age += 1;
}
}
}
return age;
} catch (Exception e) {
return 0;
}
}
根据身份证号获取年龄、生日的Map集合
/**
* 根据身份证号获取年龄、生日的Map集合
*
* @param idCard
* @return Map<String, Object>
* @author wanglingqiang
*/
public static Map<String, Object> getAgeBirthDayByIdCard(String idCard) {
Map<String, Object> result = Maps.newHashMap();
if (!isMatches(idCard)) return result;
String birthdayStr = idCard.substring(6, 14);
LocalDate birthday = LocalDate.parse(birthdayStr, DateTimeFormatter.ofPattern(Constants.SMALL_DATE_FORMAT));
int age = getAgeByBirthday(birthday);
result.put("age", age);
result.put("birthday", birthday);
return result;
}
private static boolean isMatches(String idCard) {
//上面写了
}
private static int getAgeByBirthday(LocalDate birthday) {
//上面写了
}