|
@@ -6,6 +6,8 @@ import java.text.ParseException;
|
|
|
import java.text.SimpleDateFormat;
|
|
|
import java.util.Calendar;
|
|
|
import java.util.Date;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
|
|
|
/**
|
|
|
* @description: IdCard functions
|
|
@@ -20,6 +22,48 @@ public class IdCardUtil {
|
|
|
private static final int[] POWER = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
|
|
|
private static final int MAX_LENGTH = 18;
|
|
|
private static final int MIN_LENGTH = 15;
|
|
|
+ /** 台湾身份首字母对应数字 */
|
|
|
+ public static Map<String, Integer> twFirstCode = new HashMap<>();
|
|
|
+ /** 香港身份首字母对应数字 */
|
|
|
+ public static Map<String, Integer> hkFirstCode = new HashMap<>();
|
|
|
+ static {
|
|
|
+ twFirstCode.put("A", 10);
|
|
|
+ twFirstCode.put("B", 11);
|
|
|
+ twFirstCode.put("C", 12);
|
|
|
+ twFirstCode.put("D", 13);
|
|
|
+ twFirstCode.put("E", 14);
|
|
|
+ twFirstCode.put("F", 15);
|
|
|
+ twFirstCode.put("G", 16);
|
|
|
+ twFirstCode.put("H", 17);
|
|
|
+ twFirstCode.put("J", 18);
|
|
|
+ twFirstCode.put("K", 19);
|
|
|
+ twFirstCode.put("L", 20);
|
|
|
+ twFirstCode.put("M", 21);
|
|
|
+ twFirstCode.put("N", 22);
|
|
|
+ twFirstCode.put("P", 23);
|
|
|
+ twFirstCode.put("Q", 24);
|
|
|
+ twFirstCode.put("R", 25);
|
|
|
+ twFirstCode.put("S", 26);
|
|
|
+ twFirstCode.put("T", 27);
|
|
|
+ twFirstCode.put("U", 28);
|
|
|
+ twFirstCode.put("V", 29);
|
|
|
+ twFirstCode.put("X", 30);
|
|
|
+ twFirstCode.put("Y", 31);
|
|
|
+ twFirstCode.put("W", 32);
|
|
|
+ twFirstCode.put("Z", 33);
|
|
|
+ twFirstCode.put("I", 34);
|
|
|
+ twFirstCode.put("O", 35);
|
|
|
+ hkFirstCode.put("A", 1);
|
|
|
+ hkFirstCode.put("B", 2);
|
|
|
+ hkFirstCode.put("C", 3);
|
|
|
+ hkFirstCode.put("R", 18);
|
|
|
+ hkFirstCode.put("U", 21);
|
|
|
+ hkFirstCode.put("Z", 26);
|
|
|
+ hkFirstCode.put("X", 24);
|
|
|
+ hkFirstCode.put("W", 23);
|
|
|
+ hkFirstCode.put("O", 15);
|
|
|
+ hkFirstCode.put("N", 14);
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
* 验证所有的身份证的合法性
|
|
@@ -34,13 +78,10 @@ public class IdCardUtil {
|
|
|
if (StringUtil.isBlank(idCard)) {
|
|
|
return false;
|
|
|
}
|
|
|
- if (idCard.startsWith("R")) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- return isValidate18IdCard(idCard);
|
|
|
+ return validateIdCard18(idCard) || validateIdCard10(idCard);
|
|
|
}
|
|
|
|
|
|
- private static boolean isValidate18IdCard(String idCard) {
|
|
|
+ private static boolean validateIdCard18(String idCard) {
|
|
|
// 非18位为假
|
|
|
if (idCard.length() != MAX_LENGTH) {
|
|
|
return false;
|
|
@@ -230,4 +271,98 @@ public class IdCardUtil {
|
|
|
}
|
|
|
return --age;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证10位身份证编码是否合法
|
|
|
+ */
|
|
|
+ private static boolean validateIdCard10(String idCard) {
|
|
|
+ String card = idCard.replaceAll("\\(", "").replaceAll("\\)", "");
|
|
|
+ if (card.length() != 8 && card.length() != 9 && idCard.length() != 10) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (idCard.matches("^[A-Z]{1,2}[0-9]{6}\\(?[0-9A]\\)?$")) { // 香港
|
|
|
+ return validateHKCard(idCard);
|
|
|
+ }
|
|
|
+ if (idCard.matches("^[1|5|7][0-9]{6}\\(?[0-9A-Z]\\)?$")) { // 澳门,目前没做校验,澳门的直接返回true
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (idCard.matches("^[a-zA-Z][0-9]{9}")) { // 台湾
|
|
|
+ String char2 = idCard.substring(1, 2);
|
|
|
+ if (!char2.equals("1") && !char2.equals("2")) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return validateTWCard(idCard);
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证台湾身份证号码
|
|
|
+ * 共10位
|
|
|
+ * 计算校验码的步骤:1、英文转成数字,其个位数字*9+十位数
|
|
|
+ * 2、中间八位数字,各数字从左到右依次乘以8、7、6、5....2、1
|
|
|
+ * 3、计算步骤1和2的和sum
|
|
|
+ * 4、计算10-sum%10 ,其结果就是检查码,若余数为0,则检查码就是0
|
|
|
+ * @param idCard
|
|
|
+ * 身份证号码
|
|
|
+ * @return 验证码是否符合
|
|
|
+ */
|
|
|
+ private static boolean validateTWCard(String idCard) {
|
|
|
+ //第一位是字母(表示地区代码),通过map找到对应的数字代码
|
|
|
+ String start = idCard.substring(0, 1);
|
|
|
+ //第二位数字表示性别,男生为1,女生为2
|
|
|
+ String mid = idCard.substring(1, 9);
|
|
|
+ //最后一位是检查码,由第一位和8个数字的组合计算得到校验和
|
|
|
+ String end = idCard.substring(9, 10);
|
|
|
+ Integer iStart = twFirstCode.get(start);
|
|
|
+
|
|
|
+ int sum = iStart / 10 + (iStart % 10) * 9;
|
|
|
+ char[] chars = mid.toCharArray();
|
|
|
+ int iflag = 8;
|
|
|
+ for (char c : chars) {
|
|
|
+ sum = sum + Integer.parseInt(c + "") * iflag;
|
|
|
+ iflag--;
|
|
|
+ }
|
|
|
+ return (sum % 10 == 0 ? 0 : (10 - sum % 10)) == Integer.parseInt(end);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 验证香港身份证号码(存在Bug,部份特殊身份证无法检查)
|
|
|
+ *
|
|
|
+ * 如:身份证号码是:C668668(9)
|
|
|
+ * 香港身份证号码由三部分组成:一个英文字母;6个数字;括号及0-9中的任一个数字,或者字母A。
|
|
|
+ * 括号中的数字或字母A,是校验码,用于检验括号前面的号码的逻辑正确性。
|
|
|
+ *
|
|
|
+ * 身份证前2位为英文字符,如果只出现一个英文字符则表示第一位是空格,对应数字58, 前2位英文字符A-Z分别对应数字10-35
|
|
|
+ * 最后一位校验码为0-9的数字加上字符"A","A"代表10
|
|
|
+ * 将身份证号码全部转换为数字,分别对应乘9、8...1相加的总和,整除11则证件号码有效
|
|
|
+ *
|
|
|
+ * @param idCard
|
|
|
+ * 身份证号码
|
|
|
+ * @return 验证码是否符合
|
|
|
+ */
|
|
|
+ private static boolean validateHKCard(String idCard) {
|
|
|
+ String card = idCard.replaceAll("\\(", "").replaceAll("\\)", "");
|
|
|
+ int sum = 0;
|
|
|
+ if (card.length() == 9) {
|
|
|
+ sum = ((int) card.charAt(0) - 55) * 9 + ((int) card.charAt(1) - 55) * 8;
|
|
|
+ card = card.substring(1, 9);
|
|
|
+ } else {
|
|
|
+ sum = 522 + ((int) card.charAt(0) - 55) * 8;
|
|
|
+ }
|
|
|
+ String mid = card.substring(1, 7);
|
|
|
+ String end = card.substring(7, 8);
|
|
|
+ char[] chars = mid.toCharArray();
|
|
|
+ int iflag = 7;
|
|
|
+ for (char c : chars) {
|
|
|
+ sum = sum + Integer.parseInt(c + "") * iflag;
|
|
|
+ iflag--;
|
|
|
+ }
|
|
|
+ if (end.equalsIgnoreCase("A")) {
|
|
|
+ sum = sum + 10;
|
|
|
+ } else {
|
|
|
+ sum = sum + Integer.parseInt(end);
|
|
|
+ }
|
|
|
+ return sum % 11 == 0;
|
|
|
+ }
|
|
|
}
|