1.身份證規(guī)則
計算方法(來源百度)
- 將前面的身份證號碼17位數(shù)分別乘以不同的系數(shù)。從第一位到第十七位的系數(shù)分別為:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。
- 將這17位數(shù)字和系數(shù)相乘的結果相加。
- 用加出來和除以11,看余數(shù)是多少?
- 余數(shù)只可能有0-1-2-3-4-5-6-7-8-9-10這11個數(shù)字。其分別對應的最后一位身份證的號碼為1-0-X -9-8-7-6-5-4-3-2。(即余數(shù)0對應1,余數(shù)1對應0,余數(shù)2對應X…)
- 通過上面得知如果余數(shù)是3,就會在身份證的第18位數(shù)字上出現(xiàn)的是9。如果對應的數(shù)字是2,身份證的最后一位號碼就是羅馬數(shù)字x。
例如: 某男性的身份證號碼為【53010219200508011x】, 我們看看這個身份證是不是合法的身份證。
首先我們得出前17位的乘積和【(57)+(39)+(010)+(15)+(08)+(24)+(12)+(91)+(26)+(03)+(07)+(59)+(010)+(85)+(08)+(14)+(1*2)】是189,然后用189除以11得出的結果是189/11=17----2,也就是說其余數(shù)是2。最后通過對應規(guī)則就可以知道余數(shù)2對應的檢驗碼是X。所以,可以判定這是一個正確的身份證號碼。
2. 代碼邏輯
本工具類提供了3種類型校驗:
- 18位身份證號碼校驗
- 15位身份證號碼校驗(方法驗證不準確)
- 15位轉18位 身份證號碼校驗
18位身份證號合法性:
- 根據(jù)〖中華人民共和國國家標準GB11643-1999〗中有關公民身份號碼的規(guī)定,公民身份號碼是特征組合碼,由十七位數(shù)字本體碼和一位數(shù)字校驗碼組成。
- 排列順序從左至右依次為:六位數(shù)字地址碼,八位數(shù)字出生日期碼,三位數(shù)字順序碼和一位數(shù)字校驗碼。
- 順序碼: 表示在同一地址碼所標識的區(qū)域范圍內(nèi),對同年、同月、同 日出生的人編定的順序號,順序碼的奇數(shù)分配給男性,偶數(shù)分配 給女性。
- 前1、2位數(shù)字表示:所在省份的代碼; 2.第3、4位數(shù)字表示:所在城市的代碼; 3.第5、6位數(shù)字表示:所在區(qū)縣的代碼;
- 第7~14位數(shù)字表示:出生年、月、日; 5.第15、16位數(shù)字表示:所在地的派出所的代碼;
- 第17位數(shù)字表示性別:奇數(shù)表示男性,偶數(shù)表示女性;
- 第18位數(shù)字是校檢碼:也有的說是個人信息碼,一般是隨計算機的隨機產(chǎn)生,用來檢驗身份證的正確性。校檢碼可以是0~9的數(shù)字,有時也用x表示。
3.代碼
此工具類可以直接拷貝使用 并且提供了 main方法進行測試
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
|
/** * <p> * 類說明:身份證合法性校驗 * </p> * <p> * --15位身份證號碼:第7、8位為出生年份(兩位數(shù)),第9、10位為出生月份,第11、12位代表出生日期,第15位代表性別,奇數(shù)為男,偶數(shù)為女。 * --18位身份證號碼:第7、8、9、10位為出生年份(四位數(shù)),第11、第12位為出生月份,第13、14位代表出生日期,第17位代表性別,奇數(shù)為男,偶數(shù)為女。 * </p> */ /** * @Description: 身份證校驗工具類 * @author: xuxinku * @Date: 2020/9/07 10:55 * @ModifiedDate: * @Copyright:xx保險股份有限公司 */ @SuppressWarnings ({ "unchecked" , "unused" , "all" }) public class IdcardValidator { /** * 省,直轄市代碼表: { 11:"北京",12:"天津",13:"河北",14:"山西",15:"內(nèi)蒙古", * 21:"遼寧",22:"吉林",23:"黑龍江",31:"上海",32:"江蘇", * 33:"浙江",34:"安徽",35:"福建",36:"江西",37:"山東",41:"河南", * 42:"湖北",43:"湖南",44:"廣東",45:"廣西",46:"海南",50:"重慶", * 51:"四川",52:"貴州",53:"云南",54:"西藏",61:"陜西",62:"甘肅", * 63:"青海",64:"寧夏",65:"新疆",71:"臺灣",81:"香港",82:"澳門",91:"國外"} */ protected String codeAndCity[][] = { { "11" , "北京" }, { "12" , "天津" }, { "13" , "河北" }, { "14" , "山西" }, { "15" , "內(nèi)蒙古" }, { "21" , "遼寧" }, { "22" , "吉林" }, { "23" , "黑龍江" }, { "31" , "上海" }, { "32" , "江蘇" }, { "33" , "浙江" }, { "34" , "安徽" }, { "35" , "福建" }, { "36" , "江西" }, { "37" , "山東" }, { "41" , "河南" }, { "42" , "湖北" }, { "43" , "湖南" }, { "44" , "廣東" }, { "45" , "廣西" }, { "46" , "海南" }, { "50" , "重慶" }, { "51" , "四川" }, { "52" , "貴州" }, { "53" , "云南" }, { "54" , "西藏" }, { "61" , "陜西" }, { "62" , "甘肅" }, { "63" , "青海" }, { "64" , "寧夏" }, { "65" , "新疆" }, { "71" , "臺灣" }, { "81" , "香港" }, { "82" , "澳門" }, { "91" , "國外" } }; private String cityCode[] = { "11" , "12" , "13" , "14" , "15" , "21" , "22" , "23" , "31" , "32" , "33" , "34" , "35" , "36" , "37" , "41" , "42" , "43" , "44" , "45" , "46" , "50" , "51" , "52" , "53" , "54" , "61" , "62" , "63" , "64" , "65" , "71" , "81" , "82" , "91" }; // 每位加權因子 private int power[] = { 7 , 9 , 10 , 5 , 8 , 4 , 2 , 1 , 6 , 3 , 7 , 9 , 10 , 5 , 8 , 4 , 2 }; // 第18位校檢碼 private String verifyCode[] = { "1" , "0" , "X" , "9" , "8" , "7" , "6" , "5" , "4" , "3" , "2" }; /** * 驗證所有的身份證的合法性 * @param idcard * @return */ public boolean isValidatedAllIdcard(String idcard) { if (idcard.length() == 15 ) { idcard = this .convertIdcarBy15bit(idcard); } return this .isValidate18Idcard(idcard); } /** * <p> * 判斷18位身份證的合法性 * </p> * 根據(jù)〖中華人民共和國國家標準GB11643-1999〗中有關公民身份號碼的規(guī)定,公民身份號碼是特征組合碼,由十七位數(shù)字本體碼和一位數(shù)字校驗碼組成。 * 排列順序從左至右依次為:六位數(shù)字地址碼,八位數(shù)字出生日期碼,三位數(shù)字順序碼和一位數(shù)字校驗碼。 * <p> * 順序碼: 表示在同一地址碼所標識的區(qū)域范圍內(nèi),對同年、同月、同 日出生的人編定的順序號,順序碼的奇數(shù)分配給男性,偶數(shù)分配 給女性。 * </p> * <p> * 1.前1、2位數(shù)字表示:所在省份的代碼; 2.第3、4位數(shù)字表示:所在城市的代碼; 3.第5、6位數(shù)字表示:所在區(qū)縣的代碼; * 4.第7~14位數(shù)字表示:出生年、月、日; 5.第15、16位數(shù)字表示:所在地的派出所的代碼; * 6.第17位數(shù)字表示性別:奇數(shù)表示男性,偶數(shù)表示女性; * 7.第18位數(shù)字是校檢碼:也有的說是個人信息碼,一般是隨計算機的隨機產(chǎn)生,用來檢驗身份證的正確性。校檢碼可以是0~9的數(shù)字,有時也用x表示。 * </p> * <p> * 第十八位數(shù)字(校驗碼)的計算方法為: 1.將前面的身份證號碼17位數(shù)分別乘以不同的系數(shù)。從第一位到第十七位的系數(shù)分別為:7 9 10 5 8 4 * 2 1 6 3 7 9 10 5 8 4 2 * </p> * <p> * 2.將這17位數(shù)字和系數(shù)相乘的結果相加。 * </p> * <p> * 3.用加出來和除以11,看余數(shù)是多少? * </p> * 4.余數(shù)只可能有0 1 2 3 4 5 6 7 8 9 10這11個數(shù)字。其分別對應的最后一位身份證的號碼為1 0 X 9 8 7 6 5 4 3 * 2。 * <p> * 5.通過上面得知如果余數(shù)是2,就會在身份證的第18位數(shù)字上出現(xiàn)羅馬數(shù)字的Ⅹ。如果余數(shù)是10,身份證的最后一位號碼就是2。 * </p> * * @param idcard * @return */ public boolean isValidate18Idcard(String idcard) { // 非18位為假 if (idcard.length() != 18 ) { return false ; } // 獲取前17位 String idcard17 = idcard.substring( 0 , 17 ); // 獲取第18位 String idcard18Code = idcard.substring( 17 , 18 ); char c[] = null ; String checkCode = "" ; // 是否都為數(shù)字 if (isDigital(idcard17)) { c = idcard17.toCharArray(); } else { return false ; } if ( null != c) { int bit[] = new int [idcard17.length()]; bit = converCharToInt(c); int sum17 = 0 ; sum17 = getPowerSum(bit); // 將和值與11取模得到余數(shù)進行校驗碼判斷 checkCode = getCheckCodeBySum(sum17); if ( null == checkCode) { return false ; } // 將身份證的第18位與算出來的校碼進行匹配,不相等就為假 if (!idcard18Code.equalsIgnoreCase(checkCode)) { return false ; } } return true ; } /** * 驗證15位身份證的合法性,該方法驗證不準確,最好是將15轉為18位后再判斷,該類中已提供。 * * @param idcard * @return */ public boolean isValidate15Idcard(String idcard) { // 非15位為假 if (idcard.length() != 15 ) { return false ; } // 是否全都為數(shù)字 if (isDigital(idcard)) { String provinceid = idcard.substring( 0 , 2 ); String birthday = idcard.substring( 6 , 12 ); int year = Integer.parseInt(idcard.substring( 6 , 8 )); int month = Integer.parseInt(idcard.substring( 8 , 10 )); int day = Integer.parseInt(idcard.substring( 10 , 12 )); // 判斷是否為合法的省份 boolean flag = false ; for (String id : cityCode) { if (id.equals(provinceid)) { flag = true ; break ; } } if (!flag) { return false ; } // 該身份證生出日期在當前日期之后時為假 Date birthdate = null ; try { birthdate = new SimpleDateFormat( "yyMMdd" ).parse(birthday); } catch (ParseException e) { e.printStackTrace(); } if (birthdate == null || new Date().before(birthdate)) { return false ; } // 判斷是否為合法的年份 GregorianCalendar curDay = new GregorianCalendar(); int curYear = curDay.get(Calendar.YEAR); int year2bit = Integer.parseInt(String.valueOf(curYear) .substring( 2 )); // 判斷該年份的兩位表示法,小于50的和大于當前年份的,為假 if ((year < 50 && year > year2bit)) { return false ; } // 判斷是否為合法的月份 if (month < 1 || month > 12 ) { return false ; } // 判斷是否為合法的日期 boolean mflag = false ; curDay.setTime(birthdate); //將該身份證的出生日期賦于對象curDay switch (month) { case 1 : case 3 : case 5 : case 7 : case 8 : case 10 : case 12 : mflag = (day >= 1 && day <= 31 ); break ; case 2 : //公歷的2月非閏年有28天,閏年的2月是29天。 if (curDay.isLeapYear(curDay.get(Calendar.YEAR))) { mflag = (day >= 1 && day <= 29 ); } else { mflag = (day >= 1 && day <= 28 ); } break ; case 4 : case 6 : case 9 : case 11 : mflag = (day >= 1 && day <= 30 ); break ; } if (!mflag) { return false ; } } else { return false ; } return true ; } /** * 將15位的身份證轉成18位身份證 * * @param idcard * @return */ public String convertIdcarBy15bit(String idcard) { String idcard17 = null ; // 非15位身份證 if (idcard.length() != 15 ) { return null ; } if (isDigital(idcard)) { // 獲取出生年月日 String birthday = idcard.substring( 6 , 12 ); Date birthdate = null ; try { birthdate = new SimpleDateFormat( "yyMMdd" ).parse(birthday); } catch (ParseException e) { e.printStackTrace(); } Calendar cday = Calendar.getInstance(); cday.setTime(birthdate); String year = String.valueOf(cday.get(Calendar.YEAR)); idcard17 = idcard.substring( 0 , 6 ) + year + idcard.substring( 8 ); char c[] = idcard17.toCharArray(); String checkCode = "" ; if ( null != c) { int bit[] = new int [idcard17.length()]; // 將字符數(shù)組轉為整型數(shù)組 bit = converCharToInt(c); int sum17 = 0 ; sum17 = getPowerSum(bit); // 獲取和值與11取模得到余數(shù)進行校驗碼 checkCode = getCheckCodeBySum(sum17); // 獲取不到校驗位 if ( null == checkCode) { return null ; } // 將前17位與第18位校驗碼拼接 idcard17 += checkCode; } } else { // 身份證包含數(shù)字 return null ; } return idcard17; } /** * 15位和18位身份證號碼的基本數(shù)字和位數(shù)驗校 * * @param idcard * @return */ public boolean isIdcard(String idcard) { return idcard == null || "" .equals(idcard) ? false : Pattern.matches( "(^\\d{15}$)|(\\d{17}(?:\\d|x|X)$)" , idcard); } /** * 15位身份證號碼的基本數(shù)字和位數(shù)驗校 * * @param idcard * @return */ public boolean is15Idcard(String idcard) { return idcard == null || "" .equals(idcard) ? false : Pattern.matches( "^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$" , idcard); } /** * 18位身份證號碼的基本數(shù)字和位數(shù)驗校 * * @param idcard * @return */ public boolean is18Idcard(String idcard) { return Pattern .matches( "^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([\\d|x|X]{1})$" , idcard); } /** * 數(shù)字驗證 * * @param str * @return */ public boolean isDigital(String str) { return str == null || "" .equals(str) ? false : str.matches( "^[0-9]*$" ); } /** * 將身份證的每位和對應位的加權因子相乘之后,再得到和值 * * @param bit * @return */ public int getPowerSum( int [] bit) { int sum = 0 ; if (power.length != bit.length) { return sum; } for ( int i = 0 ; i < bit.length; i++) { for ( int j = 0 ; j < power.length; j++) { if (i == j) { sum = sum + bit[i] * power[j]; } } } return sum; } /** * 將和值與11取模得到余數(shù)進行校驗碼判斷 * * @param checkCode * @param sum17 * @return 校驗位 */ public String getCheckCodeBySum( int sum17) { String checkCode = null ; switch (sum17 % 11 ) { case 10 : checkCode = "2" ; break ; case 9 : checkCode = "3" ; break ; case 8 : checkCode = "4" ; break ; case 7 : checkCode = "5" ; break ; case 6 : checkCode = "6" ; break ; case 5 : checkCode = "7" ; break ; case 4 : checkCode = "8" ; break ; case 3 : checkCode = "9" ; break ; case 2 : checkCode = "x" ; break ; case 1 : checkCode = "0" ; break ; case 0 : checkCode = "1" ; break ; } return checkCode; } /** * 將字符數(shù)組轉為整型數(shù)組 * * @param c * @return * @throws NumberFormatException */ public int [] converCharToInt( char [] c) throws NumberFormatException { int [] a = new int [c.length]; int k = 0 ; for ( char temp : c) { a[k++] = Integer.parseInt(String.valueOf(temp)); } return a; } public static void main(String[] args) throws Exception { String idcard15 = "130503670401001" ; String idcard18 = "321321198810113333" ; String idcard = "130503670401001" ; IdcardValidator iv = new IdcardValidator(); boolean flag = false ; flag = iv.isValidate18Idcard(idcard18); System.out.println( "18位身份證號校驗" +flag); flag = iv.isValidate15Idcard(idcard15); System.out.println( "15位身份證號校驗" + flag); System.out.println( "15位轉18位身份證號" + iv.convertIdcarBy15bit(idcard15)); flag = iv.isValidate18Idcard(iv.convertIdcarBy15bit(idcard15)); System.out.println( "15位轉18位身份證號校驗" + flag); System.out.println( " 驗證所有的身份證的合法性" + iv.isValidatedAllIdcard(idcard)); } } |
總結
到此這篇關于java身份證合法性校驗工具類的文章就介紹到這了,更多相關java身份證合法性校驗工具類內(nèi)容請搜索服務器之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/xxk666/article/details/108470091