⼆代⾝份证编码规则及校验代码实现
本⽂主要讨论的是⼆代⾝份证编码规则及其Java代码实现,下⾯的校验⽅式还不是特别严谨,由于只校验了前两位的省份信息,中间六位的出⽣⽇期信息和最后⼀位的校验码信息,故对于部分不满⾜要求的证件号码刚好同时满⾜了这⾥提到的⼏个条件,也会被判定为是合法的证件号码…
1 ⼆代⾝份证号码编码规则
1.1 编码格式
1999年我国颁发了第⼆代居民⾝份证号,公民⾝份号码为18位,且终⾝不变。
居民⾝份证格式如:ABCDEFYYYYMMDDXXXR
1.1.1地址码(ABCDEF)
表⽰登记户⼝时所在地的⾏政区划代码(省、市、县),如果⾏政区划进⾏了重新划分,同⼀个地⽅进⾏户⼝登记的可能存在地址码不⼀致的情况。⾏政区划代码按GB/T2260的规定执⾏。
1.1.2 出⽣⽇期码(YYYYMMDD)
表⽰该居民的出⽣年⽉⽇,年4位数字,⽉和⽇分别⽤2位数字表⽰,如19491001,;出⽣⽇期码是按GB/T 7408的规定执⾏的。
1.1.3 顺序码(XXX)
表⽰同⼀地址码区域内,同年、同⽉、同⽇⽣的⼈所编订的顺序号,根据⾃⼰⾝份证的顺序码就可以知道:与我们同年同⽉同⽇⽣的同性⾄少有多少个,且在我们之前登记户籍的有多少⼈。⾝份证顺序码的奇数分配给男性,偶数分配给⼥性。这就是为什么倒数第⼆位奇数表⽰男⽣,偶数表⽰⼥⽣。
1.1.4 校验码(R)
R之前的17位被称为本体码,R是根据本体码,按照校验码算法(ISO 7064:1983,MOD 11-2校)计算出来的。当我们输⼊⾝份号码进⾏实名认证的时候,根据校验码算法可以初步判断你输⼊⾝份证号码格式是否正确。
1.2 校验码算法
将本体码各位数字乘以对应加权因⼦并求和,除以11得到余数,根据余数通过校验码对照表查得校验码。
1.2.1 加权因⼦
位置序号1234567891011121314151617加权因⼦7910584216379105842(本体码每个位置对应的加权因⼦)
1.2.2 校验码表
余数012345678910
校验码10X98765432
(每个余数对应的校验码)哪个牌子的女装好
1.2.3 应⽤举例
某公民的⾝份证号码是340524************
第⼀步:本体码乘以加权因⼦:
3*7+4*9+0*10+……0*4+1*2=189
第⼆步:计算求和后除以11的余数
189%11=2安康汉江大桥
第三步:在检验码中查询余数对应的检验码
2所对应的校验码是X,注意X必须⼤写
2 Java编码实现
2.1 对外提供的调⽤接⼝
/**张娜拉 结婚
* ⼆代⾝份证号码有效性校验
*
* @param idNo
* @return
*/
public static boolean isValidIdNo(String idNo) {
chenxiao
return isIdNoPattern(idNo) && isValidProvinceId(idNo.substring(0, 2))
&& isValidDate(idNo.substring(6, 14)) && checkIdNoLastNum(idNo);
}
2.2 ⼆代⾝份证正则表达式
/**
* ⼆代⾝份证正则表达式
*
* @param idNo
* @return
*/
private static boolean isIdNoPattern(String idNo) {
return Pattern.matches("^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([\\d|x|X]{1})$", idNo);
}
2.3 校验前两位省份信息
2.3.1 常量
//省(直辖市)码表
private static String provinceCode[] = { "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" };
2.3.2 检查省份信息
/**
* 检查⾝份证的省份信息是否正确
于小彤女朋友
* @param provinceId
* @return
*/
public static boolean isValidProvinceId(String provinceId){
for (String id : provinceCode) {
if (id.equals(provinceId)) {
return true;
}
}
return false;
}
2.4 判断中间的六位⽇期是否有效
/**
* 判断⽇期是否有效
* @param inDate
* @return
*/
public static boolean isValidDate(String inDate) {
if (inDate == null){
return false;
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
if (im().length() != Pattern().length()){
return false;
}
dateFormat.setLenient(false);//执⾏严格的⽇期匹配
try {
dateFormat.im());
} catch (ParseException e) {
return false;
查身份证
}
return true;
}
2.4 校验第18位校验码
2.4.1 常量
//⾝份证前17位每位加权因⼦
private static int[] power = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
//⾝份证第18位校检码
private static String[] refNumber ={"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};
2.4.2 计算第18位校验码
/**
* 计算⾝份证的第⼗⼋位校验码
* @param cardIdArray
* @return
*/
public static String sumPower(int[] cardIdArray){
int result = 0;
for(int i=0;i<power.length;i++){
result += power[i] * cardIdArray[i];
}
return refNumber[(result%11)];
}
2.4.2 验证第18位校验码是否正确
/**
* 校验⾝份证第18位是否正确(只适合18位⾝份证)
* @param idNo
* @return
*/
public static boolean checkIdNoLastNum(String idNo){
if(idNo.length() != 18){
return false;
}
char[] tmp = CharArray();
int[] cardidArray = new int[tmp.length-1];
int i=0;
for(i=0;i<tmp.length-1;i++){
cardidArray[i] = Integer.parseInt(tmp[i]+"");
}
String checkCode = sumPower(cardidArray);
String lastNum = tmp[tmp.length-1] + "";
if(lastNum.equals("x")){
lastNum = UpperCase();
}
if(!checkCode.equals(lastNum)){
return false;
}
return true;
}
3 参考⽂献