package com.techqy.common.util;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 身份證號驗證類
*/
public class CardId {
/**
* 1、號碼的結構 公民身份號碼是特徵組合碼,由十七位數字本體碼和一位校驗碼組成。排列順序從左至右依次爲:六位數字地址碼,八位數字出生日期碼,
* 三位數字順序碼和一位數字校驗碼。
*
* 2、地址碼(前六位數) 表示編碼對象常住戶口所在縣(市、旗、區)的行政區劃代碼,按GB/T2260的規定執行。
*
* 3、出生日期碼(第七位至十四位) 表示編碼對象出生的年、月、日,按GB/T7408的規定執行,年、月、日代碼之間不用分隔符。
*
* 4、順序碼(第十五位至十七位)
* 表示在同一地址碼所標識的區域範圍內,對同年、同月、同日出生的人編定的順序號,順序碼的奇數分配給男性,偶數分配給女性。
*
* 5、校驗碼(第十八位數) (1)十七位數字本體碼加權求和公式 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 (2)計算模 Y = mod(S, 11) (3)通過模得到對應的校驗碼 Y: 0 1 2 3 4 5 6 7
* 8 9 10 校驗碼: 1 0 X 9 8 7 6 5 4 3 2
* */
/**
* 身份證號
*/
private String cardId;
/**
* 出生年月
*/
private Date birthday;
/**
* 性別
*/
private String gender;
/**
* 構造函數
*/
public CardId() {
super();
// TODO Auto-generated constructor stub
}
/**
* 帶身份證號的構造函數
*
* @param cardId
* 身份證號
* @throws Exception
*/
public CardId(String cardId) throws Exception {
this.cardId = toEighteenId(cardId);
birthday = getBirthday(cardId);
gender = getGender(cardId);
}
/**
* @param cardId
* the cardId to set
* @throws Exception
*/
public void setCardId(String cardId) throws Exception {
this.cardId = cardId;
birthday = getBirthday(cardId);
gender = getGender(cardId);
}
/**
* @return the cardId
*/
public String getCardId() {
return cardId;
}
/**
* 返回出生年月
*
* @return
*/
public String getBirthday() {
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMM");
return formatter.format(birthday);
}
/**
* 獲取年齡
*
* @return
*/
public int getAge() {
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy");
int age = Integer.parseInt(formatter.format(date))
- Integer.parseInt(formatter.format(birthday));
return age;
}
/**
* 返回達齡時間
*
* @return
*/
public String getTireDate() {
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMM");
String str = formatter.format(birthday);
str = String.valueOf(Integer.parseInt(str.substring(0, 4)) + 60)
+ str.substring(4);
return str;
}
/**
* 返回性別
*
* @return
*/
public String getGender() {
return gender;
}
/**
* 根據身份證獲取出生年月
*
* @param cardId
* 身份證號
* @return 出生年月
* @throws Exception
* 身份證錯誤信息
*/
public static Date getBirthday(String cardId) throws Exception {
Date birthday;
// 判斷身份證號碼長度
if (cardId.length() != 18 && cardId.length() != 15) {
throw new Exception("號碼長度應該爲15位或18位");
}
// ================ 數字 除最後以爲都爲數字 ================
String sevenId = "";
if (cardId.length() == 18) {
sevenId = cardId.substring(0, 17);
} else if (cardId.length() == 15) {
sevenId = cardId.substring(0, 6) + "19" + cardId.substring(6, 15);
}
if (isNumeric(sevenId) == false) {
throw new Exception("15位號碼都應爲數字 ; 18位號碼除最後一位外,都應爲數字。");
}
// // 驗證校驗位
// if (cardId.length() == 18) {
// String verify = getVerify(sevenId);
// if (!cardId.substring(17, 18).toLowerCase().equals(verify)) {
// throw new Exception("身份證校驗位有誤");
// }
// }
// 根據身份證號獲取出生年月
String dateString;
dateString = sevenId.substring(6, 10);
dateString = dateString + "-" + sevenId.substring(10, 12);
dateString = dateString + "-" + sevenId.substring(12, 14);
birthday = StringToDate(dateString);
return birthday;
}
public static String checkEffect(String cardId) {
// 判斷身份證號碼長度
if (cardId.length() != 18 && cardId.length() != 15) {
return "號碼長度應該爲15位或18位";
}
// ================ 數字 除最後以爲都爲數字 ================
String sevenId = "";
if (cardId.length() == 18) {
sevenId = cardId.substring(0, 17);
} else if (cardId.length() == 15) {
sevenId = cardId.substring(0, 6) + "19" + cardId.substring(6, 15);
}
if (isNumeric(sevenId) == false) {
return "15位號碼都應爲數字 ; 18位號碼除最後一位外,都應爲數字。";
}
// // 驗證校驗位
// if (cardId.length() == 18) {
// String verify = getVerify(sevenId);
// if (!cardId.substring(17, 18).toLowerCase().equals(verify)) {
// return "身份證校驗位有誤";
// }
// }
int year = Integer.parseInt(sevenId.substring(6, 10));
int month = Integer.parseInt(sevenId.substring(10, 12));
int day = Integer.parseInt(sevenId.substring(12, 14));
if (month < 1
|| month > 12
|| day < 1
|| day > 31
|| ((month == 4 || month == 6 || month == 9 || month == 11) && day > 30)
|| (month == 2 && (((year) % 4 > 0 && day > 28) || day > 29))) {
return "身份證號中出生日期有誤";
}
return "";
}
/**
* 根據身份證號獲取性別
*
* @param cardId
* 身份證號
* @return 性別
* @throws Exception 身份證錯誤信息
*/
public static String getGender(String cardId) {
String gender = null;
if (cardId.length() == 18) {
gender = Integer.parseInt(cardId.substring(16, 17)) % 2 == 0 ? "女"
: "男";
} else if (cardId.length() == 15) {
gender = Integer.parseInt(cardId.substring(14, 15)) % 2 == 0 ? "女"
: "男";
}
return gender;
}
public static boolean isNumeric(String str) {
Pattern pattern = Pattern.compile("[0-9]*");
Matcher isNum = pattern.matcher(str);
if (isNum.matches()) {
return true;
} else {
return false;
}
}
/**
* 根據17位身份證號獲取驗證碼
*
* @param cardId
* 17位身份證號
* @return 驗證碼
*/
public static String getVerify(String cardId) {
String[] ValCodeArr = { "1", "0", "x", "9", "8", "7", "6", "5", "4",
"3", "2" };
String[] Wi = { "7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7",
"9", "10", "5", "8", "4", "2" };
int TotalmulAiWi = 0;
for (int i = 0; i < 17; i++) {
TotalmulAiWi = TotalmulAiWi
+ Integer.parseInt(String.valueOf(cardId.charAt(i)))
* Integer.parseInt(Wi[i]);
}
int modValue = TotalmulAiWi % 11;
String strVerifyCode = ValCodeArr[modValue];
return strVerifyCode;
}
/**
* 將"yyyy-MM-dd"格式的日期字符串轉爲java.util.Date類型
*
* @param strDate
* 日期字符串
* @return 時間類型 <span style="BACKGROUND-COLOR: #ffd700"></span>
*/
public static Date StringToDate(String strDate) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
try {
String[] array = strDate.split("-");
if (array.length != 3)
throw new Exception();
int year = Integer.parseInt(array[0]);
int month = Integer.parseInt(array[1]);
int day = Integer.parseInt(array[2]);
if (month < 1
|| month > 12
|| day < 1
|| day > 31
|| ((month == 4 || month == 6 || month == 9 || month == 11) && day > 30)
|| (month == 2 && (((year) % 4 > 0 && day > 28) || day > 29)))
throw new Exception();
return formatter.parse(strDate);
} catch (Exception e) {
throw new RuntimeException("日期錯誤");
}
}
/**
* 15位身份證號轉18位
*
* @param cardId
* @return
*/
public static String toEighteenId(String cardId) {
if (cardId.length() != 15)
return cardId;
cardId = cardId.substring(0, 6) + "19" + cardId.substring(6, 15);
cardId = cardId + getVerify(cardId);
return cardId;
}
/**
* 生成隨機身份證號
*
* @param num
* 個數
* @param year
* 從1920年開始第幾年出生
*/
public static String genCardId(int num, int year) {
return genCardId(num, "d:\\cardId.txt", year);
}
/**
* 生成隨機身份證號
*
* @param num
* 個數
*/
public static String genCardId(int num) {
return genCardId(num, "d:\\cardId.txt", 100);
}
/**
* 生成隨機身份證號
*
* @param num
* 個數
* @param filePath
* 文件路徑
* @param year
* 從1920年開始第幾年出生
*/
public static String genCardId(int num, String filePath, int yearLen) {
String ret = "";
FileWriter fw = null;
try {
// 定義一個properties文件的名字
fw = new FileWriter(filePath);
String propFile = "areacode.properties";
// 定義一個properties對象
Properties properties = new Properties();
// 讀取properties
InputStream file = CardId.class.getClassLoader()
.getResourceAsStream(propFile);
// 加載properties文件
// properties.load(new InputStreamReader(file, "utf-8"));
properties.load(file);
Object[] code = properties.keySet().toArray();
int size = code.length;
Random random = new Random();
for (int i = 0; i < num; i++) {
String areaCode = (String) code[random.nextInt(size)];
int year = 1920 + random.nextInt(yearLen);
int month = random.nextInt(11);
if (month == 0)
month = 12;
int day = 0;
while (true) {
day = random.nextInt(31);
if (!((day == 0 || (month == 4 || month == 6 || month == 9 || month == 11)
&& day > 30) || (month == 2 && (((year) % 4 > 0 && day > 28) || day > 29)))) {
break;
}
}
String birthday = String.valueOf(year * 10000 + month * 100
+ day);
String randomCode = String.valueOf(1000 + random.nextInt(999))
.substring(1);
String verify = getVerify(areaCode + birthday + randomCode);
ret = areaCode + birthday + randomCode + verify;
fw.write(ret);
fw.write("\r\n");
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
if (fw != null) {
try {
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return ret;
}
/**
* @param args
*/
public static void main(String[] args) {
try {
System.out.println(genCardId(10000));
;
} catch (Exception e) {
e.printStackTrace();
}
}
}