import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;
public class IDCardCheck {
private static int POWER[] = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
public static boolean isValidatedAllIdcard(String idcard) {
if (Objects.isNull(idcard) || idcard.length() == 0) {
return false;
} else if (idcard.length() != 18 && idcard.length() != 15) {
return false;
} else if (idcard.length() == 18) {
return IDCardCheck.validate18IDCard(idcard);
} else if (idcard.length() == 15) {
return IDCardCheck.validate15IDCard(idcard);
}
return false;
}
public static boolean validate18IDCard(String idcard) {
if (Objects.isNull(idcard)) {
return false;
}
if (idcard.length() != 18) {
return false;
}
String idcard17 = idcard.substring(0, 17);
if (!IDCardCheck.isDigital(idcard17)) {
return false;
}
String provinceid = idcard.substring(0, 2);
if (!ProvinceEnum.check(provinceid)) {
return false;
}
String birthday = idcard.substring(6, 14);
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
try {
Date birthDate = sdf.parse(birthday);
String tmpDate = sdf.format(birthDate);
if (!tmpDate.equals(birthday)) {
return false;
}
} catch (ParseException e1) {
return false;
}
String idcard18Code = idcard.substring(17, 18);
char c[] = idcard17.toCharArray();
int bit[] = IDCardCheck.converCharToInt(c);
int sum17 = IDCardCheck.getPowerSum(bit);
String checkCode = CheckCodeEnum.getCode(sum17);
if (Objects.isNull(checkCode)) {
return false;
}
if (!idcard18Code.equalsIgnoreCase(checkCode)) {
return false;
}
return true;
}
public static boolean validate15IDCard(String idcard) {
if (Objects.isNull(idcard)) {
return false;
}
if (idcard.length() != 15) {
return false;
}
if (!IDCardCheck.isDigital(idcard)) {
return false;
}
String provinceid = idcard.substring(0, 2);
if (!ProvinceEnum.check(provinceid)) {
return false;
}
String birthday = idcard.substring(6, 12);
SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
try {
Date birthDate = sdf.parse(birthday);
String tmpDate = sdf.format(birthDate);
if (!tmpDate.equals(birthday)) {
return false;
}
} catch (ParseException e1) {
return false;
}
return true;
}
public static String convertIdcarBy15bit(String idcard) {
if (Objects.isNull(idcard)) {
return null;
}
int s = 15;
if (idcard.length() != s) {
return null;
}
if (!IDCardCheck.isDigital(idcard)) {
return null;
}
String provinceid = idcard.substring(0, 2);
if (!ProvinceEnum.check(provinceid)) {
return null;
}
String birthday = idcard.substring(6, 12);
SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
Date birthdate = null;
try {
birthdate = sdf.parse(birthday);
String tmpDate = sdf.format(birthdate);
if (!tmpDate.equals(birthday)) {
return null;
}
} catch (ParseException e1) {
return null;
}
Calendar cday = Calendar.getInstance();
cday.setTime(birthdate);
String year = String.valueOf(cday.get(Calendar.YEAR));
String idcard17 = idcard.substring(0, 6) + year + idcard.substring(8);
char c[] = idcard17.toCharArray();
String checkCode = "";
int bit[] = IDCardCheck.converCharToInt(c);
int sum17 = IDCardCheck.getPowerSum(bit);
checkCode = CheckCodeEnum.valueOf("CHECK_CODE_" + sum17).code;
if (Objects.isNull(checkCode)) {
return null;
}
idcard17 += checkCode;
return idcard17;
}
enum ProvinceEnum {
北京("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"),
臺灣("71"),
香港("81"), 澳門("82"),
國外("91");
private String id;
private ProvinceEnum(String id) {
this.id = id;
}
public String getId() {
return this.id;
}
public static boolean check(String province) {
ProvinceEnum[] pes = ProvinceEnum.values();
for (ProvinceEnum pe : pes) {
if (pe.getId().equals(province)) {
return true;
}
}
return false;
}
}
enum CheckCodeEnum {
CHECK_CODE_0(0, "1"),
CHECK_CODE_1(1, "0"),
CHECK_CODE_2(2, "x"),
CHECK_CODE_3(3, "9"),
CHECK_CODE_4(4, "8"),
CHECK_CODE_5(5, "7"),
CHECK_CODE_6(6, "6"),
CHECK_CODE_7(7, "5"),
CHECK_CODE_8(8, "4"),
CHECK_CODE_9(9, "3"),
CHECK_CODE_10(10, "2");
private int modulus;
private String code;
CheckCodeEnum(int modulus, String code) {
this.modulus = modulus;
this.code = code;
}
public int getModulus() {
return this.modulus;
}
public String getCode() {
return this.code;
}
public static String getCode(int modulus) {
CheckCodeEnum checkCodeEnum = CheckCodeEnum.getCheckCodeEnum(modulus);
return checkCodeEnum.getCode();
}
public static CheckCodeEnum getCheckCodeEnum(int modulus) {
return Arrays.stream(CheckCodeEnum.values()).filter(x -> x.modulus == modulus).findFirst().orElse(null);
}
}
private static boolean isDigital(String str) {
return str.matches("^[0-9]*$");
}
private static int getPowerSum(int[] bit) {
int sum = 0;
int len = IDCardCheck.POWER.length;
if (len != bit.length) {
return sum;
}
for (int i = 0; i < bit.length; i++) {
for (int j = 0; j < len; j++) {
if (i == j) {
sum = sum + bit[i] * IDCardCheck.POWER[j];
}
}
}
return sum;
}
private static int[] converCharToInt(char[] c) throws NumberFormatException {
int[] a = new int[c.length];
int k = 0;
for (char temp : c) {
a[k++] = Integer.parseInt(String.valueOf(temp));
}
return a;
}
}