博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
身份证合法性校验
阅读量:4189 次
发布时间:2019-05-26

本文共 8850 字,大约阅读时间需要 29 分钟。

package com.tzz.utils;
2.
3.import java.text.ParseException;
4.import java.text.SimpleDateFormat;
5.import java.util.Calendar;
6.import java.util.Date;
7.
8./**
9. * <p>
10. * 身份证合法性校验
11. * </p>
12. *
13. * <pre>
14. * --15位身份证号码:第7、8位为出生年份(两位数),第9、10位为出生月份,第11、12位代表出生日期,第15位代表性别,奇数为男,偶数为女。
15. * --18位身份证号码:第7、8、9、10位为出生年份(四位数),第11、第12位为出生月份,第13、14位代表出生日期,第17位代表性别,奇数为男,偶数为女。
16. * 最后一位为校验位
17. * </pre>
18. *
19. * @author 313921
20. */
21.public class IdcardValidator {
22.
23. /**
24. * <pre>
25. * 省、直辖市代码表:
26. * 11 : 北京 12 : 天津 13 : 河北 14 : 山西 15 : 内蒙古
27. * 21 : 辽宁 22 : 吉林 23 : 黑龙江 31 : 上海 32 : 江苏
28. * 33 : 浙江 34 : 安徽 35 : 福建 36 : 江西 37 : 山东
29. * 41 : 河南 42 : 湖北 43 : 湖南 44 : 广东 45 : 广西 46 : 海南
30. * 50 : 重庆 51 : 四川 52 : 贵州 53 : 云南 54 : 西藏
31. * 61 : 陕西 62 : 甘肃 63 : 青海 64 : 宁夏 65 : 新疆
32. * 71 : 台湾
33. * 81 : 香港 82 : 澳门
34. * 91 : 国外
35. * </pre>
36. */
37. private static String cityCode[] = { "11", "12", "13", "14", "15", "21",
38. "22", "23", "31", "32", "33", "34", "35", "36", "37", "41", "42",
39. "43", "44", "45", "46", "50", "51", "52", "53", "54", "61", "62",
40. "63", "64", "65", "71", "81", "82", "91" };
41.
42. /**
43. * 每位加权因子
44. */
45. private static int power[] = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5,
46. 8, 4, 2 };
47.
48. /**
49. * 验证所有的身份证的合法性
50. *
51. * @param idcard
52. * 身份证
53. * @return 合法返回true,否则返回false
54. */
55. public static boolean isValidatedAllIdcard(String idcard) {
56. if (idcard == null || "".equals(idcard)) {
57. return false;
58. }
59. if (idcard.length() == 15) {
60. return validate15IDCard(idcard);
61. }
62. return validate18Idcard(idcard);
63. }
64.
65. /**
66. * <p>
67. * 判断18位身份证的合法性
68. * </p>
69. * 根据〖中华人民共和国国家标准GB11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。
70. * 排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。
71. * <p>
72. * 顺序码: 表示在同一地址码所标识的区域范围内,对同年、同月、同 日出生的人编定的顺序号,顺序码的奇数分配给男性,偶数分配 给女性。
73. * </p>
74. * <p>
75. * 1.前1、2位数字表示:所在省份的代码; 2.第3、4位数字表示:所在城市的代码; 3.第5、6位数字表示:所在区县的代码;
76. * 4.第7~14位数字表示:出生年、月、日; 5.第15、16位数字表示:所在地的派出所的代码;
77. * 6.第17位数字表示性别:奇数表示男性,偶数表示女性;
78. * 7.第18位数字是校检码:也有的说是个人信息码,一般是随计算机的随机产生,用来检验身份证的正确性。校检码可以是0~9的数字,有时也用x表示。
79. * </p>
80. * <p>
81. * 第十八位数字(校验码)的计算方法为: 1.将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7 9 10 5 8 4
82. * 2 1 6 3 7 9 10 5 8 4 2
83. * </p>
84. * <p>
85. * 2.将这17位数字和系数相乘的结果相加。
86. * </p>
87. * <p>
88. * 3.用加出来和除以11,看余数是多少
89. * </p>
90. * 4.余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3
91. * 2。
92. * <p>
93. * 5.通过上面得知如果余数是2,就会在身份证的第18位数字上出现罗马数字的Ⅹ。如果余数是10,身份证的最后一位号码就是2。
94. * </p>
95. *
96. * @param idcard
97. * @return
98. */
99. public static boolean validate18Idcard(String idcard) {
100. if (idcard == null) {
101. return false;
102. }
103.
104. // 非18位为假
105. if (idcard.length() != 18) {
106. return false;
107. }
108. // 获取前17位
109. String idcard17 = idcard.substring(0, 17);
110.
111. // 前17位全部为数字
112. if (!isDigital(idcard17)) {
113. return false;
114. }
115.
116. String provinceid = idcard.substring(0, 2);
117. // 校验省份
118. if (!checkProvinceid(provinceid)) {
119. return false;
120. }
121.
122. // 校验出生日期
123. String birthday = idcard.substring(6, 14);
124.
125. SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
126.
127. try {
128. Date birthDate = sdf.parse(birthday);
129. String tmpDate = sdf.format(birthDate);
130. if (!tmpDate.equals(birthday)) {// 出生年月日不正确
131. return false;
132. }
133.
134. } catch (ParseException e1) {
135.
136. return false;
137. }
138.
139. // 获取第18位
140. String idcard18Code = idcard.substring(17, 18);
141.
142. char c[] = idcard17.toCharArray();
143.
144. int bit[] = converCharToInt(c);
145.
146. int sum17 = 0;
147.
148. sum17 = getPowerSum(bit);
149.
150. // 将和值与11取模得到余数进行校验码判断
151. String checkCode = getCheckCodeBySum(sum17);
152. if (null == checkCode) {
153. return false;
154. }
155. // 将身份证的第18位与算出来的校码进行匹配,不相等就为假
156. if (!idcard18Code.equalsIgnoreCase(checkCode)) {
157. return false;
158. }
159.
160. return true;
161. }
162.
163. /**
164. * 校验15位身份证
165. *
166. * <pre>
167. * 只校验省份和出生年月日
168. * </pre>
169. *
170. * @param idcard
171. * @return
172. */
173. public static boolean validate15IDCard(String idcard) {
174. if (idcard == null) {
175. return false;
176. }
177. // 非15位为假
178. if (idcard.length() != 15) {
179. return false;
180. }
181.
182. // 15全部为数字
183. if (!isDigital(idcard)) {
184. return false;
185. }
186.
187. String provinceid = idcard.substring(0, 2);
188. // 校验省份
189. if (!checkProvinceid(provinceid)) {
190. return false;
191. }
192.
193. String birthday = idcard.substring(6, 12);
194.
195. SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
196.
197. try {
198. Date birthDate = sdf.parse(birthday);
199. String tmpDate = sdf.format(birthDate);
200. if (!tmpDate.equals(birthday)) {// 身份证日期错误
201. return false;
202. }
203.
204. } catch (ParseException e1) {
205.
206. return false;
207. }
208.
209. return true;
210. }
211.
212. /**
213. * 将15位的身份证转成18位身份证
214. *
215. * @param idcard
216. * @return
217. */
218. public static String convertIdcarBy15bit(String idcard) {
219. if (idcard == null) {
220. return null;
221. }
222.
223. // 非15位身份证
224. if (idcard.length() != 15) {
225. return null;
226. }
227.
228. // 15全部为数字
229. if (!isDigital(idcard)) {
230. return null;
231. }
232.
233. String provinceid = idcard.substring(0, 2);
234. // 校验省份
235. if (!checkProvinceid(provinceid)) {
236. return null;
237. }
238.
239. String birthday = idcard.substring(6, 12);
240.
241. SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
242.
243. Date birthdate = null;
244. try {
245. birthdate = sdf.parse(birthday);
246. String tmpDate = sdf.format(birthdate);
247. if (!tmpDate.equals(birthday)) {// 身份证日期错误
248. return null;
249. }
250.
251. } catch (ParseException e1) {
252. return null;
253. }
254.
255. Calendar cday = Calendar.getInstance();
256. cday.setTime(birthdate);
257. String year = String.valueOf(cday.get(Calendar.YEAR));
258.
259. String idcard17 = idcard.substring(0, 6) + year + idcard.substring(8);
260.
261. char c[] = idcard17.toCharArray();
262. String checkCode = "";
263.
264. // 将字符数组转为整型数组
265. int bit[] = converCharToInt(c);
266.
267. int sum17 = 0;
268. sum17 = getPowerSum(bit);
269.
270. // 获取和值与11取模得到余数进行校验码
271. checkCode = getCheckCodeBySum(sum17);
272.
273. // 获取不到校验位
274. if (null == checkCode) {
275. return null;
276. }
277. // 将前17位与第18位校验码拼接
278. idcard17 += checkCode;
279. return idcard17;
280. }
281.
282. /**
283. * 校验省份
284. *
285. * @param provinceid
286. * @return 合法返回TRUE,否则返回FALSE
287. */
288. private static boolean checkProvinceid(String provinceid) {
289. for (String id : cityCode) {
290. if (id.equals(provinceid)) {
291. return true;
292. }
293. }
294. return false;
295. }
296.
297. /**
298. * 数字验证
299. *
300. * @param str
301. * @return
302. */
303. private static boolean isDigital(String str) {
304. return str.matches("^[0-9]*$");
305. }
306.
307. /**
308. * 将身份证的每位和对应位的加权因子相乘之后,再得到和值
309. *
310. * @param bit
311. * @return
312. */
313. private static int getPowerSum(int[] bit) {
314.
315. int sum = 0;
316.
317. if (power.length != bit.length) {
318. return sum;
319. }
320.
321. for (int i = 0; i < bit.length; i++) {
322. for (int j = 0; j < power.length; j++) {
323. if (i == j) {
324. sum = sum + bit[i] * power[j];
325. }
326. }
327. }
328. return sum;
329. }
330.
331. /**
332. * 将和值与11取模得到余数进行校验码判断
333. *
334. * @param checkCode
335. * @param sum17
336. * @return 校验位
337. */
338. private static String getCheckCodeBySum(int sum17) {
339. String checkCode = null;
340. switch (sum17 % 11) {
341. case 10:
342. checkCode = "2";
343. break;
344. case 9:
345. checkCode = "3";
346. break;
347. case 8:
348. checkCode = "4";
349. break;
350. case 7:
351. checkCode = "5";
352. break;
353. case 6:
354. checkCode = "6";
355. break;
356. case 5:
357. checkCode = "7";
358. break;
359. case 4:
360. checkCode = "8";
361. break;
362. case 3:
363. checkCode = "9";
364. break;
365. case 2:
366. checkCode = "x";
367. break;
368. case 1:
369. checkCode = "0";
370. break;
371. case 0:
372. checkCode = "1";
373. break;
374. }
375. return checkCode;
376. }
377.
378. /**
379. * 将字符数组转为整型数组
380. *
381. * @param c
382. * @return
383. * @throws NumberFormatException
384. */
385. private static int[] converCharToInt(char[] c) throws NumberFormatException {
386. int[] a = new int[c.length];
387. int k = 0;
388. for (char temp : c) {
389. a[k++] = Integer.parseInt(String.valueOf(temp));
390. }
391. return a;
392. }
393.
394. public static void main(String[] args) throws Exception {
395. String idcard15 = "130321860311519";
396. String idcard18 = "210102198617083732";//
397. // 15位身份证
398. System.out.println(isValidatedAllIdcard(idcard15));
399. // 18位身份证
400. System.out.println(isValidatedAllIdcard(idcard18));
401. // 15位身份证转18位身份证
402. System.out.println(convertIdcarBy15bit(idcard15));
403. }
404.}

转载地址:http://sknoi.baihongyu.com/

你可能感兴趣的文章
异构数据源海量数据交换工具-Taobao DataX 下载和使用
查看>>
代理模式解析,静态代理、动态代理一文全都告诉你
查看>>
我是如何从电脑小白走上编程之路
查看>>
想成为优秀的Java程序员,你需要读哪些书?
查看>>
Java并发| Atomic包下的原子操作类使用与原理解析
查看>>
Mac M1 安装 iTerm2+Oh My Zsh+zsh-syntax-highlighting 真香!
查看>>
M1芯片Mac 安装git
查看>>
M1芯片Mac Homebrew 安装
查看>>
一篇文章看懂ZooKeeper内部原理
查看>>
全面理解Java内存模型
查看>>
Java类型信息详解
查看>>
深入理解Java线程池
查看>>
Java线程堆栈分析
查看>>
Java中子类能否继承父类的私有属性和方法
查看>>
JVM内存模型详解
查看>>
(二)Git--工作区和暂存区、管理修改与撤销
查看>>
(七)Git--自定义Git
查看>>
(五)Git--分支管理
查看>>
(四)Git--远程仓库
查看>>
(六) Git--标签管理
查看>>