根据身份证号百度百科介绍的计算方法 来校验身份证号的合法性
计算方法
1、将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。
2、将这17位数字和系数相乘的结果相加。
3、用加出来和除以11,看余数是多少?
4、余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字。其分别对应的最后一位身份证的号码为1-0-X -9-8-7-6-5-4-3-2。(即余数0对应1,余数1对应0,余数2对应X...)
5、通过上面得知如果余数是3,就会在身份证的第18位数字上出现的是9。如果对应的数字是2,身份证的最后一位号码就是罗马数字X。
例如:某男性的身份证号码为【53010219200508011X】, 我们看看这个身份证是不是符合计算规则的身份证。
首先我们得出前17位的乘积和【(5*7)+(3*9)+(0*10)+(1*5)+(0*8)+(2*4)+(1*2)+(9*1)+(2*6)+(0*3)+(0*7)+(5*9)+(0*10)+(8*5)+(0*8)+(1*4)+(1*2)】是189,然后用189除以11得出的结果是189÷11=17余下2,187÷11=17,还剩下2不能被除尽,也就是说其余数是2。最后通过对应规则就可以知道余数2对应的检验码是X。所以,可以判定这是一个正确的身份证号码。
一 长度为18位的身份证
//身份证长度
private static final int ID_CARD_LENGTH_18 = 18;
//身份证 正则表达式
private static final String REGEX_ID_CARD = "(^\\d{18}$)|(^\\d{17}(\\d|X|x)$)";
//身份证 加权因子
private static int[] Wi = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1};
// 身份证验证位值.10代表X
private static int[] ValideCode = {1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2};
/**
* 目前只验证18位身份证
* @param idCard 身份证号
* @return
*/
public static boolean idCardValidate(String idCard) {
if (TextUtils.isEmpty(idCard) ) return false;
idCard = deleteWhitespace(idCard.trim());//去除中间和两端空格
if (idCard.length() != ID_CARD_LENGTH_18 || !Pattern.matches(REGEX_ID_CARD, idCard)) return false;
List<String> charList = new ArrayList<>();
String[] splitArr = idCard.split(""); // 得到身份证数组,首位可能是空字符串
for (int i = 0; i < splitArr.length; i++) { //过滤空字符串
if (!TextUtils.isEmpty(splitArr[i])) {
charList.add(splitArr[i]);
}
}
String[] idCardArr = new String[charList.size()];
charList.toArray(idCardArr);
if (isValidityBrithBy18IdCard(idCard) && isTrueValidateCodeBy18IdCard(idCardArr)) {
return true;
}
return false;
}
/**
* 验证18位数身份证号码中的生日是否是有效生日
*
* @param idCard18 18位身份证字符串
* @return
*/
public static boolean isValidityBrithBy18IdCard(String idCard18) {
if (TextUtils.isEmpty(idCard18) || idCard18.length() < ID_CARD_LENGTH_18) return false;
String year = idCard18.substring(6, 10);
String month = idCard18.substring(10, 12);
String day = idCard18.substring(12, 14);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, parseInt(year));
calendar.set(Calendar.MONTH, parseInt(month) - 1);
calendar.set(Calendar.DATE, parseInt(day));
// 这里用getFullYear()获取年份,避免千年虫问题
if (calendar.get(Calendar.YEAR) != parseInt(year)
|| calendar.get(Calendar.MONTH) != parseInt(month) - 1
|| calendar.get(Calendar.DATE) != parseInt(day)) {
return false;
}
return true;
}
/**
* 判断身份证号码为18位时最后的验证位是否正确
*
* @param idCardArr 身份证号码切分数组
* @return
*/
public static boolean isTrueValidateCodeBy18IdCard(String[] idCardArr) {
if (idCardArr == null || idCardArr.length < ID_CARD_LENGTH_18) return false;
int sum = 0; // 声明加权求和变量
if (idCardArr[17] != null && idCardArr[17].equalsIgnoreCase("x")) {
idCardArr[17] = "10"; // 将最后位为x的验证码替换为10方便后续操作
}
for (int i = 0; i < 17; i++) {
sum += Wi[i] * parseInt(idCardArr[i]); // 加权求和
}
int valCodePosition = sum % 11; // 得到验证码所位置
if (parseInt(idCardArr[17]) == ValideCode[valCodePosition]) {
return true;
}
return false;
}
/**
* 去除字符串空格
* @param str
* @return
*/
public static String deleteWhitespace(String str) {
if (TextUtils.isEmpty(str)) return str;
int sz = str.length();
char[] chs = new char[sz];
int count = 0;
for (int i = 0; i < sz; i++) {
if (!Character.isWhitespace(str.charAt(i))) {
chs[(count++)] = str.charAt(i);
}
}
if (count == sz) {
return str;
}
return new String(chs, 0, count);
}
public static int parseInt(String strInt) {
try {
return Integer.parseInt(strInt);
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
二 长度为15位的身份证
15位身份证不用加权因子计算规则,只判断生日是否有效即可;
结合上面idCardValidate方法可以把15位的身份证校验写出
/**
* 验证15位数身份证号码中的生日是否是有效生日
*
* @param idCard15 15位身份证字符串
*/
public static boolean isValidityBrithBy15IdCard(String idCard15) {
String year = idCard15.substring(6, 8);
String month = idCard15.substring(8, 10);
String day = idCard15.substring(10, 12);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, parseInt(year));
calendar.set(Calendar.MONTH, parseInt(month) - 1);
calendar.set(Calendar.DATE, parseInt(day));
if (calendar.get(Calendar.YEAR) != parseInt(year)
|| calendar.get(Calendar.MONTH) != parseInt(month) - 1
|| calendar.get(Calendar.DATE) != parseInt(day)) {
return false;
}
return true;
}
三 香港身份证
/**
* 香港身份证
* @param k
* @return
*/
public static boolean hkIDCard(String k) {
if (!Pattern.matches("^[A-Za-z]\\d{6}(\\(\\d\\)|\\d)$", k)) {
return false;
}
//if (!/^[A-Za-z]\d{6}(\(\d\)|\d)$/.test(k)) { return false; }
k = k.toUpperCase().replace("(", "").replace(")", "");
int num1 = k.charAt(0) - 64;
String[] karr = k.split("");
int t = num1 * 8;//+ Number(karr[1]) * 7
for (int i = 7; i > 1; i--) {
t += parseInt(karr[8 - i]) * i;
}
int jc = t % 11;
if (jc == 1) {
jc = 'A';
} else if (jc > 1) {
jc = 11 - jc;
}
return jc == parseInt(karr[7]);
}
四 澳门身份证
/**
* 澳门身份证
* @param k
* @return
*/
public static boolean mcIDCard(String k) {
return Pattern.matches("^[157]\\d{6}(\\(\\d\\)|\\d)$", k);
}
身份证号校验总结
/**
* 验证18位身份证
* @param card 身份证号
* @return
*/
public static boolean isCommIdCard(String card) {
return (idCardValidate(card) || hkIDCard(card) || mcIDCard(card));
}
五 邮箱校验
邮箱最长30位,必须包含@和.
private static final String REGEX_EMAIL = "^[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?$";
//邮箱
public static boolean isEmail(String str) {
if (str == null) return false;
return Pattern.matches(REGEX_EMAIL, str);
}