Java的身份证号码工具类
来源:互联网 发布:淘宝美工关联 编辑:程序博客网 时间:2024/05/22 09:04
实现从15位~18位的身份证号码转换,校验中国大陆公民身份证、香港居民身份证、澳门身份证和台湾身份证。
代码片段(1)
017
package
my.tools;
018
019
import
java.text.ParseException;
020
import
java.text.SimpleDateFormat;
021
import
java.util.Calendar;
022
import
java.util.Date;
023
import
java.util.HashMap;
024
import
java.util.Map;
025
026
import
org.apache.commons.lang.StringUtils;
027
028
/**
029
* 身份证工具类
030
*
031
* @author June
032
* @version 1.0, 2010-06-17
033
*/
034
public
class
IdcardUtils
extends
StringUtils {
035
036
/** 中国公民身份证号码最小长度。 */
037
public
static
final
int
CHINA_ID_MIN_LENGTH =
15
;
038
039
/** 中国公民身份证号码最大长度。 */
040
public
static
final
int
CHINA_ID_MAX_LENGTH =
18
;
041
042
/** 省、直辖市代码表 */
043
public
static
final
String cityCode[] = {
044
"11"
,
"12"
,
"13"
,
"14"
,
"15"
,
"21"
,
"22"
,
"23"
,
"31"
,
"32"
,
"33"
,
"34"
,
"35"
,
"36"
,
"37"
,
"41"
,
045
"42"
,
"43"
,
"44"
,
"45"
,
"46"
,
"50"
,
"51"
,
"52"
,
"53"
,
"54"
,
"61"
,
"62"
,
"63"
,
"64"
,
"65"
,
"71"
,
046
"81"
,
"82"
,
"91"
047
};
048
049
/** 每位加权因子 */
050
public
static
final
int
power[] = {
051
7
,
9
,
10
,
5
,
8
,
4
,
2
,
1
,
6
,
3
,
7
,
9
,
10
,
5
,
8
,
4
,
2
052
};
053
054
/** 第18位校检码 */
055
public
static
final
String verifyCode[] = {
056
"1"
,
"0"
,
"X"
,
"9"
,
"8"
,
"7"
,
"6"
,
"5"
,
"4"
,
"3"
,
"2"
057
};
058
/** 最低年限 */
059
public
static
final
int
MIN =
1930
;
060
public
static
Map<String, String> cityCodes =
new
HashMap<String, String>();
061
/** 台湾身份首字母对应数字 */
062
public
static
Map<String, Integer> twFirstCode =
new
HashMap<String, Integer>();
063
/** 香港身份首字母对应数字 */
064
public
static
Map<String, Integer> hkFirstCode =
new
HashMap<String, Integer>();
065
static
{
066
cityCodes.put(
"11"
,
"北京"
);
067
cityCodes.put(
"12"
,
"天津"
);
068
cityCodes.put(
"13"
,
"河北"
);
069
cityCodes.put(
"14"
,
"山西"
);
070
cityCodes.put(
"15"
,
"内蒙古"
);
071
cityCodes.put(
"21"
,
"辽宁"
);
072
cityCodes.put(
"22"
,
"吉林"
);
073
cityCodes.put(
"23"
,
"黑龙江"
);
074
cityCodes.put(
"31"
,
"上海"
);
075
cityCodes.put(
"32"
,
"江苏"
);
076
cityCodes.put(
"33"
,
"浙江"
);
077
cityCodes.put(
"34"
,
"安徽"
);
078
cityCodes.put(
"35"
,
"福建"
);
079
cityCodes.put(
"36"
,
"江西"
);
080
cityCodes.put(
"37"
,
"山东"
);
081
cityCodes.put(
"41"
,
"河南"
);
082
cityCodes.put(
"42"
,
"湖北"
);
083
cityCodes.put(
"43"
,
"湖南"
);
084
cityCodes.put(
"44"
,
"广东"
);
085
cityCodes.put(
"45"
,
"广西"
);
086
cityCodes.put(
"46"
,
"海南"
);
087
cityCodes.put(
"50"
,
"重庆"
);
088
cityCodes.put(
"51"
,
"四川"
);
089
cityCodes.put(
"52"
,
"贵州"
);
090
cityCodes.put(
"53"
,
"云南"
);
091
cityCodes.put(
"54"
,
"西藏"
);
092
cityCodes.put(
"61"
,
"陕西"
);
093
cityCodes.put(
"62"
,
"甘肃"
);
094
cityCodes.put(
"63"
,
"青海"
);
095
cityCodes.put(
"64"
,
"宁夏"
);
096
cityCodes.put(
"65"
,
"新疆"
);
097
cityCodes.put(
"71"
,
"台湾"
);
098
cityCodes.put(
"81"
,
"香港"
);
099
cityCodes.put(
"82"
,
"澳门"
);
100
cityCodes.put(
"91"
,
"国外"
);
101
twFirstCode.put(
"A"
,
10
);
102
twFirstCode.put(
"B"
,
11
);
103
twFirstCode.put(
"C"
,
12
);
104
twFirstCode.put(
"D"
,
13
);
105
twFirstCode.put(
"E"
,
14
);
106
twFirstCode.put(
"F"
,
15
);
107
twFirstCode.put(
"G"
,
16
);
108
twFirstCode.put(
"H"
,
17
);
109
twFirstCode.put(
"J"
,
18
);
110
twFirstCode.put(
"K"
,
19
);
111
twFirstCode.put(
"L"
,
20
);
112
twFirstCode.put(
"M"
,
21
);
113
twFirstCode.put(
"N"
,
22
);
114
twFirstCode.put(
"P"
,
23
);
115
twFirstCode.put(
"Q"
,
24
);
116
twFirstCode.put(
"R"
,
25
);
117
twFirstCode.put(
"S"
,
26
);
118
twFirstCode.put(
"T"
,
27
);
119
twFirstCode.put(
"U"
,
28
);
120
twFirstCode.put(
"V"
,
29
);
121
twFirstCode.put(
"X"
,
30
);
122
twFirstCode.put(
"Y"
,
31
);
123
twFirstCode.put(
"W"
,
32
);
124
twFirstCode.put(
"Z"
,
33
);
125
twFirstCode.put(
"I"
,
34
);
126
twFirstCode.put(
"O"
,
35
);
127
hkFirstCode.put(
"A"
,
1
);
128
hkFirstCode.put(
"B"
,
2
);
129
hkFirstCode.put(
"C"
,
3
);
130
hkFirstCode.put(
"R"
,
18
);
131
hkFirstCode.put(
"U"
,
21
);
132
hkFirstCode.put(
"Z"
,
26
);
133
hkFirstCode.put(
"X"
,
24
);
134
hkFirstCode.put(
"W"
,
23
);
135
hkFirstCode.put(
"O"
,
15
);
136
hkFirstCode.put(
"N"
,
14
);
137
}
138
139
/**
140
* 将15位身份证号码转换为18位
141
*
142
* @param idCard
143
* 15位身份编码
144
* @return 18位身份编码
145
*/
146
public
static
String conver15CardTo18(String idCard) {
147
String idCard18 =
""
;
148
if
(idCard.length() != CHINA_ID_MIN_LENGTH) {
149
return
null
;
150
}
151
if
(isNum(idCard)) {
152
// 获取出生年月日
153
String birthday = idCard.substring(
6
,
12
);
154
Date birthDate =
null
;
155
try
{
156
birthDate =
new
SimpleDateFormat(
"yyMMdd"
).parse(birthday);
157
}
catch
(ParseException e) {
158
e.printStackTrace();
159
}
160
Calendar cal = Calendar.getInstance();
161
if
(birthDate !=
null
)
162
cal.setTime(birthDate);
163
// 获取出生年(完全表现形式,如:2010)
164
String sYear = String.valueOf(cal.get(Calendar.YEAR));
165
idCard18 = idCard.substring(
0
,
6
) + sYear + idCard.substring(
8
);
166
// 转换字符数组
167
char
[] cArr = idCard18.toCharArray();
168
if
(cArr !=
null
) {
169
int
[] iCard = converCharToInt(cArr);
170
int
iSum17 = getPowerSum(iCard);
171
// 获取校验位
172
String sVal = getCheckCode18(iSum17);
173
if
(sVal.length() >
0
) {
174
idCard18 += sVal;
175
}
else
{
176
return
null
;
177
}
178
}
179
}
else
{
180
return
null
;
181
}
182
return
idCard18;
183
}
184
185
/**
186
* 验证身份证是否合法
187
*/
188
public
static
boolean
validateCard(String idCard) {
189
String card = idCard.trim();
190
if
(validateIdCard18(card)) {
191
return
true
;
192
}
193
if
(validateIdCard15(card)) {
194
return
true
;
195
}
196
String[] cardval = validateIdCard10(card);
197
if
(cardval !=
null
) {
198
if
(cardval[
2
].equals(
"true"
)) {
199
return
true
;
200
}
201
}
202
return
false
;
203
}
204
205
/**
206
* 验证18位身份编码是否合法
207
*
208
* @param idCard 身份编码
209
* @return 是否合法
210
*/
211
public
static
boolean
validateIdCard18(String idCard) {
212
boolean
bTrue =
false
;
213
if
(idCard.length() == CHINA_ID_MAX_LENGTH) {
214
// 前17位
215
String code17 = idCard.substring(
0
,
17
);
216
// 第18位
217
String code18 = idCard.substring(
17
, CHINA_ID_MAX_LENGTH);
218
if
(isNum(code17)) {
219
char
[] cArr = code17.toCharArray();
220
if
(cArr !=
null
) {
221
int
[] iCard = converCharToInt(cArr);
222
int
iSum17 = getPowerSum(iCard);
223
// 获取校验位
224
String val = getCheckCode18(iSum17);
225
if
(val.length() >
0
) {
226
if
(val.equalsIgnoreCase(code18)) {
227
bTrue =
true
;
228
}
229
}
230
}
231
}
232
}
233
return
bTrue;
234
}
235
236
/**
237
* 验证15位身份编码是否合法
238
*
239
* @param idCard
240
* 身份编码
241
* @return 是否合法
242
*/
243
public
static
boolean
validateIdCard15(String idCard) {
244
if
(idCard.length() != CHINA_ID_MIN_LENGTH) {
245
return
false
;
246
}
247
if
(isNum(idCard)) {
248
String proCode = idCard.substring(
0
,
2
);
249
if
(cityCodes.get(proCode) ==
null
) {
250
return
false
;
251
}
252
String birthCode = idCard.substring(
6
,
12
);
253
Date birthDate =
null
;
254
try
{
255
birthDate =
new
SimpleDateFormat(
"yy"
).parse(birthCode.substring(
0
,
2
));
256
}
catch
(ParseException e) {
257
e.printStackTrace();
258
}
259
Calendar cal = Calendar.getInstance();
260
if
(birthDate !=
null
)
261
cal.setTime(birthDate);
262
if
(!valiDate(cal.get(Calendar.YEAR), Integer.valueOf(birthCode.substring(
2
,
4
)),
263
Integer.valueOf(birthCode.substring(
4
,
6
)))) {
264
return
false
;
265
}
266
}
else
{
267
return
false
;
268
}
269
return
true
;
270
}
271
272
/**
273
* 验证10位身份编码是否合法
274
*
275
* @param idCard 身份编码
276
* @return 身份证信息数组
277
* <p>
278
* [0] - 台湾、澳门、香港 [1] - 性别(男M,女F,未知N) [2] - 是否合法(合法true,不合法false)
279
* 若不是身份证件号码则返回null
280
* </p>
281
*/
282
public
static
String[] validateIdCard10(String idCard) {
283
String[] info =
new
String[
3
];
284
String card = idCard.replaceAll(
"[\\(|\\)]"
,
""
);
285
if
(card.length() !=
8
&& card.length() !=
9
&& idCard.length() !=
10
) {
286
return
null
;
287
}
288
if
(idCard.matches(
"^[a-zA-Z][0-9]{9}$"
)) {
// 台湾
289
info[
0
] =
"台湾"
;
290
System.out.println(
"11111"
);
291
String char2 = idCard.substring(
1
,
2
);
292
if
(char2.equals(
"1"
)) {
293
info[
1
] =
"M"
;
294
System.out.println(
"MMMMMMM"
);
295
}
else
if
(char2.equals(
"2"
)) {
296
info[
1
] =
"F"
;
297
System.out.println(
"FFFFFFF"
);
298
}
else
{
299
info[
1
] =
"N"
;
300
info[
2
] =
"false"
;
301
System.out.println(
"NNNN"
);
302
return
info;
303
}
304
info[
2
] = validateTWCard(idCard) ?
"true"
:
"false"
;
305
}
else
if
(idCard.matches(
"^[1|5|7][0-9]{6}\\(?[0-9A-Z]\\)?$"
)) {
// 澳门
306
info[
0
] =
"澳门"
;
307
info[
1
] =
"N"
;
308
// TODO
309
}
else
if
(idCard.matches(
"^[A-Z]{1,2}[0-9]{6}\\(?[0-9A]\\)?$"
)) {
// 香港
310
info[
0
] =
"香港"
;
311
info[
1
] =
"N"
;
312
info[
2
] = validateHKCard(idCard) ?
"true"
:
"false"
;
313
}
else
{
314
return
null
;
315
}
316
return
info;
317
}
318
319
/**
320
* 验证台湾身份证号码
321
*
322
* @param idCard
323
* 身份证号码
324
* @return 验证码是否符合
325
*/
326
public
static
boolean
validateTWCard(String idCard) {
327
String start = idCard.substring(
0
,
1
);
328
String mid = idCard.substring(
1
,
9
);
329
String end = idCard.substring(
9
,
10
);
330
Integer iStart = twFirstCode.get(start);
331
Integer sum = iStart /
10
+ (iStart %
10
) *
9
;
332
char
[] chars = mid.toCharArray();
333
Integer iflag =
8
;
334
for
(
char
c : chars) {
335
sum = sum + Integer.valueOf(c +
""
) * iflag;
336
iflag--;
337
}
338
return
(sum %
10
==
0
?
0
: (
10
- sum %
10
)) == Integer.valueOf(end) ?
true
:
false
;
339
}
340
341
/**
342
* 验证香港身份证号码(存在Bug,部份特殊身份证无法检查)
343
* <p>
344
* 身份证前2位为英文字符,如果只出现一个英文字符则表示第一位是空格,对应数字58 前2位英文字符A-Z分别对应数字10-35
345
* 最后一位校验码为0-9的数字加上字符"A","A"代表10
346
* </p>
347
* <p>
348
* 将身份证号码全部转换为数字,分别对应乘9-1相加的总和,整除11则证件号码有效
349
* </p>
350
*
351
* @param idCard 身份证号码
352
* @return 验证码是否符合
353
*/
354
public
static
boolean
validateHKCard(String idCard) {
355
String card = idCard.replaceAll(
"[\\(|\\)]"
,
""
);
356
Integer sum =
0
;
357
if
(card.length() ==
9
) {
358
sum = (Integer.valueOf(card.substring(
0
,
1
).toUpperCase().toCharArray()[
0
]) -
55
) *
9
359
+ (Integer.valueOf(card.substring(
1
,
2
).toUpperCase().toCharArray()[
0
]) -
55
) *
8
;
360
card = card.substring(
1
,
9
);
361
}
else
{
362
sum =
522
+ (Integer.valueOf(card.substring(
0
,
1
).toUpperCase().toCharArray()[
0
]) -
55
) *
8
;
363
}
364
String mid = card.substring(
1
,
7
);
365
String end = card.substring(
7
,
8
);
366
char
[] chars = mid.toCharArray();
367
Integer iflag =
7
;
368
for
(
char
c : chars) {
369
sum = sum + Integer.valueOf(c +
""
) * iflag;
370
iflag--;
371
}
372
if
(end.toUpperCase().equals(
"A"
)) {
373
sum = sum +
10
;
374
}
else
{
375
sum = sum + Integer.valueOf(end);
376
}
377
return
(sum %
11
==
0
) ?
true
:
false
;
378
}
379
380
/**
381
* 将字符数组转换成数字数组
382
*
383
* @param ca
384
* 字符数组
385
* @return 数字数组
386
*/
387
public
static
int
[] converCharToInt(
char
[] ca) {
388
int
len = ca.length;
389
int
[] iArr =
new
int
[len];
390
try
{
391
for
(
int
i =
0
; i < len; i++) {
392
iArr[i] = Integer.parseInt(String.valueOf(ca[i]));
393
}
394
}
catch
(NumberFormatException e) {
395
e.printStackTrace();
396
}
397
return
iArr;
398
}
399
400
/**
401
* 将身份证的每位和对应位的加权因子相乘之后,再得到和值
402
*
403
* @param iArr
404
* @return 身份证编码。
405
*/
406
public
static
int
getPowerSum(
int
[] iArr) {
407
int
iSum =
0
;
408
if
(power.length == iArr.length) {
409
for
(
int
i =
0
; i < iArr.length; i++) {
410
for
(
int
j =
0
; j < power.length; j++) {
411
if
(i == j) {
412
iSum = iSum + iArr[i] * power[j];
413
}
414
}
415
}
416
}
417
return
iSum;
418
}
419
420
/**
421
* 将power和值与11取模获得余数进行校验码判断
422
*
423
* @param iSum
424
* @return 校验位
425
*/
426
public
static
String getCheckCode18(
int
iSum) {
427
String sCode =
""
;
428
switch
(iSum %
11
) {
429
case
10
:
430
sCode =
"2"
;
431
break
;
432
case
9
:
433
sCode =
"3"
;
434
break
;
435
case
8
:
436
sCode =
"4"
;
437
break
;
438
case
7
:
439
sCode =
"5"
;
440
break
;
441
case
6
:
442
sCode =
"6"
;
443
break
;
444
case
5
:
445
sCode =
"7"
;
446
break
;
447
case
4
:
448
sCode =
"8"
;
449
break
;
450
case
3
:
451
sCode =
"9"
;
452
break
;
453
case
2
:
454
sCode =
"x"
;
455
break
;
456
case
1
:
457
sCode =
"0"
;
458
break
;
459
case
0
:
460
sCode =
"1"
;
461
break
;
462
}
463
return
sCode;
464
}
465
466
/**
467
* 根据身份编号获取年龄
468
*
469
* @param idCard
470
* 身份编号
471
* @return 年龄
472
*/
473
public
static
int
getAgeByIdCard(String idCard) {
474
int
iAge =
0
;
475
if
(idCard.length() == CHINA_ID_MIN_LENGTH) {
476
idCard = conver15CardTo18(idCard);
477
}
478
String year = idCard.substring(
6
,
10
);
479
Calendar cal = Calendar.getInstance();
480
int
iCurrYear = cal.get(Calendar.YEAR);
481
iAge = iCurrYear - Integer.valueOf(year);
482
return
iAge;
483
}
484
485
/**
486
* 根据身份编号获取生日
487
*
488
* @param idCard 身份编号
489
* @return 生日(yyyyMMdd)
490
*/
491
public
static
String getBirthByIdCard(String idCard) {
492
Integer len = idCard.length();
493
if
(len < CHINA_ID_MIN_LENGTH) {
494
return
null
;
495
}
else
if
(len == CHINA_ID_MIN_LENGTH) {
496
idCard = conver15CardTo18(idCard);
497
}
498
return
idCard.substring(
6
,
14
);
499
}
500
501
/**
502
* 根据身份编号获取生日年
503
*
504
* @param idCard 身份编号
505
* @return 生日(yyyy)
506
*/
507
public
static
Short getYearByIdCard(String idCard) {
508
Integer len = idCard.length();
509
if
(len < CHINA_ID_MIN_LENGTH) {
510
return
null
;
511
}
else
if
(len == CHINA_ID_MIN_LENGTH) {
512
idCard = conver15CardTo18(idCard);
513
}
514
return
Short.valueOf(idCard.substring(
6
,
10
));
515
}
516
517
/**
518
* 根据身份编号获取生日月
519
*
520
* @param idCard
521
* 身份编号
522
* @return 生日(MM)
523
*/
524
public
static
Short getMonthByIdCard(String idCard) {
525
Integer len = idCard.length();
526
if
(len < CHINA_ID_MIN_LENGTH) {
527
return
null
;
528
}
else
if
(len == CHINA_ID_MIN_LENGTH) {
529
idCard = conver15CardTo18(idCard);
530
}
531
return
Short.valueOf(idCard.substring(
10
,
12
));
532
}
533
534
/**
535
* 根据身份编号获取生日天
536
*
537
* @param idCard
538
* 身份编号
539
* @return 生日(dd)
540
*/
541
public
static
Short getDateByIdCard(String idCard) {
542
Integer len = idCard.length();
543
if
(len < CHINA_ID_MIN_LENGTH) {
544
return
null
;
545
}
else
if
(len == CHINA_ID_MIN_LENGTH) {
546
idCard = conver15CardTo18(idCard);
547
}
548
return
Short.valueOf(idCard.substring(
12
,
14
));
549
}
550
551
/**
552
* 根据身份编号获取性别
553
*
554
* @param idCard 身份编号
555
* @return 性别(M-男,F-女,N-未知)
556
*/
557
public
static
String getGenderByIdCard(String idCard) {
558
String sGender =
"N"
;
559
if
(idCard.length() == CHINA_ID_MIN_LENGTH) {
560
idCard = conver15CardTo18(idCard);
561
}
562
String sCardNum = idCard.substring(
16
,
17
);
563
if
(Integer.parseInt(sCardNum) %
2
!=
0
) {
564
sGender =
"M"
;
565
}
else
{
566
sGender =
"F"
;
567
}
568
return
sGender;
569
}
570
571
/**
572
* 根据身份编号获取户籍省份
573
*
574
* @param idCard 身份编码
575
* @return 省级编码。
576
*/
577
public
static
String getProvinceByIdCard(String idCard) {
578
int
len = idCard.length();
579
String sProvince =
null
;
580
String sProvinNum =
""
;
581
if
(len == CHINA_ID_MIN_LENGTH || len == CHINA_ID_MAX_LENGTH) {
582
sProvinNum = idCard.substring(
0
,
2
);
583
}
584
sProvince = cityCodes.get(sProvinNum);
585
return
sProvince;
586
}
587
588
/**
589
* 数字验证
590
*
591
* @param val
592
* @return 提取的数字。
593
*/
594
public
static
boolean
isNum(String val) {
595
return
val ==
null
||
""
.equals(val) ?
false
: val.matches(
"^[0-9]*$"
);
596
}
597
598
/**
599
* 验证小于当前日期 是否有效
600
*
601
* @param iYear
602
* 待验证日期(年)
603
* @param iMonth
604
* 待验证日期(月 1-12)
605
* @param iDate
606
* 待验证日期(日)
607
* @return 是否有效
608
*/
609
public
static
boolean
valiDate(
int
iYear,
int
iMonth,
int
iDate) {
610
Calendar cal = Calendar.getInstance();
611
int
year = cal.get(Calendar.YEAR);
612
int
datePerMonth;
613
if
(iYear < MIN || iYear >= year) {
614
return
false
;
615
}
616
if
(iMonth <
1
|| iMonth >
12
) {
617
return
false
;
618
}
619
switch
(iMonth) {
620
case
4
:
621
case
6
:
622
case
9
:
623
case
11
:
624
datePerMonth =
30
;
625
break
;
626
case
2
:
627
boolean
dm = ((iYear %
4
==
0
&& iYear %
100
!=
0
) || (iYear %
400
==
0
))
628
&& (iYear > MIN && iYear < year);
629
datePerMonth = dm ?
29
:
28
;
630
break
;
631
default
:
632
datePerMonth =
31
;
633
}
634
return
(iDate >=
1
) && (iDate <= datePerMonth);
635
}
636
}
0 0
- Java的身份证号码工具类
- Java的身份证号码工具类
- Java的身份证号码工具类
- Java的身份证号码工具类
- Java的身份证号码工具类
- Java的身份证号码工具类
- Java的身份证号码工具类
- Java的身份证号码工具类
- Java的身份证号码工具类
- Java的身份证号码工具类
- Java的身份证号码工具类
- 工具类之Java的身份证号码工具类
- java 身份证号码 验证 工具类
- Java 身份证号码验证工具类
- Java工具类 验证身份证号码是否规范
- 身份证号码验证的工具类,学习备用
- Java_身份证号码工具类
- 身份证号码工具类
- SVN上箭头都是什么意思,红色灰色蓝色的
- 手动部署Eclipse内的项目至Tomcat中
- Web测试点-登录,搜索,翻页,输入框
- 学生账号部署XAP程序,在Lumia手机上
- Oracle 11.2.0.1 INS-32025 INS-52001 解决方法
- Java的身份证号码工具类
- 小陈的站正式启用,欢迎造访。
- java.util.ConcurrentModificationException异常
- 黑马程序员_java截图工具
- 伪静态及其原理实现
- Jpcap学习笔记0--Jpcap帮助文档
- Openshift + GOLANG
- 再析数学与编程
- 搬运工 Struts2 Action的单元测试