IDCardUtils.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /*******************************************************************************
  2. * Copyright ( c ) 2016 ZhiJieYun Corporation. All Rights Reserved.
  3. *
  4. * This software is the confidential and proprietary information of ZhiJieYun
  5. * Corporation ("Confidential Information"). You shall not disclose such
  6. * Confidential Information and shall use it only in accordance with the terms
  7. * of the license agreement you entered into with ZhiJieYun Corporation or a ZhiJieYun
  8. * authorized reseller (the "License Agreement"). ZhiJieYun may make changes to the
  9. * Confidential Information from time to time. Such Confidential Information may
  10. * contain errors.
  11. *
  12. * EXCEPT AS EXPLICITLY SET FORTH IN THE LICENSE AGREEMENT, ZhiJieYun DISCLAIMS ALL
  13. * WARRANTIES, COVENANTS, REPRESENTATIONS, INDEMNITIES, AND GUARANTEES WITH
  14. * RESPECT TO SOFTWARE AND DOCUMENTATION, WHETHER EXPRESS OR IMPLIED, WRITTEN OR
  15. * ORAL, STATUTORY OR OTHERWISE INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  16. * WARRANTIES OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A
  17. * PARTICULAR PURPOSE. ZhiJieYun DOES NOT WARRANT THAT END USER'S USE OF THE
  18. * SOFTWARE WILL BE UNINTERRUPTED, ERROR FREE OR SECURE.
  19. *
  20. * ZhiJieYun SHALL NOT BE LIABLE TO END USER, OR ANY OTHER PERSON, CORPORATION OR
  21. * ENTITY FOR INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL
  22. * DAMAGES, OR DAMAGES FOR LOSS OF PROFITS, REVENUE, DATA OR USE, WHETHER IN AN
  23. * ACTION IN CONTRACT, TORT OR OTHERWISE, EVEN IF ZhiJieYun HAS BEEN ADVISED OF THE
  24. * POSSIBILITY OF SUCH DAMAGES. ZhiJieYun' TOTAL LIABILITY TO END USER SHALL NOT
  25. * EXCEED THE AMOUNTS PAID FOR THE ZhiJieYun SOFTWARE BY END USER DURING THE PRIOR
  26. * TWELVE (12) MONTHS FROM THE DATE IN WHICH THE CLAIM AROSE. BECAUSE SOME
  27. * STATES OR JURISDICTIONS DO NOT ALLOW LIMITATION OR EXCLUSION OF CONSEQUENTIAL
  28. * OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY NOT APPLY TO END USER.
  29. *
  30. * Copyright version 1.0
  31. *******************************************************************************/
  32. package com.ydtech.utils;
  33. import java.text.ParseException;
  34. import java.text.SimpleDateFormat;
  35. import java.util.*;
  36. import java.util.regex.Matcher;
  37. import java.util.regex.Pattern;
  38. /**
  39. * <p>
  40. * 类说明: 1、号码的结构 公民身份号码是特征组合码,由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,
  41. * 三位数字顺序码和一位数字校验码。 2、地址码(前六位数) 表示编码对象常住户口所在县(市、旗、区)的行政区划代码,按GB/T2260的规定执行。
  42. * 3、出生日期码(第七位至十四位) 表示编码对象出生的年、月、日,按GB/T7408的规定执行,年、月、日代码之间不用分隔符。
  43. * 4、顺序码(第十五位至十七位) 表示在同一地址码所标识的区域范围内,对同年、同月、同日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配给女性。
  44. * 5、校验码(第十八位数)
  45. *
  46. * @version 1.00
  47. * @author:aidy
  48. */
  49. public class IDCardUtils {
  50. /**
  51. * <p>
  52. * 身份证号码合法性校验。
  53. *
  54. * @return boolean
  55. * @author: aidy
  56. */
  57. public static boolean idCardValidate(String idStr) {
  58. String errorInfo = null;// 记录错误信息
  59. String[] ValCodeArr = {"1", "0", "x", "9", "8", "7", "6", "5", "4", "3", "2"};
  60. String[] Wi = {"7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2"};
  61. // String[] Checker = {"1","9","8","7","6","5","4","3","2","1","1"};
  62. String ai = "";
  63. if (StringUtils.isNullOrEmpty(idStr)) {
  64. return false;
  65. } else {
  66. if (idStr.length() != 15 && idStr.length() != 18) {
  67. errorInfo = "号码长度应该为15位或18位。";
  68. return false;
  69. }
  70. // ================ 数字 除最后一位都为数字 ================
  71. if (idStr.length() == 18) {
  72. ai = idStr.substring(0, 17);
  73. } else if (idStr.length() == 15) {
  74. ai = idStr.substring(0, 6) + "19" + idStr.substring(6, 15);
  75. }
  76. if (isNumeric(ai) == false) {
  77. errorInfo = "15位号码都应为数字 ; 18位号码除最后一位外,都应为数字。";
  78. return false;
  79. }
  80. // =======================(end)========================
  81. // ================ 出生年月是否有效 ================
  82. String strYear = ai.substring(6, 10);// 年份
  83. String strMonth = ai.substring(10, 12);// 月份
  84. String strDay = ai.substring(12, 14);// 月份
  85. String birthday = ai.substring(6, 14);
  86. if (!isDate(birthday)) {
  87. errorInfo = "生日无效。";
  88. return false;
  89. }
  90. GregorianCalendar gc = new GregorianCalendar();
  91. SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
  92. try {
  93. if ((gc.get(Calendar.YEAR) - Integer.parseInt(strYear)) > 150
  94. || (gc.getTime().getTime() - s.parse(strYear + "-" + strMonth + "-" + strDay).getTime()) < 0) {
  95. errorInfo = "生日不在有效范围。";
  96. return false;
  97. }
  98. } catch (NumberFormatException e) {
  99. e.printStackTrace();
  100. return false;
  101. } catch (ParseException e) {
  102. e.printStackTrace();
  103. return false;
  104. }
  105. if (Integer.parseInt(strMonth) > 12 || Integer.parseInt(strMonth) == 0) {
  106. errorInfo = "月份无效";
  107. return false;
  108. }
  109. if (Integer.parseInt(strDay) > 31 || Integer.parseInt(strDay) == 0) {
  110. errorInfo = "日期无效";
  111. return false;
  112. }
  113. // =====================(end)=====================
  114. // ================ 地区码时候有效 ================
  115. Hashtable<String, String> h = GetAreaCode();
  116. if (h.get(ai.substring(0, 2)) == null) {
  117. errorInfo = "地区编码错误。";
  118. return false;
  119. }
  120. // ==============================================
  121. // ================ 判断最后一位的值 ================
  122. int totalmulAiWi = 0;
  123. for (int i = 0; i < 17; i++) {
  124. totalmulAiWi = totalmulAiWi + Integer.parseInt(String.valueOf(ai.charAt(i))) * Integer.parseInt(Wi[i]);
  125. }
  126. int modValue = totalmulAiWi % 11;
  127. String strVerifyCode = ValCodeArr[modValue];
  128. ai = ai + strVerifyCode;
  129. if (idStr.length() == 18) {
  130. if (ai.equalsIgnoreCase(idStr) == false) {
  131. errorInfo = "身份证无效,最后一位字母错误";
  132. return false;
  133. }
  134. } else {
  135. // System.out.println("所在地区:" + h.get(ai.substring(0, 2).toString()));
  136. // System.out.println("新身份证号:" + ai);
  137. return true;
  138. }
  139. // =====================(end)=====================
  140. if (StringUtils.isNullOrEmpty(errorInfo)) {
  141. return false;
  142. } else {
  143. return true;
  144. }
  145. }
  146. }
  147. /**
  148. * <p>
  149. * 判断字符串是否为数字
  150. *
  151. * @return boolean
  152. * @author: aidy
  153. */
  154. private static boolean isNumeric(String str) {
  155. Pattern pattern = Pattern.compile("[0-9]*");
  156. Matcher isNum = pattern.matcher(str);
  157. if (isNum.matches()) {
  158. return true;
  159. } else {
  160. return false;
  161. }
  162. /**//*
  163. * 判断一个字符时候为数字 if(Character.isDigit(str.charAt(0))) { return true; }
  164. * else { return false; }
  165. */
  166. }
  167. /**
  168. * <p>
  169. * 判断字符串是否为日期格式
  170. *
  171. * @return boolean
  172. * @author: aidy
  173. */
  174. public static boolean isDate(String strDate) {
  175. String DatePattern = "^(?:([0-9]{4}(?:(?:0?[1,3-9]|1[0-2])(?:29|30)|((?:0?[13578]|1[02])-31)))|"
  176. + "([0-9]{4}(?:0?[1-9]|1[0-2])(?:0?[1-9]|1\\d|2[0-8]))|"
  177. + "(((?:(\\d\\d(?:0[48]|[2468][048]|[13579][26]))|"
  178. + "(?:0[48]00|[2468][048]00|[13579][26]00))0?229)))$";
  179. Pattern pattern = Pattern.compile(DatePattern);
  180. Matcher m = pattern.matcher(strDate);
  181. if (m.matches()) {
  182. return true;
  183. } else {
  184. return false;
  185. }
  186. }
  187. /**
  188. * <p>
  189. * 在判定已经是正确的身份证号码之后,查找出身份证所在地区。
  190. *
  191. * @return String
  192. * @author: aidy
  193. */
  194. public String GetArea(String idCard) {
  195. Hashtable<String, String> ht = GetAreaCode();
  196. String area = ht.get(idCard.substring(0, 2));
  197. return area;
  198. }
  199. /**
  200. * <p>
  201. * 在判定已经是正确的身份证号码之后,查找出此人性别(1:男;2:女)。
  202. *
  203. * @return String
  204. * @author: aidy
  205. */
  206. public static String GetSex(String idCard) {
  207. String sex = "";
  208. if (idCard.length() == 15)
  209. sex = idCard.substring(idCard.length() - 3, idCard.length());
  210. if (idCard.length() == 18)
  211. sex = idCard.substring(idCard.length() - 4, idCard.length() - 1);
  212. // System.out.println(sex);
  213. int sexNum = Integer.parseInt(sex) % 2;
  214. if (sexNum == 0) {
  215. return "FEMALE";
  216. }
  217. return "MALE";
  218. }
  219. /**
  220. * <p> 永诚使用返回对应编码
  221. * 在判定已经是正确的身份证号码之后,查找出此人性别(1:男;2:女)。
  222. *
  223. * @return String
  224. * @author: aidy
  225. */
  226. public static String GetYcSex(String idCard) {
  227. String sex = "";
  228. if (idCard.length() == 15)
  229. sex = idCard.substring(idCard.length() - 3, idCard.length());
  230. if (idCard.length() == 18)
  231. sex = idCard.substring(idCard.length() - 4, idCard.length() - 1);
  232. // System.out.println(sex);
  233. int sexNum = Integer.parseInt(sex) % 2;
  234. if (sexNum == 0) {
  235. return "106002";
  236. }
  237. return "106001";
  238. }
  239. /**
  240. * <p>
  241. * 在判定已经是正确的身份证号码之后,查找出此人出生日期
  242. *
  243. * @return String
  244. * @author: aidy
  245. */
  246. public static String GetBirthday(String idCard) {
  247. String Ain = "";
  248. if (idCard.length() == 18) {
  249. Ain = idCard.substring(0, 17);
  250. } else if (idCard.length() == 15) {
  251. Ain = idCard.substring(0, 6) + "19" + idCard.substring(6, 15);
  252. }
  253. // ================ 出生年月是否有效 ================
  254. String strYear = Ain.substring(6, 10);// 年份
  255. String strMonth = Ain.substring(10, 12);// 月份
  256. String strDay = Ain.substring(12, 14);// 日期
  257. return strYear + "-" + strMonth + "-" + strDay;
  258. }
  259. /**
  260. * <p>
  261. * 设置地区编码
  262. *
  263. * @return Hashtable
  264. * @author: aidy
  265. */
  266. private static Hashtable<String, String> GetAreaCode() {
  267. Hashtable<String, String> hashtable = new Hashtable<String, String>();
  268. hashtable.put("11", "北京");
  269. hashtable.put("12", "天津");
  270. hashtable.put("13", "河北");
  271. hashtable.put("14", "山西");
  272. hashtable.put("15", "内蒙古");
  273. hashtable.put("21", "辽宁");
  274. hashtable.put("22", "吉林");
  275. hashtable.put("23", "黑龙江");
  276. hashtable.put("31", "上海");
  277. hashtable.put("32", "江苏");
  278. hashtable.put("33", "浙江");
  279. hashtable.put("34", "安徽");
  280. hashtable.put("35", "福建");
  281. hashtable.put("36", "江西");
  282. hashtable.put("37", "山东");
  283. hashtable.put("41", "河南");
  284. hashtable.put("42", "湖北");
  285. hashtable.put("43", "湖南");
  286. hashtable.put("44", "广东");
  287. hashtable.put("45", "广西");
  288. hashtable.put("46", "海南");
  289. hashtable.put("50", "重庆");
  290. hashtable.put("51", "四川");
  291. hashtable.put("52", "贵州");
  292. hashtable.put("53", "云南");
  293. hashtable.put("54", "西藏");
  294. hashtable.put("61", "陕西");
  295. hashtable.put("62", "甘肃");
  296. hashtable.put("63", "青海");
  297. hashtable.put("64", "宁夏");
  298. hashtable.put("65", "新疆");
  299. hashtable.put("71", "台湾");
  300. hashtable.put("81", "香港");
  301. hashtable.put("82", "澳门");
  302. hashtable.put("91", "国外");
  303. return hashtable;
  304. }
  305. /**
  306. * 根据身份证地址提取省市区工具类
  307. *
  308. * @param address
  309. * @return
  310. */
  311. public static Map<String, String> addressResolution(String address) {
  312. String regex = "(?<province>[^省]+自治区|.*?省|.*?行政区|.*?市|.*?蒙古)(?<city>[^市]+自治州|.*?地区|.*?行政单位|.+盟|市辖区|.*?市|.*?县|.*?区)(?<district>[^县]+县|.*?区|.+市|.*?旗|.+海域|.+岛)?(?<town>[^区]+区|.+镇)?(?<detail>.*)";
  313. // if(address.indexOf("重庆市") == 0 || address.indexOf("上海市") == 0){
  314. // regex = "(?<province>[^市].*?市)(?<city>[^县]+县|.*?区|.+市|.*?旗|.+海域|.+岛)(?<district>[^县]+县|.*?区|.+市|.*?旗|.+海域|.+岛)?(?<town>[^区]+区|.+镇)?(?<detail>.*)";
  315. // }
  316. if(address.indexOf("新疆") == 0){
  317. regex = "(?<province>.*?新疆)(?<city>[^县]+县|.*?区|.+市|.*?旗|.+海域|.+岛)(?<district>[^县]+县|.*?区|.+市|.*?旗|.+海域|.+岛)?(?<town>[^区]+区|.+镇)?(?<detail>.*)";
  318. }
  319. Matcher m = Pattern.compile(regex).matcher(address);
  320. String province = null, city = null, district = null, town = null, detail = null;
  321. // List<Map<String, String>> table = new ArrayList<Map<String, String>>();
  322. Map<String, String> row = null;
  323. while (m.find()) {
  324. row = new LinkedHashMap<String, String>();
  325. province = m.group("province");
  326. row.put("province", province == null ? "" : province.trim());
  327. city = m.group("city");
  328. row.put("city", city == null ? "" : city.trim());
  329. district = m.group("district");
  330. row.put("district", district == null ? "" : district.trim());
  331. town = m.group("town");
  332. row.put("town", town == null ? "" : town.trim());
  333. detail = m.group("detail");
  334. row.put("detail", detail == null ? "" : detail.trim());
  335. // table.add(row);
  336. }
  337. // return table;
  338. return row;
  339. }
  340. public static void main(String[] args) throws ParseException {
  341. Map m = addressResolution("河北省邢台市邢台县西黄村镇徘徊村310号");
  342. // Map m = addressResolution("山西省忻州市忻府区合索乡沙洼村22-040");
  343. // Map m = addressResolution("安徽省池州市贵池区长江中路39号采石队宿舍9号");
  344. // Map m = addressResolution("山西省汾西县坪乡细坪村055号");
  345. // Map m = addressResolution("山西省兴县魏家滩镇高家洼村091");
  346. // Map m = addressResolution("河北省邯郸市临漳县孙陶镇兴王村兴西路富裕胡同4号");
  347. // Map m = addressResolution("内蒙古锡林郭勒盟太仆寺旗红旗镇建中村张油坊营子3组48号");
  348. // Map m = addressResolution("重庆市永川区朱沱镇大江住址路48号附59号");
  349. // Map m = addressResolution("上海市杨浦区长白三村67号28室");
  350. // String IDCardNum="210102820826411";
  351. // String IDCardNum="210102198208264114";
  352. String IDCardNum = "43282219381105414X";
  353. // IDCardUtils cc = new IDCardUtils();
  354. // long time = System.currentTimeMillis();
  355. // System.out.println(cc.idCardValidate(IDCardNum));
  356. // System.out.println(cc.idCardValidate(IDCardNum));
  357. // System.out.println(System.currentTimeMillis() - time);
  358. // cc = new IDCardUtils();
  359. // time = System.currentTimeMillis();
  360. // System.out.println(cc.idCardValidate(IDCardNum));
  361. // System.out.println(System.currentTimeMillis() - time);
  362. // // System.out.println(cc.isDate("19870827"));
  363. // System.out.println(IDCardUtils.GetBirthday(IDCardNum));
  364. }
  365. }