今天对身份证号码规则进行了简单的了解,然后试着写了一下身份证号码的验证,在此做一下记录,以备以后使用:
代码如下:
import java.util.Hashtable;
import java.util.regex.Pattern;
/**
* 身份证号码,可以解析身份证号码的各个字段,以及验证身份证号码是否有效<br>
* 身份证号码构成:6位地址编码+8位生日+3位顺序码+1位校验码
*
*/
public class ValidateIDCard {
/**
* 身份证号验证(18位新身份证号)
* @param validateStr 身份证号码
* @return true:合法 | false:非法
*/
@SuppressWarnings("unchecked")
public static boolean isValidIDCardNum(String validateStr){
if(validateStr.length()!=18){
return false;
}
String regex = "[0-9]{17}[0-9|xX]$";
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
if(!pattern.matcher(validateStr).matches()){//前17位数字,第18位数字或字母X
return false;
}
Hashtable areacodeHashtable = new Hashtable();
areacodeHashtable.put("11", "北京");
areacodeHashtable.put("12", "天津");
areacodeHashtable.put("13", "河北");
areacodeHashtable.put("14", "山西");
areacodeHashtable.put("15", "内蒙古");
areacodeHashtable.put("21", "辽宁");
areacodeHashtable.put("22", "吉林");
areacodeHashtable.put("23", "黑龙江");
areacodeHashtable.put("31", "上海");
areacodeHashtable.put("32", "江苏");
areacodeHashtable.put("33", "浙江");
areacodeHashtable.put("34", "安徽");
areacodeHashtable.put("35", "福建");
areacodeHashtable.put("36", "江西");
areacodeHashtable.put("37", "山东");
areacodeHashtable.put("41", "河南");
areacodeHashtable.put("42", "湖北");
areacodeHashtable.put("43", "湖南");
areacodeHashtable.put("44", "广东");
areacodeHashtable.put("45", "广西");
areacodeHashtable.put("46", "海南");
areacodeHashtable.put("50", "重庆");
areacodeHashtable.put("51", "四川");
areacodeHashtable.put("52", "贵州");
areacodeHashtable.put("53", "云南");
areacodeHashtable.put("54", "西藏");
areacodeHashtable.put("61", "陕西");
areacodeHashtable.put("62", "甘肃");
areacodeHashtable.put("63", "青海");
areacodeHashtable.put("64", "宁夏");
areacodeHashtable.put("65", "新疆");
areacodeHashtable.put("71", "台湾");
areacodeHashtable.put("81", "香港");
areacodeHashtable.put("82", "澳门");
areacodeHashtable.put("91", "国外");
if(areacodeHashtable.get(validateStr.substring(0,2))==null){
return false;
}
String birthdate = validateStr.substring(6, 14);//获取生日
int birthyear = Integer.parseInt(birthdate.substring(0, 4));//出生年份
int curyear = java.util.Calendar.getInstance().get(java.util.Calendar.YEAR);//当前时间年份
if(birthyear>=curyear || birthyear <1900){//不在1900年与当前时间之间
return false;
}
String dateRegex = "^((\\d{2}(([02468][048])|([13579][26]))[\\/\\/\\s]?((((0 ?[13578])|(1[02]))[\\/\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\/\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\/\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\/\\/\\s]?((((0?[13578])|(1[02]))[\\/\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\/\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\/\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))";
if(!Pattern.compile(regex, Pattern.CASE_INSENSITIVE).matches(dateRegex, birthdate)){//出生年月日不合法
return false;
}
/**
* 计算校验码(第十八位数):
* 十七位数字本体码加权求和公式 S = Sum(Ai * Wi), i = 0...16 ,先对前17位数字的权求和;
* Ai:表示第i位置上的身份证号码数字值 Wi:表示第i位置上的加权因子 Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2;
* 计算模 Y = mod(S, 11)
* 通过模Y得到对应的校验码: 0 1 2 3 4 5 6 7 8 9 10 校验码: 1 0 X 9 8 7 6 5 4 3 2
*/
final String[] LASTCODE = { "1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2" };// 18位身份证中最后一位校验码
final int[] WEIGHT = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };// 18位身份证中,前17位数字各个数字的生成校验码时的权值
String tempLastCode = "";//临时记录身份证号码最后一位
int sum = 0;//前17位号码与对应权重值相乘总和
for(int i=0; i<17; i++){
sum += ((int)(validateStr.charAt(i)-'0'))*WEIGHT[i];
}
tempLastCode = LASTCODE[sum%11];//实际最后一位号码
System.out.println(tempLastCode);
if(validateStr.substring(17).equals(tempLastCode)){//最后一位符合
return true;
}else{
return false;
}
}
}
如有不足之处,请批评指正!