package com.examine.ythgk.util;
import com.examine.common.core.utils.StringUtils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created with IntelliJ IDEA.
* User: Shendi
* Date: 2022/12/4/004
* Time: 17:04
* Description:从身份证号码中获取出生日期、性别、年龄(15位和18位)
*/
public class IdCardNumberMethod {
/**
* 校验车牌号是否正确
*/
public static boolean checkPlateNumber(String clcph){
// 中国车牌号规则正则表达式,允许6或7位字符
String pattern = "(^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳E]{1}[A-Z0-9]{1}$)|(^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$)";
// 编译正则表达式
Pattern p = Pattern.compile(pattern);
// 进行匹配
Matcher m = p.matcher(clcph);
// 返回匹配结果
return m.matches();
}
/**
* 获取出生日期
*
* @return 返回字符串类型
*/
public String getBirthFromIdCard(String idCard) {
if (idCard.length() != 18 && idCard.length() != 15) {
return "请输入正确的身份证号码";
}
if (idCard.length() == 18) {
String year = idCard.substring(6).substring(0, 4);// 得到年份
String month = idCard.substring(10).substring(0, 2);// 得到月份
String day = idCard.substring(12).substring(0, 2);// 得到日
return (year + "-" + month + "-" + day);
} else if (idCard.length() == 15) {
String year = "19" + idCard.substring(6, 8);// 年份
String month = idCard.substring(8, 10);// 月份
String day = idCard.substring(10, 12);// 得到日
return (year + "-" + month + "-" + day);
}
return null;
}
/**
* 获取出生日期
*
* @return 返回日期格式
*/
public Date getBirthDayFromIdCard(String idCard) throws ParseException {
Date birth = null;
if (idCard.length() == 18) {
String year = idCard.substring(6).substring(0, 4);// 得到年份
String month = idCard.substring(10).substring(0, 2);// 得到月份
String day = idCard.substring(12).substring(0, 2);// 得到日
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
birth = format.parse(year + "-" + month + "-" + day);
} else if (idCard.length() == 15) {
String year = "19" + idCard.substring(6, 8);// 年份
String month = idCard.substring(8, 10);// 月份
String day = idCard.substring(10, 12);// 得到日
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
birth = format.parse(year + "-" + month + "-" + day);
}
return birth;
}
/**
* 获取性别
* 0=未知的性别,9=未说明的性别,2=女性,1=男性
* @return int
*/
public static int getSexFromIdCard(String idCard) {
int sex = 9;
// 身份证号码为空
if (idCard == "" || idCard.length() <= 0){
return sex = 0;
}
if (idCard.length() == 18) {
if (Integer.parseInt(idCard.substring(16).substring(0, 1)) % 2 == 0) {// 判断性别
sex = 2; // 女
} else {
sex = 1; // 男
}
} else if (idCard.length() == 15) {
String usex = idCard.substring(14, 15);// 用户的性别
if (Integer.parseInt(usex) % 2 == 0) {
sex = 2; // 女
} else {
sex = 1; // 男
}
}
return sex;
}
/**
* 获取性别
* 0=未知的性别,9=未说明的性别,2=女性,1=男性
* @return int
*/
public static String getSexFromIdCardXbmc(String idCard) {
String sex = "未说明的性别";
// 身份证号码为空
if (idCard == "" || idCard.length() <= 0){
return sex = "未知的性别";
}
if (idCard.length() == 18) {
if (Integer.parseInt(idCard.substring(16).substring(0, 1)) % 2 == 0) {// 判断性别
sex = "女"; // 女
} else {
sex = "男"; // 男
}
} else if (idCard.length() == 15) {
String usex = idCard.substring(14, 15);// 用户的性别
if (Integer.parseInt(usex) % 2 == 0) {
sex = "女"; // 女
} else {
sex = "男"; // 男
}
}
return sex;
}
/**
* 根据身份证的号码算出当前身份证持有者的年龄
*
* @param
* @throws Exception
* @return -1(表示异常) 0 (身份证号码为空)
*/
public static int getAgeForIdcard(String idcard) {
try {
int age = 0;
if (StringUtils.isEmpty(idcard)) {
return age;
}
String birth = "";
if (idcard.length() == 18) {
birth = idcard.substring(6, 14);
} else if (idcard.length() == 15) {
birth = "19" + idcard.substring(6, 12);
}
int year = Integer.valueOf(birth.substring(0, 4));
int month = Integer.valueOf(birth.substring(4, 6));
int day = Integer.valueOf(birth.substring(6));
Calendar cal = Calendar.getInstance();
age = cal.get(Calendar.YEAR) - year;
//周岁计算
if (cal.get(Calendar.MONTH) < (month - 1) || (cal.get(Calendar.MONTH) == (month - 1) && cal.get(Calendar.DATE) < day)) {
age--;
}
return age;
} catch (Exception e) {
e.getMessage();
}
return -1;
}
/**
* 15 位身份证号码转 18 位
* <p>
* 15位身份证号码:第7、8位为出生年份(两位数),第9、10位为出生月份,第11、12位代表出生日期,第15位代表性别,奇数为男,偶数为女。
* 18位身份证号码:第7、8、9、10位为出生年份(四位数),第11、第12位为出生月份,第13、14位代表出生日期,第17位代表性别,奇数为男,偶数为女。
*/
public StringBuffer IdCardMethod15To18(String idCard) {
//将字符串转化为buffer进行操作
StringBuffer stringBuffer = new StringBuffer(idCard);
//身份证最后一位校验码,X代表10(顺序固定)
char[] checkIndex = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
int sum = 0;
//在第6位插入年份的前两位19
stringBuffer.insert(6, "19");
for (int i = 0; i < stringBuffer.length(); i++) {
char c = stringBuffer.charAt(i);
//前17位数字
int ai = Integer.valueOf(String.valueOf(c));
//前17位每位对应的系数(7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 )
int wi = ((int) Math.pow(2, stringBuffer.length() - i)) % 11;
//总和(每位数字乘以系数再相加)
sum = sum + ai * wi;
}
//总和除以11求余
int indexOf = sum % 11;
//根据余数作为下表在校验码数组里取值
stringBuffer.append(checkIndex[indexOf]);
return stringBuffer;
}
/** 以下是对身份证号码验证内容 **/
/** 省份开头字典 */
private static Map<Integer, String> provinces = new HashMap<>();
static {
provinces.put(11, "北京");
provinces.put(12, "天津");
provinces.put(13, "河北");
provinces.put(14, "山西");
provinces.put(15, "内蒙古");
provinces.put(21, "辽宁");
provinces.put(22, "吉林");
provinces.put(23, "黑龙江");
provinces.put(31, "上海");
provinces.put(32, "江苏");
provinces.put(33, "浙江");
provinces.put(34, "安徽");
provinces.put(35, "福建");
provinces.put(36, "江西");
provinces.put(37, "山东");
provinces.put(41, "河南");
provinces.put(42, "湖北 ");
provinces.put(43, "湖南");
provinces.put(44, "广东");
provinces.put(45, "广西");
provinces.put(46, "海南");
provinces.put(50, "重庆");
provinces.put(51, "四川");
provinces.put(52, "贵州");
provinces.put(53, "云南");
provinces.put(54, "西藏 ");
provinces.put(61, "陕西");
provinces.put(62, "甘肃");
provinces.put(63, "青海");
provinces.put(64, "宁夏");
provinces.put(65, "新疆");
provinces.put(71, "台湾");
provinces.put(81, "香港");
provinces.put(82, "澳门");
}
/**
* @description 简单校验满足非空及18位,无法校验到月份对应天数
* @date 2022/10/10 16:52
* @param
* @param IdCard
* @return boolean
*/
public static boolean easyCheckIdCard(String IdCard) {
//字符串为空或者不符合简单的18位校验返回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]$";
if (StringUtils.isBlank(IdCard) || !Pattern.matches(regex, IdCard)) {
return false;
}
return true;
}
/**
* @description 中级校验,不校验最后一位
* @date 2022/10/10 16:57
* @param
* @param IdCard
* @return boolean
*/
public static boolean middleCheckIdCard(String IdCard) {
return (easyCheckIdCard(IdCard) && checkBirthday(IdCard) && checkProvince(IdCard));
}
/**
* @description 高级校验包含校验位
* @date 2022/10/10 16:57
* @param
* @param IdCard
* @return boolean
*/
public static boolean highCheckIdCard(String IdCard) {
return (middleCheckIdCard(IdCard) && checkLastNumber(IdCard));
}
/**
* @description 身份证校验位的校验
* @date 2022/10/10 15:16
* @param
* @param IdCard
* @return boolean
*/
public static boolean checkLastNumber(String IdCard) {
try {
char[] charArray = 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 sum = 0;
for (int i = 0; i < IdCardWi.length; i++) {
int current = Integer.parseInt(String.valueOf(charArray[i]));
int count = current * IdCardWi[i];
sum += count;
}
char IdCardLast = charArray[17];
int IdCardMod = sum % 11;
return IdCardY[IdCardMod].toUpperCase().equals(String.valueOf(IdCardLast).toUpperCase());
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* @description 年月日校验
* @date 2022/10/10 16:48
* @param
* @param IdCard
* @return boolean
*/
public static boolean checkBirthday(String IdCard) {
String yearRegex = "(18|19|20)\\d{2}";
String monthRegex = "(0[1-9])|10|11|12";
String dayRegex = "([0-2][1-9])|10|20|30|31";
String year = IdCard.substring(6, 10);
if (!Pattern.matches(yearRegex, year)) {
return false;
}
String month = IdCard.substring(10, 12);
if (!Pattern.matches(monthRegex, month)) {
return false;
}
String day = IdCard.substring(12, 14);
if (!Pattern.matches(dayRegex, day)) {
return false;
}
Integer yearInt = Integer.parseInt(year);
Integer monthInt = Integer.parseInt(month);
Integer dayInt = Integer.parseInt(day);
switch (monthInt) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
return true;
case 2:
if (leapYear(yearInt)) {
//闰年 29
return dayInt <= 29;
}
return dayInt <= 28;
default:
return dayInt <= 30;
}
}
/**
* @description 校验是否为闰年
* @date 2022/10/10 15:39
* @param
* @param year
* @return boolean
*/
public static boolean leapYear(int year) {
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
return true;
}
return false;
}
/**
* @description 身份证省份的校验,这里默认符合简单的18位校验
* @date 2022/10/10 15:18
* @param
* @param IdCard
* @return boolean
*/
public static boolean checkProvince(String IdCard) {
String pattern = "^[1-9][0-9]";
String prov = IdCard.substring(0, 2);
if (Pattern.matches(pattern, prov)) {
return provinces.containsKey(Integer.parseInt(prov));
}
return false;
}
}