【工具类】身份证号码相关验证

2022-10-12,,,

验证身份证真实性、根据身份证号码获取相关年龄、性别、生日、星座等信息。

直接上代码

  1 package com.itxs.util;
  2 
  3 import java.text.simpledateformat;
  4 import java.util.calendar;
  5 import java.util.date;
  6 import java.util.hashmap;
  7 import java.util.map;
  8 
  9 /**
 10  * description 身份证号码工具类 
 11  * @author 
12 * @2019年9月20日 13 */ 14 public class idcardutil { 15 16 //中国公民身份证号码最小长度 17 public static final int china_id_min_length = 15; 18 19 //中国公民身份证号码最大长度。 20 public static final int china_id_max_length = 18; 21 //每位加权因子 22 public static final int power[] = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 }; 23 24 private static final string pattern18 = "^[1-9][0-7]\\d{4}((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})(((0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)(0[1-9]|[12][0-9]|30))|(02(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))0229))\\d{3}(\\d|x)?$"; 25 private static final string pattern15_1 = "^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$"; 26 private static final string pattern15_2 = "^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$"; 27 private static final int[] rights = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1}; 28 private static final string[] checkdigits = {"1", "0", "x", "9", "8", "7", "6", "5", "4", "3", "2"}; 29 private static final string ssx[] = { "猪", "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗" }; 30 31 //省份编码集合 32 public static map<string, string> citycodes = new hashmap<string, string>(); 33 34 //台湾身份首字母对应数字 35 //public static map<string, integer> twfirstcode = new hashmap<string, integer>(); 36 //香港身份首字母对应数字 37 //public static map<string, integer> hkfirstcode = new hashmap<string, integer>(); 38 39 40 static { 41 citycodes.put("11", "北京"); 42 citycodes.put("12", "天津"); 43 citycodes.put("13", "河北"); 44 citycodes.put("14", "山西"); 45 citycodes.put("15", "内蒙古"); 46 citycodes.put("21", "辽宁"); 47 citycodes.put("22", "吉林"); 48 citycodes.put("23", "黑龙江"); 49 citycodes.put("31", "上海"); 50 citycodes.put("32", "江苏"); 51 citycodes.put("33", "浙江"); 52 citycodes.put("34", "安徽"); 53 citycodes.put("35", "福建"); 54 citycodes.put("36", "江西"); 55 citycodes.put("37", "山东"); 56 citycodes.put("41", "河南"); 57 citycodes.put("42", "湖北"); 58 citycodes.put("43", "湖南"); 59 citycodes.put("44", "广东"); 60 citycodes.put("45", "广西"); 61 citycodes.put("46", "海南"); 62 citycodes.put("50", "重庆"); 63 citycodes.put("51", "四川"); 64 citycodes.put("52", "贵州"); 65 citycodes.put("53", "云南"); 66 citycodes.put("54", "西藏"); 67 citycodes.put("61", "陕西"); 68 citycodes.put("62", "甘肃"); 69 citycodes.put("63", "青海"); 70 citycodes.put("64", "宁夏"); 71 citycodes.put("65", "新疆"); 72 citycodes.put("71", "台湾"); 73 citycodes.put("81", "香港"); 74 citycodes.put("82", "澳门"); 75 citycodes.put("91", "国外"); 76 /*twfirstcode.put("a", 10); 77 twfirstcode.put("b", 11); 78 twfirstcode.put("c", 12); 79 twfirstcode.put("d", 13); 80 twfirstcode.put("e", 14); 81 twfirstcode.put("f", 15); 82 twfirstcode.put("g", 16); 83 twfirstcode.put("h", 17); 84 twfirstcode.put("j", 18); 85 twfirstcode.put("k", 19); 86 twfirstcode.put("l", 20); 87 twfirstcode.put("m", 21); 88 twfirstcode.put("n", 22); 89 twfirstcode.put("p", 23); 90 twfirstcode.put("q", 24); 91 twfirstcode.put("r", 25); 92 twfirstcode.put("s", 26); 93 twfirstcode.put("t", 27); 94 twfirstcode.put("u", 28); 95 twfirstcode.put("v", 29); 96 twfirstcode.put("x", 30); 97 twfirstcode.put("y", 31); 98 twfirstcode.put("w", 32); 99 twfirstcode.put("z", 33); 100 twfirstcode.put("i", 34); 101 twfirstcode.put("o", 35); 102 hkfirstcode.put("a", 1); 103 hkfirstcode.put("b", 2); 104 hkfirstcode.put("c", 3); 105 hkfirstcode.put("r", 18); 106 hkfirstcode.put("u", 21); 107 hkfirstcode.put("z", 26); 108 hkfirstcode.put("x", 24); 109 hkfirstcode.put("w", 23); 110 hkfirstcode.put("o", 15); 111 hkfirstcode.put("n", 14);*/ 112 } 113 114 115 116 117 /** 118 * description 验证身份证是否合法 119 * @param cardno 身份证号 120 * @return true or false 121 * @author122 * @date 2019年9月20日 123 */ 124 public static boolean isvalididcard(string cardno) { 125 if (cardno == null) { 126 return false; 127 } 128 switch (cardno.length()) { 129 case 15 : 130 return verify15(cardno); 131 case 18 : 132 return verify18(cardno); 133 } 134 return false; 135 } 136 137 private static boolean verify15(string cardno) { 138 if (cardno.matches(pattern15_1)) { 139 return true; 140 } 141 return cardno.matches(pattern15_2); 142 } 143 144 private static boolean verify18(string cardno) { 145 if (cardno.matches(pattern18)) { 146 return cardno.substring(17).equalsignorecase(getcheck_digit18(cardno)); 147 } 148 return false; 149 } 150 private static string getcheck_digit18(string idcardno) { 151 int sum = 0; 152 for (int i = 0; i <= 16; i++) { 153 int num = integer.parseint(idcardno.substring(i, i + 1)); 154 int right = rights[i]; 155 sum += num * right; 156 } 157 int y = sum % 11; 158 return checkdigits[y]; 159 } 160 161 162 /** 163 * 根据身份证号获取生日年 164 * @param idcard 身份证号 165 * @return 生日(yyyy) 166 */ 167 public static string getyearbyidcard(string idcard) { 168 integer len = idcard.length(); 169 if (len < china_id_min_length) { 170 return null; 171 } else if (len == china_id_min_length) { 172 idcard = conver15cardto18(idcard); 173 } 174 return idcard.substring(6, 10); 175 } 176 177 /** 178 * 根据身份证号获取生日月 179 * @param idcard 身份证号 180 * @return 生日(mm) 181 */ 182 public static string getmonthbyidcard(string idcard) { 183 integer len = idcard.length(); 184 if (len < china_id_min_length) { 185 return null; 186 } else if (len == china_id_min_length) { 187 idcard = conver15cardto18(idcard); 188 } 189 return idcard.substring(10, 12); 190 } 191 192 /** 193 * 根据身份证号获取生日天 194 * @param idcard 身份证号 195 * @return 生日(dd) 196 */ 197 public static string getdatebyidcard(string idcard) { 198 integer len = idcard.length(); 199 if (len < china_id_min_length) { 200 return null; 201 } else if (len == china_id_min_length) { 202 idcard = conver15cardto18(idcard); 203 } 204 return idcard.substring(12, 14); 205 } 206 207 /** 208 * description 根据身份证获取获取年龄 209 * @param idcard 身份证号 210 * @return age 年龄 211 * @author212 * @date 2019年9月20日 213 */ 214 public static int getagebyidcard(string idcard) { 215 int iage = 0; 216 if (idcard.length() == china_id_min_length) { 217 idcard = conver15cardto18(idcard); 218 } 219 string year = idcard.substring(6, 10); 220 calendar cal = calendar.getinstance(); 221 int icurryear = cal.get(calendar.year); 222 iage = icurryear - integer.valueof(year); 223 return iage; 224 } 225 226 227 /** 228 * 根据身份证号获取性别 229 * @param idcard 身份证号 230 * @return 性别(m-男,f-女,n-未知) 231 */ 232 public static string getgenderbyidcard(string idcard) { 233 string sgender = "n"; 234 if (idcard.length() == china_id_min_length) { 235 idcard = conver15cardto18(idcard); 236 } 237 string scardnum = idcard.substring(16, 17); 238 if (integer.parseint(scardnum) % 2 != 0) { 239 sgender = "m"; 240 } else { 241 sgender = "f"; 242 } 243 return sgender; 244 } 245 246 247 /** 248 * 根据身份证号获取户籍省份 249 * @param idcard 身份编码 250 * @return 省级编码。 251 */ 252 public static string getprovincebyidcard(string idcard) { 253 int len = idcard.length(); 254 string sprovince = null; 255 string sprovinnum = ""; 256 if (len == china_id_min_length || len == china_id_max_length) { 257 sprovinnum = idcard.substring(0, 2); 258 } 259 sprovince = citycodes.get(sprovinnum); 260 return sprovince; 261 } 262 263 /** 264 * 根据身份证号,自动获取对应的生肖 265 * @param idcard 身份证号码 266 * @return 生肖 267 */ 268 public static string getzodiacbyidcard(string idcard) { // 根据身份证号,自动返回对应的生肖 269 if (!isvalididcard(idcard)){ 270 return "idcard error"; 271 } 272 int year = integer.valueof(getyearbyidcard(idcard)); 273 int end = 3; 274 int x = (year - end) % 12; 275 string retvalue = ""; 276 retvalue = ssx[x]; 277 return retvalue; 278 } 279 /** 280 * 根据身份证号获取对应的星座 281 * @param idcard: 身份证号 282 * @return 星座 283 */ 284 public static string getconstebyidcard(string idcard) { 285 string conste = ""; 286 if (idcard == null || !isvalididcard(idcard)) { 287 return null; 288 } else { 289 integer month = integer.valueof(getmonthbyidcard(idcard)); 290 integer day = integer.valueof(getdatebyidcard(idcard)); 291 if ((month == 1 && day >= 20) || (month == 2 && day <= 18)) { 292 conste = "水瓶座"; 293 } else if ((month == 2 && day >= 19) || (month == 3 && day <= 20)) { 294 conste = "双鱼座"; 295 } else if ((month == 3 && day > 20) || (month == 4 && day <= 19)) { 296 conste = "白羊座"; 297 } else if ((month == 4 && day >= 20) || (month == 5 && day <= 20)) { 298 conste = "金牛座"; 299 } else if ((month == 5 && day >= 21) || (month == 6 && day <= 21)) { 300 conste = "双子座"; 301 } else if ((month == 6 && day > 21) || (month == 7 && day <= 22)) { 302 conste = "巨蟹座"; 303 } else if ((month == 7 && day > 22) || (month == 8 && day <= 22)) { 304 conste = "狮子座"; 305 } else if ((month == 8 && day >= 23) || (month == 9 && day <= 22)) { 306 conste = "处女座"; 307 } else if ((month == 9 && day >= 23) || (month == 10 && day <= 23)) { 308 conste = "天秤座"; 309 } else if ((month == 10 && day > 23) || (month == 11 && day <= 22)) { 310 conste = "天蝎座"; 311 } else if ((month == 11 && day > 22) || (month == 12 && day <= 21)) { 312 conste = "射手座"; 313 } else if ((month == 12 && day > 21) || (month == 1 && day <= 19)) { 314 conste = "摩羯座"; 315 } 316 return conste; 317 } 318 } 319 320 321 322 323 324 325 /** 326 * 根据身份证号获取生日 327 * @param idcard 身份证号 328 * @return 生日(yyyymmdd) 329 */ 330 public static string getbirthbyidcard(string idcard){ 331 integer len = idcard.length(); 332 if (len < china_id_min_length) { 333 return null; 334 } else if (len == china_id_min_length) { 335 idcard = conver15cardto18(idcard); 336 } 337 return idcard.substring(6, 14); 338 } 339 /** 340 * 根据生日获取 生日年 yyyy 341 * @param idbirthday yyyy-mm-dd 342 * @return year 年份 343 */ 344 public static string getyearbydate(string strdate){ 345 return strdate.substring(0,4); 346 } 347 /** 348 * 根据生日获取 生日月 mm 349 * @param idbirthday yyyy-mm-dd 350 * @return month 351 */ 352 public static string getmonthbydate(string strdate){ 353 return strdate.substring(5,7); 354 } 355 /** 356 * 根据生日获取 生日天 dd 357 * @param idbirthday yyyy-mm-dd 358 * @return 359 */ 360 public static string getdaybydate(string strdate){ 361 return strdate.substring(8,10); 362 } 363 364 /** 365 * 根据生日获取用户年龄 yyyy-mm-dd 366 * @param idbirthday yyyy-mm-dd 367 * @return age 年龄 368 */ 369 public static integer getagebydate(string strdate){ 370 string year = getyearbydate(strdate); 371 calendar cal = calendar.getinstance(); 372 integer nowyear = cal.get(calendar.year); 373 integer age = nowyear-integer.valueof(year); 374 return age; 375 } 376 /** 377 * description 根据生日获取生肖 378 * @param idbirthday yyyy-mm-dd 379 * @return 380 * @author381 * @date 2019年9月20日 382 */ 383 public static string getzodiacbybirthday(string idbirthday) { 384 int year = integer.valueof(getyearbydate(idbirthday)); 385 int end = 3; 386 int x = (year - end) % 12; 387 string retvalue = ""; 388 retvalue = ssx[x]; 389 return retvalue; 390 } 391 392 /** 393 * 根据生日(yyyy-mm-dd)获取对应的星座 394 * @param idbirthday: (yyyy-mm-dd) 395 * @return 星座 396 */ 397 public static string getconstebybirthday(string idbirthday) { 398 string conste = ""; 399 if (idbirthday == null) { 400 return null; 401 } else { 402 integer month = integer.valueof(getmonthbydate(idbirthday)); 403 integer day = integer.valueof(getdaybydate(idbirthday)); 404 if ((month == 1 && day >= 20) || (month == 2 && day <= 18)) { 405 conste = "水瓶座"; 406 } else if ((month == 2 && day >= 19) || (month == 3 && day <= 20)) { 407 conste = "双鱼座"; 408 } else if ((month == 3 && day > 20) || (month == 4 && day <= 19)) { 409 conste = "白羊座"; 410 } else if ((month == 4 && day >= 20) || (month == 5 && day <= 20)) { 411 conste = "金牛座"; 412 } else if ((month == 5 && day >= 21) || (month == 6 && day <= 21)) { 413 conste = "双子座"; 414 } else if ((month == 6 && day > 21) || (month == 7 && day <= 22)) { 415 conste = "巨蟹座"; 416 } else if ((month == 7 && day > 22) || (month == 8 && day <= 22)) { 417 conste = "狮子座"; 418 } else if ((month == 8 && day >= 23) || (month == 9 && day <= 22)) { 419 conste = "处女座"; 420 } else if ((month == 9 && day >= 23) || (month == 10 && day <= 23)) { 421 conste = "天秤座"; 422 } else if ((month == 10 && day > 23) || (month == 11 && day <= 22)) { 423 conste = "天蝎座"; 424 } else if ((month == 11 && day > 22) || (month == 12 && day <= 21)) { 425 conste = "射手座"; 426 } else if ((month == 12 && day > 21) || (month == 1 && day <= 19)) { 427 conste = "摩羯座"; 428 } 429 return conste; 430 } 431 } 432 433 /** 434 * description 传入生日 ,身份证有效期开始时间,截止时间,判断当前身份证是否在合法的年限范围内 435 * 证件的有效期限(未满十六周岁:五年;十六周岁至二十五周岁:十年;二十六周岁至四十五周岁:二十年;四十六周岁以上:长期) 436 * @param birthday yyyy-mm-dd 437 * @param str_date yyyy-mm-dd 438 * @param end_date yyyy-mm-dd or 长期 439 * @return true or false 440 * @author441 * @date 2019年3月20日 442 */ 443 public static boolean islegalcard(string birthday,string str_date,string end_date){ 444 integer age = getagebydate(birthday);//获取年龄 445 if(age <= 16){//未成年不允许开卡 446 return false; 447 } 448 //获取当前身份证的有效期 449 if("长期".equals(end_date)){//长期的身份证-年龄应是四十六岁以上 450 if(age < 46){//长期期限 46岁以上 451 return false; 452 } 453 return true; 454 }else{//计算有效期限 455 string stryear = getyearbydate(str_date);//开始年限 456 string endyear = getyearbydate(end_date);//结束年限 457 //计算年限 458 integer time_limit = integer.valueof(endyear) - integer.valueof(stryear); 459 switch (time_limit) { 460 case 5://5年期限年龄在20岁以下 461 return age <=20 ?true:false; 462 case 10://10年期限 16~35岁 463 return 16<=age && age <= 35?true:false; 464 case 20://20年期限 26~65岁 465 return 26<=age && age <= 65?true:false; 466 default: 467 break; 468 } 469 return false; 470 } 471 } 472 473 474 /** 475 * description 验证身份证地址与签发机关所在公安局是否一致 (签发机关截取(县/市/区)公安局之前的部分,获得地名) 476 * @param addr 地址 例:江苏省阜宁县益林镇杨园新村一巷2号 477 * @param issu_organ 签发机关公安局 例:阜宁县公安局 478 * 截取后的签发地为:阜宁 479 * @return true or false 480 * @author481 * @date 2019年4月21日 482 */ 483 public static boolean stringiscontainsstr(string addr,string issu_organ){ 484 if(addr == null || issu_organ == null || addr == "" || issu_organ == ""|| addr.equals("") || issu_organ.equals("") || issu_organ.length() <= 3){ 485 return false; 486 } 487 issu_organ = issu_organ.substring(0, issu_organ.lastindexof("公安")-1);//截取签发机关所在地 488 if(issu_organ.trim() == "" || issu_organ.trim().equals("")){ 489 return false; 490 } 491 if(addr.contains(issu_organ)){ 492 return true; 493 }else{ 494 return false; 495 } 496 } 497 498 499 /** 500 * 将15位身份证号码转换为18位 501 * @param idcard 15位身份编码 502 * @return 18 位身份编码 503 */ 504 public static string conver15cardto18(string idcard) { 505 string idcard18 = ""; 506 if (idcard.length() != china_id_min_length) { 507 return null; 508 } 509 if (isnum(idcard)) { 510 // 获取出生年月日 511 string birthday = idcard.substring(6, 12); 512 date birthdate = null; 513 try { 514 birthdate = new simpledateformat("yymmdd").parse(birthday); 515 } catch (exception e) { 516 e.printstacktrace(); 517 } 518 calendar cal = calendar.getinstance(); 519 if (birthdate != null) 520 cal.settime(birthdate); 521 // 获取出生年(完全表现形式,如:2010) 522 string syear = string.valueof(cal.get(calendar.year)); 523 idcard18 = idcard.substring(0, 6) + syear + idcard.substring(8); 524 // 转换字符数组 525 char[] carr = idcard18.tochararray(); 526 if (carr != null) { 527 int[] icard = converchartoint(carr); 528 int isum17 = getpowersum(icard); 529 // 获取校验位 530 string sval = getcheckcode18(isum17); 531 if (sval.length() > 0) { 532 idcard18 += sval; 533 } else { 534 return null; 535 } 536 } 537 } else { 538 return null; 539 } 540 return idcard18; 541 } 542 543 /** 544 * 数字验证 545 * 546 * @param val 547 * @return 提取的数字。 548 */ 549 public static boolean isnum(string val) { 550 return val == null || "".equals(val) ? false : val.matches("^[0-9]*{1}"); 551 } 552 553 public static int[] converchartoint(char[] ca) { 554 int len = ca.length; 555 int[] iarr = new int[len]; 556 try { 557 for (int i = 0; i < len; i++) { 558 iarr[i] = integer.parseint(string.valueof(ca[i])); 559 } 560 } catch (numberformatexception e) { 561 e.printstacktrace(); 562 } 563 return iarr; 564 } 565 566 /** 567 * 将身份证的每位和对应位的加权因子相乘之后,再得到和值 568 * 569 * @param iarr 570 * @return 身份证编码。 571 */ 572 public static int getpowersum(int[] iarr) { 573 int isum = 0; 574 if (power.length == iarr.length) { 575 for (int i = 0; i < iarr.length; i++) { 576 for (int j = 0; j < power.length; j++) { 577 if (i == j) { 578 isum = isum + iarr[i] * power[j]; 579 } 580 } 581 } 582 } 583 return isum; 584 } 585 /** 586 * 将power和值与11取模获得余数进行校验码判断 587 * 588 * @param isum 589 * @return 校验位 590 */ 591 public static string getcheckcode18(int isum) { 592 string scode = ""; 593 switch (isum % 11) { 594 case 10: 595 scode = "2"; 596 break; 597 case 9: 598 scode = "3"; 599 break; 600 case 8: 601 scode = "4"; 602 break; 603 case 7: 604 scode = "5"; 605 break; 606 case 6: 607 scode = "6"; 608 break; 609 case 5: 610 scode = "7"; 611 break; 612 case 4: 613 scode = "8"; 614 break; 615 case 3: 616 scode = "9"; 617 break; 618 case 2: 619 scode = "x"; 620 break; 621 case 1: 622 scode = "0"; 623 break; 624 case 0: 625 scode = "1"; 626 break; 627 } 628 return scode; 629 } 630 631 632 633 660 661 }

《【工具类】身份证号码相关验证.doc》

下载本文的Word格式文档,以方便收藏与打印。