function
checkIdcard(idcard)
{
var
area
=
{
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
:
"
国外
"
}
var
idcard,Y,JYM;
var
S,M;
var
idcard_array
=
new
Array();
idcard_array
=
idcard.split(
""
);
//
地区检验
if
(area[parseInt(idcard.substr(
0
,
2
))]
==
null
)
return
4
;
//
身份号码位数及格式检验
switch
(idcard.length){
case
15
:
if
( (parseInt(idcard.substr(
6
,
2
))
+
1900
)
%
4
==
0
||
((parseInt(idcard.substr(
6
,
2
))
+
1900
)
%
100
==
0
&&
(parseInt(idcard.substr(
6
,
2
))
+
1900
)
%
4
==
0
)){
ereg
=/^
[
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
}$
/
;
//
测试出生日期的合法性
}
else
{
ereg
=/^
[
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
}$
/
;
//
测试出生日期的合法性
}
if
(ereg.test(idcard))
return
0
;
else
return
2
;
break
;
case
18
:
//
18位身份号码检测
//
出生日期的合法性检查
//
闰年月日:((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]))
//
平年月日:((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]))
if
( parseInt(idcard.substr(
6
,
4
))
%
4
==
0
||
(parseInt(idcard.substr(
6
,
4
))
%
100
==
0
&&
parseInt(idcard.substr(
6
,
4
))
%
4
==
0
)){
ereg
=/^
[
1
-
9
][
0
-
9
]{
5
}
19
[
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
}[
0
-
9Xx]$
/
;
//
闰年出生日期的合法性正则表达式
}
else
{
ereg
=/^
[
1
-
9
][
0
-
9
]{
5
}
19
[
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
}[
0
-
9Xx]$
/
;
//
平年出生日期的合法性正则表达式
}
if
(ereg.test(idcard)){
//
测试出生日期的合法性
//
计算校验位
S
=
(parseInt(idcard_array[
0
])
+
parseInt(idcard_array[
10
]))
*
7
+
(parseInt(idcard_array[
1
])
+
parseInt(idcard_array[
11
]))
*
9
+
(parseInt(idcard_array[
2
])
+
parseInt(idcard_array[
12
]))
*
10
+
(parseInt(idcard_array[
3
])
+
parseInt(idcard_array[
13
]))
*
5
+
(parseInt(idcard_array[
4
])
+
parseInt(idcard_array[
14
]))
*
8
+
(parseInt(idcard_array[
5
])
+
parseInt(idcard_array[
15
]))
*
4
+
(parseInt(idcard_array[
6
])
+
parseInt(idcard_array[
16
]))
*
2
+
parseInt(idcard_array[
7
])
*
1
+
parseInt(idcard_array[
8
])
*
6
+
parseInt(idcard_array[
9
])
*
3
;
Y
=
S
%
11
;
if
(idcard_array[
17
]
==
"
x
"
)
{
idcard_array[
17
]
=
"
X
"
;
}
//
alert(Y);
//
M = "F";
JYM
=
"
10X98765432
"
;
M
=
JYM.substr(Y,
1
);
//
判断校验位
if
(M
==
idcard_array[
17
] )
return
0
;
//
检测ID的校验位
else
return
3
;
}
else
return
2
;
break
;
default
:
return
1
;
break
;
}
}
2
var
Errors
=
new
Array(
"
验证通过!
"
,
"
身份证号码位数不对!
"
,
"
身份证号码出生日期超出范围或含有非法字符!
"
,
"
身份证号码校验错误!
"
,
"
身份证地区非法!
"
);
var
result
=
checkIdcard(IDCardNoValue);
if
(result
!=
0
)
...
{
//你的代码 here
}
3
'
'' -----------------------------------------------------------------------------
'
'' <summary>
'
'' 将15位的身份证号码升级到18位
'
'' </summary>
'
'' <param name="IDCard15">15位的身份证号码</param>
'
'' <returns>18位的身份证号码</returns>
'
'' <remarks>
'
'' 根据〖中华人民共和国国家标准 GB 11643-1999〗中有关公民身份号码的规定,公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。
'
'' 排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码, 三位数字顺序码和一位数字校验码。
'
'' 地址码表示编码对象常住户口所在县(市、旗、区)的行政区划代码。
'
'' 生日期码表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。
'
'' 顺序码表示同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。
'
'' 顺序码的奇数分给男性,偶数分给女性。
'
'' 校验码是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。
'
''
'
'' 注意:这里没有考虑1900年以及之前出生的人的情况
'
''
'
'' </remarks>
'
'' <history>
'
'' [Hudan] 2005-8-8 Created
'
'' </history>
'
'' -----------------------------------------------------------------------------
Public
Function
IDCard15to18(
ByVal
IDCard15
As
String
)
As
String
Dim
IDCard17
As
String
'
将出生年扩展为4位,即在2位数的出生年前面加19 (这里没有考虑1900年以及之前出生的人的情况)
'
IDCard18 = IDCard15.Substring(0, 6) + "19" + IDCard15.Substring(6)
IDCard17
=
IDCard15.Insert(
6
,
"
19
"
)
'
计算校验码
Dim
code
As
Char
code
=
GetCheckCode(IDCard17)
'
返回18位身份证号码
Return
IDCard17
+
code.ToString()
End Function
'
'' -----------------------------------------------------------------------------
'
'' <summary>
'
'' 判断身份证号码的校验码是否正确
'
'' </summary>
'
'' <param name="IDCard18">18位身份证号码</param>
'
'' <returns>true表示验证码正确,否则表示验证码错误</returns>
'
'' <remarks>
'
'' 注意:
'
'' 此方法只是对验证码进行判断,不判断身份证号码其它部分的合法性.
'
'' 比如出现666666198013320014这样的号码,显然是非法的身份证号码
'
'' 666666的地区号目前是不存在的
'
'' 1980年没有13月,也没有32日
'
'' 但是它的校验码4却是正确的
'
'' </remarks>
'
'' <history>
'
'' [Hudan] 2005-8-8 Created
'
'' </history>
'
'' -----------------------------------------------------------------------------
Public
Function
ValidCheckcode(
ByVal
IDCard18
As
String
)
As
Boolean
'
参数IDCard18中的校验码
Dim
currentCode
As
Char
currentCode
=
IDCard18.Chars(
17
)
'
正确的验证码
Dim
ValidCode
As
Char
ValidCode
=
GetCheckCode(IDCard18.Substring(
0
,
17
))
Return
ValidCode.Equals(currentCode)
End Function
'
'' -----------------------------------------------------------------------------
'
'' <summary>
'
'' 根据身份证号码的前17位数字生成最后一位的校验码
'
'' </summary>
'
'' <param name="IDCard17">身份证号码的前17位数字</param>
'
'' <returns>校验码(身份证号码的第18位)</returns>
'
'' <remarks>
'
'' </remarks>
'
'' <history>
'
'' [Hudan] 2005-8-8 Created
'
'' </history>
'
'' -----------------------------------------------------------------------------
Public
Function
GetCheckCode(
ByVal
IDCard17
As
String
)
As
Char
'
按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码
'
公式如下:
'
∑(ai×Wi)(mod 11)
'
i----表示号码字符从右至左包括校验码在内的位置序号;
'
ai----表示第i位置上的号码字符值;
'
Wi----示第i位置上的加权因子,其数值依据公式Wi=2^(n-1)(mod 11)计算得出。
Dim
num
As
Integer
=
0
For
i
As
Integer
=
18
To
2
Step
-
1
num
+=
CInt
(IDCard17.Substring(
18
-
i,
1
))
*
(
2
^
(i
-
1
)
Mod
11
)
Next
num
=
num
Mod
11
'
然后根据计算的结果,从下面的表中查出相应的校验码,其中X表示计算结果为10:
'
∑(ai×WI)(mod 11) 0 1 2 3 4 5 6 7 8 9 10
'
校验码字符值ai 1 0 X 9 8 7 6 5 4 3 2
Dim
checkcode
As
String
Select
Case
num
Case
0
checkcode
=
"
1
"
Case
1
checkcode
=
"
0
"
Case
2
'
TODO: X是大写还是小写还未确定(刚好我的身份证的校验码是小写x,不知道大写X是否也可行)
checkcode
=
"
x
"
Case
Else
checkcode
=
CStr
(
12
-
num)
End
Select
Return
CChar
(checkcode)
End Function
4下面是写成数据库的函数形式(原著不名,我在网上搜索到的都没有标明作者),其实知道了算法,写成SQL语句也不困难:
Create
function
getCheckCode(
@SFZH
char
(
18
))
Returns
char
(
1
)
As
Begin
declare
@r
char
(
1
)
declare
@i
int
if
len
(
@SFZH
)
<>
18
set
@r
=
'
?
'
else
set
@i
=
cast
(
substring
(
@SFZH
,
1
,
1
)
as
int
)
*
7
+
cast
(
substring
(
@SFZH
,
2
,
1
)
as
int
)
*
9
+
cast
(
substring
(
@SFZH
,
3
,
1
)
as
int
)
*
10
+
cast
(
substring
(
@SFZH
,
4
,
1
)
as
int
)
*
5
+
cast
(
substring
(
@SFZH
,
5
,
1
)
as
int
)
*
8
+
cast
(
substring
(
@SFZH
,
6
,
1
)
as
int
)
*
4
+
cast
(
substring
(
@SFZH
,
7
,
1
)
as
int
)
*
2
+
cast
(
substring
(
@SFZH
,
8
,
1
)
as
int
)
*
1
+
cast
(
substring
(
@SFZH
,
9
,
1
)
as
int
)
*
6
+
cast
(
substring
(
@SFZH
,
10
,
1
)
as
int
)
*
3
+
cast
(
substring
(
@SFZH
,
11
,
1
)
as
int
)
*
7
+
cast
(
substring
(
@SFZH
,
12
,
1
)
as
int
)
*
9
+
cast
(
substring
(
@SFZH
,
13
,
1
)
as
int
)
*
10
+
cast
(
substring
(
@SFZH
,
14
,
1
)
as
int
)
*
5
+
cast
(
substring
(
@SFZH
,
15
,
1
)
as
int
)
*
8
+
cast
(
substring
(
@SFZH
,
16
,
1
)
as
int
)
*
4
+
cast
(
substring
(
@SFZH
,
17
,
1
)
as
int
)
*
2
set
@i
=
@i
-
@i
/
11
*
11
set
@r
=
(
case
@i
when
0
then
'
1
'
when
1
then
'
0
'
when
2
then
'
X
'
when
3
then
'
9
'
when
4
then
'
8
'
when
5
then
'
7
'
when
6
then
'
6
'
when
7
then
'
5
'
when
8
then
'
4
'
when
9
then
'
3
'
when
10
then
'
2
'
else
'
/
'
end
)
Return
(
@r
)
End