|
@@ -0,0 +1,366 @@
|
|
|
|
|
+package com.jzg.commons.util;
|
|
|
|
|
+
|
|
|
|
|
+import java.text.ParseException;
|
|
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
+import java.util.regex.Matcher;
|
|
|
|
|
+import java.util.regex.Pattern;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * @description: todo
|
|
|
|
|
+ * @author: shenwd
|
|
|
|
|
+ * @date: 2025/3/3 17:35
|
|
|
|
|
+ **/
|
|
|
|
|
+public class IDCardUtils {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 身份证号码合法性校验。
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return boolean
|
|
|
|
|
+ * @author: aidy
|
|
|
|
|
+ */
|
|
|
|
|
+ public static boolean idCardValidate(String idStr) {
|
|
|
|
|
+ String errorInfo = null;// 记录错误信息
|
|
|
|
|
+ String[] ValCodeArr = {"1", "0", "x", "9", "8", "7", "6", "5", "4", "3", "2"};
|
|
|
|
|
+ String[] Wi = {"7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2"};
|
|
|
|
|
+ // String[] Checker = {"1","9","8","7","6","5","4","3","2","1","1"};
|
|
|
|
|
+ String ai = "";
|
|
|
|
|
+ if (StringUtils.isEmpty(idStr)) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ } else {
|
|
|
|
|
+
|
|
|
|
|
+ if (idStr.length() != 15 && idStr.length() != 18) {
|
|
|
|
|
+ errorInfo = "号码长度应该为15位或18位。";
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ================ 数字 除最后一位都为数字 ================
|
|
|
|
|
+ if (idStr.length() == 18) {
|
|
|
|
|
+ ai = idStr.substring(0, 17);
|
|
|
|
|
+ } else if (idStr.length() == 15) {
|
|
|
|
|
+ ai = idStr.substring(0, 6) + "19" + idStr.substring(6, 15);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (isNumeric(ai) == false) {
|
|
|
|
|
+ errorInfo = "15位号码都应为数字 ; 18位号码除最后一位外,都应为数字。";
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ // =======================(end)========================
|
|
|
|
|
+
|
|
|
|
|
+ // ================ 出生年月是否有效 ================
|
|
|
|
|
+ String strYear = ai.substring(6, 10);// 年份
|
|
|
|
|
+ String strMonth = ai.substring(10, 12);// 月份
|
|
|
|
|
+ String strDay = ai.substring(12, 14);// 月份
|
|
|
|
|
+ String birthday = ai.substring(6, 14);
|
|
|
|
|
+
|
|
|
|
|
+ if (!isDate(birthday)) {
|
|
|
|
|
+ errorInfo = "生日无效。";
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ GregorianCalendar gc = new GregorianCalendar();
|
|
|
|
|
+ SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
|
|
|
|
|
+ try {
|
|
|
|
|
+ if ((gc.get(Calendar.YEAR) - Integer.parseInt(strYear)) > 150
|
|
|
|
|
+ || (gc.getTime().getTime() - s.parse(strYear + "-" + strMonth + "-" + strDay).getTime()) < 0) {
|
|
|
|
|
+ errorInfo = "生日不在有效范围。";
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ return false;
|
|
|
|
|
+ } catch (ParseException e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (Integer.parseInt(strMonth) > 12 || Integer.parseInt(strMonth) == 0) {
|
|
|
|
|
+ errorInfo = "月份无效";
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (Integer.parseInt(strDay) > 31 || Integer.parseInt(strDay) == 0) {
|
|
|
|
|
+ errorInfo = "日期无效";
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ // =====================(end)=====================
|
|
|
|
|
+
|
|
|
|
|
+ // ================ 地区码时候有效 ================
|
|
|
|
|
+ Hashtable<String, String> h = GetAreaCode();
|
|
|
|
|
+ if (h.get(ai.substring(0, 2)) == null) {
|
|
|
|
|
+ errorInfo = "地区编码错误。";
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ // ==============================================
|
|
|
|
|
+
|
|
|
|
|
+ // ================ 判断最后一位的值 ================
|
|
|
|
|
+ int totalmulAiWi = 0;
|
|
|
|
|
+ for (int i = 0; i < 17; i++) {
|
|
|
|
|
+ totalmulAiWi = totalmulAiWi + Integer.parseInt(String.valueOf(ai.charAt(i))) * Integer.parseInt(Wi[i]);
|
|
|
|
|
+ }
|
|
|
|
|
+ int modValue = totalmulAiWi % 11;
|
|
|
|
|
+ String strVerifyCode = ValCodeArr[modValue];
|
|
|
|
|
+ ai = ai + strVerifyCode;
|
|
|
|
|
+
|
|
|
|
|
+ if (idStr.length() == 18) {
|
|
|
|
|
+ if (ai.equalsIgnoreCase(idStr) == false) {
|
|
|
|
|
+ errorInfo = "身份证无效,最后一位字母错误";
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // System.out.println("所在地区:" + h.get(ai.substring(0, 2).toString()));
|
|
|
|
|
+ // System.out.println("新身份证号:" + ai);
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ // =====================(end)=====================
|
|
|
|
|
+
|
|
|
|
|
+ if (StringUtils.isEmpty(errorInfo)) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 判断字符串是否为数字
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return boolean
|
|
|
|
|
+ * @author: aidy
|
|
|
|
|
+ */
|
|
|
|
|
+ private static boolean isNumeric(String str) {
|
|
|
|
|
+ Pattern pattern = Pattern.compile("[0-9]*");
|
|
|
|
|
+ Matcher isNum = pattern.matcher(str);
|
|
|
|
|
+ if (isNum.matches()) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ /**//*
|
|
|
|
|
+ * 判断一个字符时候为数字 if(Character.isDigit(str.charAt(0))) { return true; }
|
|
|
|
|
+ * else { return false; }
|
|
|
|
|
+ */
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 判断字符串是否为日期格式
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return boolean
|
|
|
|
|
+ * @author: aidy
|
|
|
|
|
+ */
|
|
|
|
|
+ public static boolean isDate(String strDate) {
|
|
|
|
|
+ String DatePattern = "^(?:([0-9]{4}(?:(?:0?[1,3-9]|1[0-2])(?:29|30)|((?:0?[13578]|1[02])-31)))|"
|
|
|
|
|
+ + "([0-9]{4}(?:0?[1-9]|1[0-2])(?:0?[1-9]|1\\d|2[0-8]))|"
|
|
|
|
|
+ + "(((?:(\\d\\d(?:0[48]|[2468][048]|[13579][26]))|"
|
|
|
|
|
+ + "(?:0[48]00|[2468][048]00|[13579][26]00))0?229)))$";
|
|
|
|
|
+ Pattern pattern = Pattern.compile(DatePattern);
|
|
|
|
|
+ Matcher m = pattern.matcher(strDate);
|
|
|
|
|
+ if (m.matches()) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 在判定已经是正确的身份证号码之后,查找出身份证所在地区。
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return String
|
|
|
|
|
+ * @author: aidy
|
|
|
|
|
+ */
|
|
|
|
|
+ public String GetArea(String idCard) {
|
|
|
|
|
+ Hashtable<String, String> ht = GetAreaCode();
|
|
|
|
|
+ String area = ht.get(idCard.substring(0, 2));
|
|
|
|
|
+ return area;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 在判定已经是正确的身份证号码之后,查找出此人性别(1:男;2:女)。
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return String
|
|
|
|
|
+ * @author: aidy
|
|
|
|
|
+ */
|
|
|
|
|
+ public static String GetSex(String idCard) {
|
|
|
|
|
+ String sex = "";
|
|
|
|
|
+ if (idCard.length() == 15)
|
|
|
|
|
+ sex = idCard.substring(idCard.length() - 3, idCard.length());
|
|
|
|
|
+
|
|
|
|
|
+ if (idCard.length() == 18)
|
|
|
|
|
+ sex = idCard.substring(idCard.length() - 4, idCard.length() - 1);
|
|
|
|
|
+
|
|
|
|
|
+ // System.out.println(sex);
|
|
|
|
|
+ int sexNum = Integer.parseInt(sex) % 2;
|
|
|
|
|
+ if (sexNum == 0) {
|
|
|
|
|
+ return "FEMALE";
|
|
|
|
|
+ }
|
|
|
|
|
+ return "MALE";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <p> 永诚使用返回对应编码
|
|
|
|
|
+ * 在判定已经是正确的身份证号码之后,查找出此人性别(1:男;2:女)。
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return String
|
|
|
|
|
+ * @author: aidy
|
|
|
|
|
+ */
|
|
|
|
|
+ public static String GetYcSex(String idCard) {
|
|
|
|
|
+ String sex = "";
|
|
|
|
|
+ if (idCard.length() == 15)
|
|
|
|
|
+ sex = idCard.substring(idCard.length() - 3, idCard.length());
|
|
|
|
|
+
|
|
|
|
|
+ if (idCard.length() == 18)
|
|
|
|
|
+ sex = idCard.substring(idCard.length() - 4, idCard.length() - 1);
|
|
|
|
|
+
|
|
|
|
|
+ // System.out.println(sex);
|
|
|
|
|
+ int sexNum = Integer.parseInt(sex) % 2;
|
|
|
|
|
+ if (sexNum == 0) {
|
|
|
|
|
+ return "106002";
|
|
|
|
|
+ }
|
|
|
|
|
+ return "106001";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 在判定已经是正确的身份证号码之后,查找出此人出生日期
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return String
|
|
|
|
|
+ * @author: aidy
|
|
|
|
|
+ */
|
|
|
|
|
+ public static String GetBirthday(String idCard) {
|
|
|
|
|
+ String Ain = "";
|
|
|
|
|
+ if (idCard.length() == 18) {
|
|
|
|
|
+ Ain = idCard.substring(0, 17);
|
|
|
|
|
+ } else if (idCard.length() == 15) {
|
|
|
|
|
+ Ain = idCard.substring(0, 6) + "19" + idCard.substring(6, 15);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // ================ 出生年月是否有效 ================
|
|
|
|
|
+ String strYear = Ain.substring(6, 10);// 年份
|
|
|
|
|
+ String strMonth = Ain.substring(10, 12);// 月份
|
|
|
|
|
+ String strDay = Ain.substring(12, 14);// 日期
|
|
|
|
|
+ return strYear + "-" + strMonth + "-" + strDay;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 在判定已经是正确的身份证号码之后,查找出此人年龄
|
|
|
|
|
+ * @param idCard
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ public static int getAgeFromIDCard(String idCard) {
|
|
|
|
|
+ String birthday = idCard.substring(6, 14);
|
|
|
|
|
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
|
|
|
|
|
+ try {
|
|
|
|
|
+ Date birthDate = dateFormat.parse(birthday);
|
|
|
|
|
+ Calendar calendar = Calendar.getInstance();
|
|
|
|
|
+ calendar.setTime(birthDate);
|
|
|
|
|
+ Calendar now = Calendar.getInstance();
|
|
|
|
|
+ int age = now.get(Calendar.YEAR) - calendar.get(Calendar.YEAR);
|
|
|
|
|
+ if (now.get(Calendar.MONTH) < calendar.get(Calendar.MONTH)
|
|
|
|
|
+ || (now.get(Calendar.MONTH) == calendar.get(Calendar.MONTH)
|
|
|
|
|
+ && now.get(Calendar.DAY_OF_MONTH) < calendar.get(Calendar.DAY_OF_MONTH))) {
|
|
|
|
|
+ age--;
|
|
|
|
|
+ }
|
|
|
|
|
+ return age;
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ }
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 设置地区编码
|
|
|
|
|
+ *
|
|
|
|
|
+ * @return Hashtable
|
|
|
|
|
+ * @author: aidy
|
|
|
|
|
+ */
|
|
|
|
|
+ private static Hashtable<String, String> GetAreaCode() {
|
|
|
|
|
+ Hashtable<String, String> hashtable = new Hashtable<String, String>();
|
|
|
|
|
+ hashtable.put("11", "北京");
|
|
|
|
|
+ hashtable.put("12", "天津");
|
|
|
|
|
+ hashtable.put("13", "河北");
|
|
|
|
|
+ hashtable.put("14", "山西");
|
|
|
|
|
+ hashtable.put("15", "内蒙古");
|
|
|
|
|
+ hashtable.put("21", "辽宁");
|
|
|
|
|
+ hashtable.put("22", "吉林");
|
|
|
|
|
+ hashtable.put("23", "黑龙江");
|
|
|
|
|
+ hashtable.put("31", "上海");
|
|
|
|
|
+ hashtable.put("32", "江苏");
|
|
|
|
|
+ hashtable.put("33", "浙江");
|
|
|
|
|
+ hashtable.put("34", "安徽");
|
|
|
|
|
+ hashtable.put("35", "福建");
|
|
|
|
|
+ hashtable.put("36", "江西");
|
|
|
|
|
+ hashtable.put("37", "山东");
|
|
|
|
|
+ hashtable.put("41", "河南");
|
|
|
|
|
+ hashtable.put("42", "湖北");
|
|
|
|
|
+ hashtable.put("43", "湖南");
|
|
|
|
|
+ hashtable.put("44", "广东");
|
|
|
|
|
+ hashtable.put("45", "广西");
|
|
|
|
|
+ hashtable.put("46", "海南");
|
|
|
|
|
+ hashtable.put("50", "重庆");
|
|
|
|
|
+ hashtable.put("51", "四川");
|
|
|
|
|
+ hashtable.put("52", "贵州");
|
|
|
|
|
+ hashtable.put("53", "云南");
|
|
|
|
|
+ hashtable.put("54", "西藏");
|
|
|
|
|
+ hashtable.put("61", "陕西");
|
|
|
|
|
+ hashtable.put("62", "甘肃");
|
|
|
|
|
+ hashtable.put("63", "青海");
|
|
|
|
|
+ hashtable.put("64", "宁夏");
|
|
|
|
|
+ hashtable.put("65", "新疆");
|
|
|
|
|
+ hashtable.put("71", "台湾");
|
|
|
|
|
+ hashtable.put("81", "香港");
|
|
|
|
|
+ hashtable.put("82", "澳门");
|
|
|
|
|
+ hashtable.put("91", "国外");
|
|
|
|
|
+ return hashtable;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 根据身份证地址提取省市区工具类
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param address
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ public static Map<String, String> addressResolution(String address) {
|
|
|
|
|
+ String regex = "(?<province>[^省]+自治区|.*?省|.*?行政区|.*?市|.*?蒙古)(?<city>[^市]+自治州|.*?地区|.*?行政单位|.+盟|市辖区|.*?市|.*?县|.*?区)(?<district>[^县]+县|.*?区|.+市|.*?旗|.+海域|.+岛)?(?<town>[^区]+区|.+镇)?(?<detail>.*)";
|
|
|
|
|
+
|
|
|
|
|
+// if(address.indexOf("重庆市") == 0 || address.indexOf("上海市") == 0){
|
|
|
|
|
+// regex = "(?<province>[^市].*?市)(?<city>[^县]+县|.*?区|.+市|.*?旗|.+海域|.+岛)(?<district>[^县]+县|.*?区|.+市|.*?旗|.+海域|.+岛)?(?<town>[^区]+区|.+镇)?(?<detail>.*)";
|
|
|
|
|
+// }
|
|
|
|
|
+ if(address.indexOf("新疆") == 0){
|
|
|
|
|
+ regex = "(?<province>.*?新疆)(?<city>[^县]+县|.*?区|.+市|.*?旗|.+海域|.+岛)(?<district>[^县]+县|.*?区|.+市|.*?旗|.+海域|.+岛)?(?<town>[^区]+区|.+镇)?(?<detail>.*)";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Matcher m = Pattern.compile(regex).matcher(address);
|
|
|
|
|
+ String province = null, city = null, district = null, town = null, detail = null;
|
|
|
|
|
+// List<Map<String, String>> table = new ArrayList<Map<String, String>>();
|
|
|
|
|
+ Map<String, String> row = null;
|
|
|
|
|
+ while (m.find()) {
|
|
|
|
|
+ row = new LinkedHashMap<String, String>();
|
|
|
|
|
+ province = m.group("province");
|
|
|
|
|
+ row.put("province", province == null ? "" : province.trim());
|
|
|
|
|
+ city = m.group("city");
|
|
|
|
|
+ row.put("city", city == null ? "" : city.trim());
|
|
|
|
|
+ district = m.group("district");
|
|
|
|
|
+ row.put("district", district == null ? "" : district.trim());
|
|
|
|
|
+ town = m.group("town");
|
|
|
|
|
+ row.put("town", town == null ? "" : town.trim());
|
|
|
|
|
+ detail = m.group("detail");
|
|
|
|
|
+ row.put("detail", detail == null ? "" : detail.trim());
|
|
|
|
|
+// table.add(row);
|
|
|
|
|
+ }
|
|
|
|
|
+// return table;
|
|
|
|
|
+ return row;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public static void main(String[] args) throws ParseException {
|
|
|
|
|
+ Map m = addressResolution("陕西省旬阳县赤岩镇闵家河村三组109号");
|
|
|
|
|
+ String IDCardNum = "43282219381105414X";
|
|
|
|
|
+ }
|
|
|
|
|
+}
|