package com.hf.mypractice.utils;
import jodd.datetime.JDateTime;
import jodd.datetime.Period;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* @Description:
* @Date: 2019/3/27
* @Auther:
*/
@Slf4j
public class CommonUtil {
/**
* 身份证正则 15位
*/
private final static String IDENTITY_CARD_15 = "^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$";
/**
* 身份证正则 18位
*/
private final static String IDENTITY_CARD_18 = "^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}(\\d|[xX])$"
/**
* 15位身份证从第一位到15位对应的系数分别为:从第一位到第十七位的系数分别为:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2
*/
private static final int[] widthArr = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
/**
* 第18位校验码数组
*/
private static final String[] checkArr = { "1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2" };
/**
*校验身份证的合法性
* @return
*/
public static Boolean checkIdentityCard(String identityCard){
Boolean isOk = false;
if(StringUtils.isNotEmpty(identityCard)){
identityCard = identityCard.trim();
if(identityCard.length() == 15){
isOk = RegexUtil.check(identityCard, IDENTITY_CARD_15);
}else{
isOk = RegexUtil.check(identityCard,IDENTITY_CARD_18);
}
}
return isOk;
}
/**
* 通过身份证获取性别
* @return 0.身份证不合法 1.男性 2.女性
*/
public static Integer getGenderByIdentityCard(String identityCard){
//校验身份证
Boolean isOk = checkIdentityCard(identityCard);
Integer sexNum = 0;
if(isOk){
if (15 == identityCard.length()) {
// 15位身份证 最后一位表示性别
sexNum = Integer.valueOf(identityCard.substring(14));
} else if (18 == identityCard.length()) {
//18位身份证 17位表示性别
sexNum = Integer.valueOf(identityCard.substring(16, 17));
}
sexNum = (sexNum & 1) != 1 ? 2 : 1;
}
return sexNum;
}
/**
* 15位:6位地址码+6位出生年月日(900101代表1990年1月1日出生)+3位顺序码
* 18位:6位地址码+8位出生年月日(19900101代表1990年1月1日出生)+3位顺序码+1位校验码
* @return 错误码 10001
*/
public static Integer getAgeByIdentityCard(String identityCard){
//校验身份证
identityCard = identityCard.trim();
Boolean isOk = checkIdentityCard(identityCard);
Integer age = 10001;
if(isOk){
if(identityCard.length() == 15){
//转换为18位
identityCard = card15To18(identityCard);
}
//获取出生年月
Date birthday = getBirthdayByIdentityCard(identityCard);
if(null != birthday){
//计算时间差
JDateTime currTime = new JDateTime(System.currentTimeMillis());
JDateTime birthdayTime = new JDateTime(birthday);
Period period = new Period(birthdayTime,currTime);
long days = period.getDays();
log.info("相差的天数为:" + days);
age = Integer.parseInt(days / 365 + "") + 1;
}
}
return age;
}
/**
* 根据身份证获取出生日期
* @param identityCard
* @return
*/
public static Date getBirthdayByIdentityCard(String identityCard){
//校验合法
Boolean isOk = checkIdentityCard(identityCard);
Date birthday = null;
if(isOk){
identityCard = identityCard.trim();
String birthdayString = null;
if(identityCard.length() == 15){
//转换为18位
identityCard = card15To18(identityCard);
}
//18位:6位地址码+8位出生年月日(19900101代表1990年1月1日出生)+3位顺序码+1位校验码
birthdayString = identityCard.substring(6,14);
birthday = dateStringFormat(birthdayString);
}
return birthday;
}
/**
* 日期字符串格式化
* @param dateString
* @return
*/
public static Date dateStringFormat(String dateString){
Date date = null;
if(StringUtils.isNotEmpty(dateString)){
JDateTime jDateTime = new JDateTime(dateString,"YYYYMMDD");
date = jDateTime.convertToDate();
}
return date;
}
/**
* 将15位身份证转换为18位
* @return 如果不是15位身份证,或者不合法将输出null,否则输出转换的18位身份证号码
*/
public static String card15To18(String identityCard){
String result = null;
if(StringUtils.isNotEmpty(identityCard)){
identityCard = identityCard.trim();
if(identityCard.length() == 15){
//校验合法性
Boolean isOk = checkIdentityCard(identityCard);
if(isOk){
/*转换开始*/
//完善年份
String card17 = identityCard.substring(0,6) + "19" + identityCard.substring(6);
//获取第18位的校验码
/*获取校验码索引的逻辑是,前提是先要得到17位的,将每一位的值乘以对应的系数,累加起来,模以11得到的*/
int sum = 0;
for (int i = 0; i < card17.length(); i++) {
sum += Integer.parseInt(card17.substring(i,i+1))*widthArr[i];
}
int checkIndex = sum % 11;
result = card17 + checkArr[checkIndex];
}
}
}
return result;
}
/**
* 根据身份证获取到身份证所在的省市/市县信息
* @param identityCard
* @return 查找到了就返回值,否则返回null
*/
public static String getAdressByIdentityCard(String identityCard){
List<String> resultList = new ArrayList<>();
if(StringUtils.isNotEmpty(identityCard)){
identityCard = identityCard.trim();
//校验身份证
Boolean isOk = checkIdentityCard(identityCard);
if(isOk){
//截取前6位
String prefixCard = identityCard.substring(0,6);
//解析配置
List<AreaNameDto> list = AreaStringUtil.parseArea();
list.stream().forEach(var -> {
Map<String, String> map = var.getMap();
if(map.containsKey(prefixCard)){
resultList.add(map.get(prefixCard));
return;
}
});
}
}
return CollectionUtils.isEmpty(resultList) ? null:resultList.get(0);
}
public static void main(String[] args) {
String card = "";
System.out.println(getAdressByIdentityCard(card));
}
}
获取省市的工具类:
package com.hf.mypractice.utils;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
/**
* @Description: 身份证前六位对应的地区处理
* @Date: 2019/3/28
* @Auther:
*/
public class AreaStringUtil {
/**
* 解析地区的正则表达式
*/
public static final String AREA_REGEX = "(\\d{6}(.){1}([\\u4e00-\\u9fa5]+))";
/**身份证前两位代表的省份/直辖市
* 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新疆维吾尔自治区;
*/
private static String[] parentCodeArr = null;
private static String[] parentNameArr = null;
private static final Map<String,String> parentMap = new HashMap<>();
static{
//获取注解上的值
Field[] fields = ProvinceCodeModel.class.getDeclaredFields();
//过滤final和static字段,并且需要有指定注解的
Arrays.stream(fields).filter((Field field) -> !Modifier.isFinal(field.getModifiers()) && !Modifier.isStatic(field.getModifiers()) && field.isAnnotationPresent(ProvinceCode.class)).forEach(var -> {
parentNameArr = var.getAnnotation(ProvinceCode.class).names();
parentCodeArr = var.getAnnotation(ProvinceCode.class).codes();
});
for (int i = 0; i < parentCodeArr.length; i++) {
parentMap.put(parentCodeArr[i],parentNameArr[i]);
}
}
/**
* 获取字段的值
* @return
*/
public static List<String> getAreaString(){
//获取该类的所有字段
Field[] fields = AreaStringUtil.class.getDeclaredFields();
List<String> list = new ArrayList<>();
Arrays.stream(fields).filter((Field field) -> !Modifier.isFinal(field.getModifiers()) && field.isAnnotationPresent(ParseString.class)).forEach(ff -> {
ff.setAccessible(true);
try {
String value = (String) ff.get(ff.getName());
list.add(value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
return list;
}
/**
* 正则解析,得到身份证前六位代号和对应的地区
* @return
*/
public static List<AreaNameDto> parseArea(){
//获取数据
List<String> list = getAreaString();
List<AreaNameDto> resultList = new ArrayList<>();
list.stream().forEach(areaString -> {
Map<String,String> map = new HashMap<>();
//正则解析
/*parseList的格式是: 110101 东城区*/
List<String> parseList = RegexUtil.matchs(areaString, AREA_REGEX, 1);
if(!CollectionUtils.isEmpty(parseList)){
parseList.stream().forEach(var -> {
String[] tempArr = var.split(" ");
Map<String, String> tempMap = new HashMap<>();
//获取前两位身份证号码
String address = "";
String shortCode = areaString.substring(0,2);
if(parentMap.containsKey(shortCode)){
address = parentMap.get(shortCode) + tempArr[1];
}
tempMap.clear();
tempMap.put(tempArr[0],address);
AreaNameDto dto = new AreaNameDto(parentMap.get(shortCode),tempMap);
resultList.add(dto);
});
}
});
return resultList;
}
public static void main(String[] args) {
List<AreaNameDto> list = parseArea();
list.stream().forEach