根据〖中华人民共和国国家标准GB11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。(顺序码:
表示在同一地址码所标识的区域范围内,对同年、同月、同 日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配 给女性。)
第1、2位数字表示:所在省份的代码;
第3、4位数字表示:所在城市的代码;
第5、6位数字表示:所在区县的代码;
第7~14位数字表示:出生年、月、日;
第15、16位数字表示:所在地的派出所的代码;
第17位数字表示性别:奇数表示男性,偶数表示女性;
第18位数字是校检码:也有的说是个人信息码,一般是随计算机的随机产生,用来检验身份证的正确性。校检码可以是0~9的数字,有时也用x表示。
第十八位数字(校验码)的计算方法为:
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。所以如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2。
省、直辖市代码表:
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 static StringcityCode[] = {"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"};
/*前17位加权因子*/
private static int power[] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
/*校验方法*/
public static boolean validate18Idcard(String idcard) {
if (idcard ==null) {
return false;
}
// 非18位为假
if (idcard.length() !=18) {
return false;
}
// 获取前17位
String idcard17 = idcard.substring(0,17);
// 前17位全部为数字
if (!isDigital(idcard17)) {
return false;
}
String provinceid = idcard.substring(0,2);
// 校验省份
if (!checkProvinceid(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;
}
// 获取第18位
String idcard18Code = idcard.substring(17,18);
char c[] = idcard17.toCharArray();
int bit[] =converCharToInt(c);
int sum17 =0;
sum17 =getPowerSum(bit);
// 将和值与11取模得到余数进行校验码判断
String checkCode =getCheckCodeBySum(sum17);
if (null == checkCode) {
return false;
}
// 将身份证的第18位与算出来的校码进行匹配,不相等就为假
if (!idcard18Code.equalsIgnoreCase(checkCode)) {
return false;
}
return true;
}
/* 数字验证*/
private static boolean isDigital(String str) {
return str.matches("^[0-9]*$");
}
/*校验省份*/
private static boolean checkProvinceid(String provinceid) {
for (String id : cityCode) {
if (id.equals(provinceid)) {
return true;
}
}
return false;
}
/* 将字符数组转为整型数组*/
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;
}
/* 将身份证的每位和对应位的加权因子相乘之后,再得到和值*/
private static int getPowerSum(int[] bit) {
int sum =0;
if (power.length != bit.length) {
return sum;
}
for (int i =0; i < bit.length; i++) {
for (int j =0; j
if (i == j) {
sum = sum + bit[i] *power[j];
}
}
}
return sum;
}
/*将和值与11取模得到余数进行校验码判断*/
private static String getCheckCodeBySum(int sum17) {
String checkCode =null;
switch (sum17 %11) {
case 10:
checkCode ="2";
break;
case 9:
checkCode ="3";
break;
case 8:
checkCode ="4";
break;
case 7:
checkCode ="5";
break;
case 6:
checkCode ="6";
break;
case 5:
checkCode ="7";
break;
case 4:
checkCode ="8";
break;
case 3:
checkCode ="9";
break;
case 2:
checkCode ="x";
break;
case 1:
checkCode ="0";
break;
case 0:
checkCode ="1";
break;
}
return checkCode;
}
写个main测试一下
public static void main(String[] args)throws Exception {
String idcard18 = "310103198811155044";
logger.info("isValidatedAllIdcard[{}]",isValidatedAllIdcard(idcard18));
}