Skip to content

Instantly share code, notes, and snippets.

@chanjarster
Created July 24, 2015 06:41
Show Gist options
  • Save chanjarster/0979fa9471e40514e9b1 to your computer and use it in GitHub Desktop.
Save chanjarster/0979fa9471e40514e9b1 to your computer and use it in GitHub Desktop.
中国大陆身份证号Parser
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 中国居民身份证parser,支持15位,18位身份证
* http://www.360doc.com/content/11/0322/21/4240950_103674335.shtml
* http://baike.baidu.com/view/3457576.htm
* Created by qianjia on 15/7/22.
*/
public class IdcardParser {
//wi =2(n-1)(mod 11)
private static final int[] wi = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1 };
// verify digit
private static final int[] vi = { 1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2 };
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
/**
* 错误信息
*/
private String error;
/**
* 18位身份证号
*/
private String idcard18;
/**
* 省份(自治区,直辖市)
*/
private String province;
/**
* 市(州)
*/
private String city;
/**
* 县(县级市)
*/
private String district;
/**
* 出生日期
*/
private Date birthday;
/**
* 当地派出所
*/
private String policeStation;
/**
* 性别 1:男,2:女
*/
private String gender;
public IdcardParser(String idcard) {
if (idcard == null || idcard.length() == 0) {
error = "身份证号为null";
return;
}
if (idcard.length() != 15 && idcard.length() != 18) {
error = "身份证号长度不正确,必须是15位或者18位";
return;
}
idcard = idcard.toUpperCase();
if (verifyLength(idcard)
&& verifyCharLegal(idcard)) {
this.idcard18 = convertTo18Digits(idcard);
if (verifyProvince()
&& verifyCity()
&& verifyDistrict()
&& verifyBirthday()
&& verifyPoliceStation()
&& verifyGender()
&& verifyVerifyDigit()) {
// 利用短路 &&
}
}
}
/**
* 检验长度
*
* @param idcard
* @return
*/
private boolean verifyLength(String idcard) {
if (idcard == null || idcard.length() == 0) {
error = "身份证号长度不正确,必须是15位或者18位";
return false;
}
if (idcard.length() != 15 && idcard.length() != 18) {
error = "身份证号长度不正确,必须是15位或者18位";
return false;
}
return true;
}
/**
* 校验字符是否合法
*
* @param idcard
* @return
*/
private boolean verifyCharLegal(String idcard) {
char[] ch = idcard.toCharArray();
for (int i = 0; i < ch.length; i++) {
if (i == 17) {
if (!(
(ch[i] >= '0' && ch[i] <= '9') || ch[i] == 'X'
)) {
error = "第" + (i + 1) + "位包含非法字符";
return false;
}
} else {
if (!(ch[i] >= '0' && ch[i] <= '9')) {
error = "第" + (i + 1) + "位包含字母";
return false;
}
}
}
return true;
}
/**
* 15位转18位身份证
*
* @param idcard
* @return
*/
private String convertTo18Digits(String idcard) {
if (idcard.length() == 18) {
return idcard;
}
if (idcard.length() == 15) {
verifyAllDigit(idcard);
}
String idcard18 = idcard.substring(0, 6);
idcard18 = idcard18 + "19";
idcard18 = idcard18 + idcard.substring(6, 15);
idcard18 = idcard18 + calculateVerifyDigit(idcard18);
return idcard18;
}
//验证身份除了最后位其他的是否包含字母
private boolean verifyAllDigit(String idcard) {
String str = idcard;
return true;
}
/**
* 检验省份(自治区,直辖市)
*
* @return
*/
private boolean verifyProvince() {
this.province = idcard18.substring(0, 2);
return true;
}
/**
* 检验市(州)
*
* @return
*/
private boolean verifyCity() {
this.city = idcard18.substring(2, 4);
return true;
}
/**
* 检验县(县级市)
*
* @return
*/
private boolean verifyDistrict() {
this.district = idcard18.substring(4, 6);
return true;
}
/**
* 检验出生日期
*
* @return
*/
private boolean verifyBirthday() {
try {
this.birthday = sdf.parse(idcard18.substring(6, 14));
return true;
} catch (ParseException e) {
this.error = "出生日期错误(15位身份证: 7-12位, 18位身份证: 7-14位)";
}
return false;
}
/**
* 检验当地派出所
*
* @return
*/
private boolean verifyPoliceStation() {
this.policeStation = idcard18.substring(14, 16);
return true;
}
/**
* 检验性别
*
* @return
*/
public boolean verifyGender() {
this.gender = Integer.parseInt(idcard18.substring(16, 17)) % 2 == 0 ? "2" : "1";
return true;
}
/**
* 检验校验位
*
* @return
*/
private boolean verifyVerifyDigit() {
String actualMod = idcard18.substring(17, 18);
String expectedMod = calculateVerifyDigit(idcard18);
if (actualMod.equals(expectedMod)) {
return true;
}
error = "最末尾的数字验证码错误";
return false;
}
/**
* 身份证号码是否合法
*
* @return
*/
public boolean isValid() {
return error == null || error.length() == 0;
}
/**
* 获得校验位
*
* @param idcard18
* @return
*/
private String calculateVerifyDigit(String idcard18) {
int[] ai = new int[18];
int remaining = 0;
if (idcard18.length() == 18) {
idcard18 = idcard18.substring(0, 17);
}
if (idcard18.length() == 17) {
int sum = 0;
for (int i = 0; i < 17; i++) {
String k = idcard18.substring(i, i + 1);
ai[i] = Integer.parseInt(k);
}
for (int i = 0; i < 17; i++) {
sum = sum + wi[i] * ai[i];
}
remaining = sum % 11;
}
return String.valueOf(vi[remaining]);
}
public String getError() {
return error;
}
/**
* 获得18位形式身份证号
*
* @return
*/
public String getIdcard18() {
return idcard18;
}
/**
* 省份(自治区,直辖市)
*
* @return
*/
public String getProvince() {
return province;
}
/**
* 市(州)
*
* @return
*/
public String getCity() {
return city;
}
/**
* 县(县级市)
*
* @return
*/
public String getDistrict() {
return district;
}
/**
* 出生日期
*
* @return
*/
public Date getBirthday() {
return birthday;
}
/**
* 当地派出所
*
* @return
*/
public String getPoliceStation() {
return policeStation;
}
/**
* 性别 1:男,2:女
*
* @return
*/
public String getGender() {
return gender;
}
}
@chanjarster
Copy link
Author

IdcardParser idcardParser = new IdcardParser("身份证号");
idcardParser.isValid();
idcardParser.getError();
idcardParser.getXXX();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment