IdCard.java 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. package com.ljsd.util;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import java.text.ParseException;
  5. import java.text.SimpleDateFormat;
  6. import java.util.*;
  7. import java.util.regex.Matcher;
  8. import java.util.regex.Pattern;
  9. public class IdCard {
  10. private static final Logger LOGGER = LoggerFactory.getLogger(TimeUtil.class);
  11. public static boolean isAdult(String idStr){
  12. try {
  13. LOGGER.info("idStr:"+idStr);
  14. if (null == idStr) {// 验证非空
  15. LOGGER.info("身份证号码不能为空");
  16. return false;
  17. }
  18. if (idStr.length() != 15 && idStr.length() != 18) {// 只能是15位或者18位
  19. LOGGER.info("身份证号码长度只能是15位或者18位"+idStr);
  20. return false;
  21. }
  22. String Ai = "";
  23. if (idStr.length() == 18) {
  24. Ai = idStr.substring(0, 17);
  25. }
  26. if (idStr.length() == 15) {// 将15位身份证转换为 17位身份证,最后加上最后一位,转换为18位身份证
  27. // 15位身份证是没有校验位的,同时采用的是2位数字来表示出生年份,并且 15位的身份证号码确定都是19**年的
  28. Ai = idStr.substring(0, 6) + "19" + idStr.substring(6, 15);
  29. }
  30. if (!isNumber(Ai)) { // 验证身份证前17位是否都是数字
  31. LOGGER.info("身份证15位号码都应为数字 ; 18位号码除最后一位外,都应为数字。");
  32. return false;
  33. }
  34. int year = Integer.parseInt(Ai.substring(6, 10));// 出生年份
  35. int month = Integer.parseInt(Ai.substring(10, 12));// 出生月份
  36. int day = Integer.parseInt(Ai.substring(12, 14));// 出生日期
  37. String birthDay = year + "-" + month + "-" + day;
  38. Date birthdate = null;
  39. try {// 将出生日期转换为Date类型
  40. birthdate = new SimpleDateFormat("yyyyMMdd").parse(birthDay);
  41. } catch (ParseException e) {
  42. e.printStackTrace();
  43. LOGGER.info("身份证生日无效。");
  44. return false;
  45. }
  46. if (birthdate == null || new Date().before(birthdate)) {
  47. LOGGER.info("身份证生日无效。");
  48. return false;
  49. }
  50. GregorianCalendar gc = new GregorianCalendar();//GregorianCalendar 是 Calendar 的一个具体子类,提供了世界上大多数国家/地区使用的标准日历系统。
  51. SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
  52. // 验证生日年份是否在范围之内
  53. if ((gc.get(Calendar.YEAR) - year) > 150 || (gc.getTime().getTime() - s.parse(birthDay).getTime()) < 0) {
  54. LOGGER.info("身份证生日不在有效范围。");
  55. return false;
  56. }
  57. //验证月份
  58. if (month > 12 || month <= 0) {
  59. LOGGER.info("身份证号中的月份无效");
  60. return false;
  61. }
  62. //验证日期
  63. gc.setTime(birthdate);
  64. boolean mflag = false;
  65. switch (month) {
  66. case 1:
  67. case 3:
  68. case 5:
  69. case 7:
  70. case 8:
  71. case 10:
  72. case 12:
  73. mflag = (day >= 1 && day <= 31);
  74. break;
  75. case 2: // 公历的2月非闰年有28天,闰年的2月是29天。
  76. if (gc.isLeapYear(gc.get(Calendar.YEAR))) {
  77. mflag = (day >= 1 && day <= 29);
  78. } else {
  79. mflag = (day >= 1 && day <= 28);
  80. }
  81. break;
  82. case 4:
  83. case 6:
  84. case 9:
  85. case 11:
  86. mflag = (day >= 1 && day <= 30);
  87. break;
  88. }
  89. if (!mflag) {// 日期不对
  90. LOGGER.info("省份证号中的出生日期不对");
  91. return false;
  92. }
  93. // 验证 开头两位数是否是真实有效的地区编码
  94. if (cityCodeMap.get(Ai.substring(0, 2)) == null) {
  95. LOGGER.info("身份证地区编码错误。");
  96. return false;
  97. }
  98. int TotalmulAiWi = 0;
  99. for (int i = 0; i < 17; i++) {//先对前17位数字的权求和 ,使用十七位数字本体码加权求和公式 S = Sum(Ai * Wi)
  100. TotalmulAiWi = TotalmulAiWi + Integer.parseInt(String.valueOf(Ai.charAt(i))) * Integer.parseInt(Wi[i]);
  101. }
  102. int modValue = TotalmulAiWi % 11;//计算模 Y = mod(S, 11) 用计算出来的结果除以11,这样就会出现
  103. String strVerifyCode = ValCodeArr[modValue]; // 获取最后一位的校验码字符值
  104. Ai = Ai + strVerifyCode; // 17位身份证 加上最后以为验证数字 得到18位有效的身份证号
  105. if (!idStr.toUpperCase().equals(Ai.toUpperCase())) {// 判断传过来的身份证号 和 计算得到的身份证号是否相同
  106. LOGGER.info(idStr.toUpperCase()+"身份证号码不对"+Ai.toUpperCase());
  107. return false;
  108. }
  109. LOGGER.info("正确");
  110. if(getAgeByBirthday(birthdate)<18){
  111. LOGGER.info("未满18岁");
  112. return false;
  113. }else{
  114. return true;
  115. }
  116. } catch (Exception e) {
  117. LOGGER.info("验证出错");
  118. e.printStackTrace();
  119. return false;
  120. }
  121. }
  122. private static boolean isNumber(String str) {
  123. Pattern pattern = Pattern.compile("[0-9]*");
  124. Matcher isNum = pattern.matcher(str);
  125. return isNum.matches();
  126. }
  127. private static Map<String, String> cityCodeMap = new HashMap<String, String>() {
  128. {
  129. this.put("11", "北京");
  130. this.put("12", "天津");
  131. this.put("13", "河北");
  132. this.put("14", "山西");
  133. this.put("15", "内蒙古");
  134. this.put("21", "辽宁");
  135. this.put("22", "吉林");
  136. this.put("23", "黑龙江");
  137. this.put("31", "上海");
  138. this.put("32", "江苏");
  139. this.put("33", "浙江");
  140. this.put("34", "安徽");
  141. this.put("35", "福建");
  142. this.put("36", "江西");
  143. this.put("37", "山东");
  144. this.put("41", "河南");
  145. this.put("42", "湖北");
  146. this.put("43", "湖南");
  147. this.put("44", "广东");
  148. this.put("45", "广西");
  149. this.put("46", "海南");
  150. this.put("50", "重庆");
  151. this.put("51", "四川");
  152. this.put("52", "贵州");
  153. this.put("53", "云南");
  154. this.put("54", "西藏");
  155. this.put("61", "陕西");
  156. this.put("62", "甘肃");
  157. this.put("63", "青海");
  158. this.put("64", "宁夏");
  159. this.put("65", "新疆");
  160. this.put("71", "台湾");
  161. this.put("81", "香港");
  162. this.put("82", "澳门");
  163. this.put("91", "国外");
  164. }
  165. };
  166. static String[] ValCodeArr = { "1", "0", "x", "9", "8", "7", "6", "5", "4","3", "2" }; //最后一位的校验码字符值
  167. static String[] Wi = { "7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7","9", "10", "5", "8", "4", "2" };//十七位数字
  168. public static int getAgeByBirthday(Date birthday) {
  169. Calendar cal = Calendar.getInstance();
  170. if (cal.before(birthday)) {
  171. throw new IllegalArgumentException(
  172. "The birthDay is before Now.It's unbelievable!");
  173. }
  174. int yearNow = cal.get(Calendar.YEAR);
  175. int monthNow = cal.get(Calendar.MONTH) + 1;
  176. int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);
  177. cal.setTime(birthday);
  178. int yearBirth = cal.get(Calendar.YEAR);
  179. int monthBirth = cal.get(Calendar.MONTH) + 1;
  180. int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
  181. int age = yearNow - yearBirth;
  182. if (monthNow <= monthBirth) {
  183. if (monthNow == monthBirth) {
  184. // monthNow==monthBirth
  185. if (dayOfMonthNow < dayOfMonthBirth) {
  186. age--;
  187. }
  188. } else {
  189. // monthNow>monthBirth
  190. age--;
  191. }
  192. }
  193. return age;
  194. }
  195. }