- 简要
- 代码
身份证号合法性判断:
若为18位身份证号:
1.第18位数字,应该在身份证号最后一位校验位数字中
2.前17为数字分别乘以对应的加权因子,累加,结果%11==17为数字
3.数字除18位外,全为数字
若位15位身份证号:
1.验证前6位是为行政区号
2.9-10位为月份<13
3.11-12位为日期<32
4.数据全为数字
注意:数据行政区号全部展示与代码中浏览器中打开时,会导致加载过慢卡顿,所以仅上传了部分数据,全量有*3271条行政区号,需要的评论留言
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
import java.util.*;
public class UdfIsIdcard extends UDF {
@Description(
name = "udf_is_idcard",
value = "_FUNC_(str) - Returns str is idcard?0:1",
extended = "Example:n > SELECt _FUNC_('620121199701232548') FROM dual LIMIT 1;n return 0 "
)
static int[] weights = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2}; // 新版身份证号 1-17 位的加权因子. 该数组顺序不能变,和index有对应关系
static String[] checkCode = {"1","0","X","9","8","7","6","5","4","3","2"}; // 新身份证号最后一位校验位的值. 该数组顺序不能变,和index有对应关系
static Set newIdCardNoLastNOSet = new HashSet(Arrays.asList(checkCode));
static Set numberSet = new HashSet(Arrays.asList("9","8","7","6","5","4","3","2","1","0"));
static Set areaCodeSet = new HashSet(Arrays.asList("110101","110102","110105"));
public int evaluate(final String idCardNo) {
if (!basicLegality(idCardNo.trim())) { // 身份证号基础校验不通过,返回false
return 0;
}
if (oldIdCardNoValidate(idCardNo) || newIdCardNoValidate(idCardNo)) {
return 1;
}
return 0;
}
private boolean basicLegality(String idCardNo) {
if (StringUtils.isEmpty(idCardNo) || (idCardNo.length() != 15 && idCardNo.length() != 18)) { // 不是合格的身份证号,新版18位,旧版15位
return false;
}
String number = idCardNo;
if (idCardNo.length() == 18) { // 新身份证号18位,最后一位可能包含X,单独验证
String lastNumber = idCardNo.substring(17).toUpperCase();
boolean contains = newIdCardNoLastNOSet.contains(lastNumber);
if (!contains) {
return false; // 如果不包含在这里面,那么验证不通过
}
number = number.substring(0, 17);
}
// 做数字验证
for (int i = 0; i < number.length(); i++) {
boolean contains = numberSet.contains(String.valueOf(number.charAt(i)));
if (!contains) {
return false; // 如果不包含在这里面,那么验证不通过
}
}
return true;
}
private boolean newIdCardNoValidate(String newIdCardNo) {
// if (StringUtils.isEmpty(newIdCardNo) || newIdCardNo.length() != 18) { // 不是合格的新版身份证号
// return false;
// }
int sum = 0; // 此处用int即可。即使每位都是9,求和之后也远远不会溢出,达到int的最大值
for (int i = 0; i < 17; i++) {
int c = Integer.parseInt(String.valueOf(newIdCardNo.charAt(i)));
sum += weights[i] * c;
}
int checkCodeIndex = sum % 11;
return checkCode[checkCodeIndex].equalsIgnoreCase(newIdCardNo.substring(17));
}
private boolean oldIdCardNoValidate(String oldIdCardNo) {
boolean flag = false;
// if(StringUtils.isNotEmpty(oldIdCardNo)&& oldIdCardNo.length() == 15){
//
// }
if(areaCodeSet.contains(oldIdCardNo.substring(0,6)) && Integer.parseInt(oldIdCardNo.substring(8,10)) < 13 && Integer.parseInt(oldIdCardNo.substring(10,12)) <32){
flag =true;
}
return flag;
}
public static void main(String[] args) {
System.out.println("值为" + new UdfIsIdcard().evaluate( "130503670241001" ));
}
}



