asp.net(c#)验证身份证号是否正确 如题,,希望高手能给我发个函数代码,本人急需。!!! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 .net 有验证控件有自带的正则表达式 C#实现的18位身份证格式验证算法 http://dev.csdn.net/htmls/57/57677.htmlC#中国身份证验证http://www.cnblogs.com/chhuic/archive/2010/01/05/1639397.html http://topic.csdn.net/u/20090512/14/c4eaef9d-2998-4054-846f-a4115ee5da02.html //这个可以验证15位和18位的身份证,并且包含生日和校验位的验证。 //如果有兴趣,还可以加上身份证所在地的验证,就是前6位有些数字合法有些数字不合法。 function isIdCardNo(num) { num = num.toUpperCase(); //身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字符X。 if (!(/(^\d{15}$)|(^\d{17}([0-9]|X)$)/.test(num))) { alert('输入的身份证号长度不对,或者号码不符合规定!\n15位号码应全为数字,18位号码末位可以为数字或X。'); return false; } //校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。 //下面分别分析出生日期和校验位 var len, re; len = num.length; if (len == 15) { re = new RegExp(/^(\d{6})(\d{2})(\d{2})(\d{2})(\d{3})$/); var arrSplit = num.match(re); //检查生日日期是否正确 var dtmBirth = new Date('19' + arrSplit[2] + '/' + arrSplit[3] + '/' + arrSplit[4]); var bGoodDay; bGoodDay = (dtmBirth.getYear() == Number(arrSplit[2])) && ((dtmBirth.getMonth() + 1) == Number(arrSplit[3])) && (dtmBirth.getDate() == Number(arrSplit[4])); if (!bGoodDay) { alert('输入的身份证号里出生日期不对!'); return false; } else { //将15位身份证转成18位 //校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。 var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); var nTemp = 0, i; num = num.substr(0, 6) + '19' + num.substr(6, num.length - 6); for(i = 0; i < 17; i ++) { nTemp += num.substr(i, 1) * arrInt[i]; } num += arrCh[nTemp % 11]; return num; } } if (len == 18) { re = new RegExp(/^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$/); var arrSplit = num.match(re); //检查生日日期是否正确 var dtmBirth = new Date(arrSplit[2] + "/" + arrSplit[3] + "/" + arrSplit[4]); var bGoodDay; bGoodDay = (dtmBirth.getFullYear() == Number(arrSplit[2])) && ((dtmBirth.getMonth() + 1) == Number(arrSplit[3])) && (dtmBirth.getDate() == Number(arrSplit[4])); if (!bGoodDay) { alert(dtmBirth.getYear()); alert(arrSplit[2]); alert('输入的身份证号里出生日期不对!'); return false; } else { //检验18位身份证的校验码是否正确。 //校验位按照ISO 7064:1983.MOD 11-2的规定生成,X可以认为是数字10。 var valnum; var arrInt = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); var arrCh = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); var nTemp = 0, i; for(i = 0; i < 17; i ++) { nTemp += num.substr(i, 1) * arrInt[i]; } valnum = arrCh[nTemp % 11]; if (valnum != num.substr(17, 1)) { alert('18位身份证的校验码不正确!应该为:' + valnum); return false; } return num; } } return false; } public class IDCard { /// <summary> /// 18位身份证验证 /// </summary> /// <param name="Id">身份证号</param> /// <returns>返回bool是否验证成功</returns> public static bool CheckIDCard18(string Id) { long n = 0; if (long.TryParse(Id.Remove(17), out n) == false || n < Math.Pow(10, 16) || long.TryParse(Id.Replace('x', '0').Replace('X', '0'), out n) == false) { return false;//数字验证 } string address = "11x22x35x44x53x12x23x36x45x54x13x31x37x46x61x14x32x41x50x62x15x33x42x51x63x21x34x43x52x64x65x71x81x82x91"; if (address.IndexOf(Id.Remove(2)) == -1) { return false;//省份验证 } string birth = Id.Substring(6, 8).Insert(6, "-").Insert(4, "-"); DateTime time = new DateTime(); if (DateTime.TryParse(birth, out time) == false) { return false;//生日验证 } string[] arrVarifyCode = ("1,0,x,9,8,7,6,5,4,3,2").Split(','); string[] Wi = ("7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2").Split(','); char[] Ai = Id.Remove(17).ToCharArray(); int sum = 0; for (int i = 0; i < 17; i++) { sum += int.Parse(Wi[i]) * int.Parse(Ai[i].ToString()); } int y = -1; Math.DivRem(sum, 11, out y); if (arrVarifyCode[y] != Id.Substring(17, 1).ToLower()) { return false;//校验码验证 } return true; //符合GB11643-1999标准 } } 关于身份证号码最后一位的校验码的算法2005-04-14 14:25:36 By: 长弓 View:24我国现行使用公民身份证号码有两种尊循两个国家标准,〖GB 11643-1989〗和〖GB 11643-1999〗。〖GB 11643-1989〗中规定的是15位身份证号码:排列顺序从左至右依次为:六位数字地址码,六位数字出生日期码,三位数字顺序码,其中出生日期码不包含世纪数。〖GB 11643-1999〗中规定的是18位身份证号码:公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。地址码表示编码对象常住户口所在县(市、旗、区)的行政区划代码。生日期码表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。顺序码表示同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。顺序码的奇数分给男性,偶数分给女性。校验码是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。公式如下: ∑(a[i]*W[i]) mod 11 ( i = 2, 3, ..., 18 ) (1) "*" 表示乘号 i--------表示身份证号码每一位的序号,从右至左,最左侧为18,最右侧为1。 a[i]-----表示身份证号码第 i 位上的号码 W[i]-----表示第 i 位上的权值 W[i] = 2^(i-1) mod 11 计算公式 (1) 令结果为 R根据下表找出 R 对应的校验码即为要求身份证号码的校验码C。 R 0 1 2 3 4 5 6 7 8 9 10 C 1 0 X 9 8 7 6 5 4 3 2由此看出 X 就是 10,罗马数字中的 10 就是X,所以在新标准的身份证号码中可能含有非数字的字母X。(从左到右的W:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 ) 以下为列子*-----------------------------**此函数功能:输入的15位或17位或18位的身份证号,返回校验后的最后一位**-----------------------------FUNCTION sfzjyParameters cIDDO CASECASE LEN(ALLTRIM(cID)) = 15cID = STUFF(ALLTRIM(cID),7,0,"19")CASE LEN(ALLTRIM(cID)) = 18 OR LEN(ALLTRIM(cID)) = 17cID =LEFT(ALLTRIM(cID),17)OTHERWISERETURN .F.ENDCASEIf Len(ALLTRIM(cID))#17Return .f.EndifnSum=Val(SubStr(cID,1,1)) * 7 ;+ Val(SubStr(cID,2,1)) * 9 ;+ Val(SubStr(cID,3,1)) * 10 ;+ Val(SubStr(cID,4,1)) * 5 ;+ Val(SubStr(cID,5,1)) * 8 ;+ Val(SubStr(cID,6,1)) * 4 ;+ Val(SubStr(cID,7,1)) * 2 ;+ Val(SubStr(cID,8,1)) * 1 ;+ Val(SubStr(cID,9,1)) * 6 ;+ Val(SubStr(cID,10,1)) * 3 ;+ Val(SubStr(cID,11,1)) * 7 ;+ Val(SubStr(cID,12,1)) * 9 ;+ Val(SubStr(cID,13,1)) * 10 ;+ Val(SubStr(cID,14,1)) * 5 ;+ Val(SubStr(cID,15,1)) * 8 ;+ Val(SubStr(cID,16,1)) * 4 ;+ Val(SubStr(cID,17,1)) * 2*计算校验位check_number=INT((12-nSum % 11)%11)If check_number=10check_number='X'EndifReturn check_numberEndfunc*-----------------------------**此函数功能:输入的15位或18位身份证号,返回正确的18位的身份证号。**---------------------------FUNCTION IDCardTFPARAMETERS cNumber#DEFINE InvalidSize "身份证号码长度不正确!"#DEFINE InvalidChar "身份证号码包括非法字符!"#DEFINE InvalidDate "出生日期无效!"#DEFINE InvalidReturnValue ".F."PRIVATE cStringDO CASECASE LEN(cNumber) = 15cString = STUFF(cNumber,7,0,"19")CASE LEN(cNumber) = 18cString =LEFT(ALLTRIM(cNumber),17)OTHERWISEMESSAGEBOX(InvalidSize,48,"信息提示")RETURN InvalidReturnValueENDCASEPRIVATE i,n,iRetSTORE 0 TO iRetFOR i = 1 TO 17n = SUBSTR(cString,i,1)IF NOT ISDIGIT(n)MESSAGEBOX(invalidChar,48,"信息提示")RETURN invalidReturnValueENDIFn = 2 ^ (18 - i) % 11 * VAL(n)iRet = iRet + nENDFORiRet = iRet % 11 + 1PRIVATE oldDateSet, oldCenturyPRIVATE oldStrictDate, BirthDayoldDateSet = SET("DATE")oldCentury = SET("CENTURY")oldStrictDate = SET("STRICTDATE")SET DATE ANSISET CENTURY ONSET STRICTDATE TO 0BirthDay = CTOD(SUBSTR(cString,7,4)+"-"+SUBSTR(cString,11,2)+"-"+SUBSTR(cString,13,2))SET STRICTDATE TO &oldStrictDateSET CENTURY &oldCenturySET DATE &oldDateSetIF EMPTY(BirthDay)MESSAGEBOX(InvalidDate,48,"信息提示")RETURN InvalidReturnValueENDIFRETURN cString+SUBSTR("10x98765432",iRet,1)ENDFUNC*-----------------------------**此函数功能:检验输入的15位或18位身份证号码是否为合法**-----------------------------FUNCTION sfzynLPARAMETERS lstr &&参数:lstr 传入的号码LOCAL lstr,relyn,tsfzLOCAL m1,m2,m3,m4,m,i,r,c,ai,wiSET TALK OFFSET DATE TO ANSISET CENT ONrelyn=.F. &&返回值tsfz=ALLT(lstr)*分别用m1,m2,m3,m4表示四个条件是否成立STOR .T. TO m1,m2,m3,m4*条件1:只能是15或18位m1=IIF(LEN(tsfz)=15 OR LEN(tsfz)=18,.T.,.F.)IF LEN(tsfz)=15 && 15位的号码FOR i=1 TO 15 &&检查每一位是否为数字m=ASC(SUBS(tsfz,i,1))IF m<48 OR m>57 &&数字m2=.F. &&若有一位不是就不再查EXITENDIFENDFORm="19" +SUBS(tsfz, 7,2) &&早期的号都是上个世纪的m=m+"."+SUBS(tsfz, 9,2)m=m+"."+SUBS(tsfz,11,2)m=CTOD(m)IF ISNULL(m) OR isblank(m)m3=.F. &&生日不正确ENDIFENDIFIF LEN(tsfz)=18 && 18位的号码FOR i=1 TO 17m=ASC(SUBS(tsfz,i,1))IF m<48 OR m>57m2=.F.EXITENDIFENDFORm=SUBS(tsfz,7,4)m=m+"."+SUBS(tsfz,11,2)m=m+"."+SUBS(tsfz,13,2)m=CTOD(m)IF ISNULL(m) OR isblank(m)m3=.F.ENDIFr=0 &&计算校验位FOR i=18 TO 2 STEP -1ai=VAL(SUBS(tsfz,19-i,1))wi=MOD(2^(i-1),11)r=r+ai*wiNEXTr=MOD(r,11)DO CASECASE r=0c="1"CASE r=1c="0"CASE r=2c="X"OTHERc=ALLTRIM(STR(12-r))ENDCASEIF UPPE(SUBS(tsfz,18,1))<>cm4=.F. &&校验位与原码最末位不同ENDIFENDIF*四个条件全成立,则返回.t.relyn=IIF(m1 AND m2 AND m3 AND m4,.T.,.F.)RETU relynENDFUN*-----------------------------**此函数功能:输入15位或18位的身份证号,返回被校验后的18位的身份证号,若身份证号非法,则返回空**-----------------------------FUNC sfjyPARA msfzON ERRO RETU ''DIME T(17)PRIV msfz,T,sn,imsfz=ALLT(msfz)DO CASECASE LEN(msfz)=15msfz=LEFT(msfz,6)+'19'+SUBS(msfz,7)CASE LEN(msfz)=18msfz=LEFT(msfz,17)OTHERETU ''ENDCFOR i=1 TO 17IF !ISDI(SUBS(msfz,i,1))RETU ''ENDIENDFIF !LEFT(msfz,2)$'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'RETU ''ENDIIF EMPT(DATE(VAL(SUBS(msfz,7,4)),VAL(SUBS(msfz,11,2)),VAL(SUBS(msfz,13,2))))RETU ''ENDIsn=0T(1)=7T(2)=9T(3)=10T(4)=5T(5)=8T(6)=4T(7)=2T(8)=1T(9)=6T(10)=3T(11)=7T(12)=9T(13)=10T(14)=5T(15)=8T(16)=4T(17)=2FOR i=1 TO 17sn=sn+VAL(SUBS(msfz,i,1))*T(i)ENDFsn=MOD(sn,11)ON ERRORETU msfz+SUBS('10X98765432',sn+1,1) 15位的正则 /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$/; 18位的 /^[1-9正则]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$/; 对,用正则表达式,或者本身asp.net中有个RegualExpression控件,里面可以自己选 多个web.config的问题 这个问题怎么解决--非常头痛关于sql 的条件限制问题 c#报错的一个信息.高分求解 DataTable DataRow DataColumn SQL存储过程 什么叫多层结构?三层结构 请大家帮我解释一下(1)(2) 不个懂的问题`高手在下 用.Net制作安装程序,如何添加注册码验证? updatepannel 加了以后javascript和jquery 失效, 问题请教,急急急!!!!! XMLHttpReq.readyState为空或不是对象,大家帮忙看下啊。急````` 高分求助!!!
http://dev.csdn.net/htmls/57/57677.htmlC#中国身份证验证
http://www.cnblogs.com/chhuic/archive/2010/01/05/1639397.html
public class IDCard
{
/// <summary>
/// 18位身份证验证
/// </summary>
/// <param name="Id">身份证号</param>
/// <returns>返回bool是否验证成功</returns>
public static bool CheckIDCard18(string Id)
{
long n = 0;
if (long.TryParse(Id.Remove(17), out n) == false || n < Math.Pow(10, 16) || long.TryParse(Id.Replace('x', '0').Replace('X', '0'), out n) == false)
{
return false;//数字验证
}
string address = "11x22x35x44x53x12x23x36x45x54x13x31x37x46x61x14x32x41x50x62x15x33x42x51x63x21x34x43x52x64x65x71x81x82x91";
if (address.IndexOf(Id.Remove(2)) == -1)
{
return false;//省份验证
}
string birth = Id.Substring(6, 8).Insert(6, "-").Insert(4, "-");
DateTime time = new DateTime();
if (DateTime.TryParse(birth, out time) == false)
{
return false;//生日验证
}
string[] arrVarifyCode = ("1,0,x,9,8,7,6,5,4,3,2").Split(',');
string[] Wi = ("7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2").Split(',');
char[] Ai = Id.Remove(17).ToCharArray();
int sum = 0;
for (int i = 0; i < 17; i++)
{
sum += int.Parse(Wi[i]) * int.Parse(Ai[i].ToString());
}
int y = -1;
Math.DivRem(sum, 11, out y);
if (arrVarifyCode[y] != Id.Substring(17, 1).ToLower())
{
return false;//校验码验证
}
return true; //符合GB11643-1999标准
}
}
2005-04-14 14:25:36 By: 长弓 View:24我国现行使用公民身份证号码有两种尊循两个国家标准,〖GB 11643-1989〗和〖GB 11643-1999〗。〖GB 11643-1989〗中规定的是15位身份证号码:排列顺序从左至右依次为:六位数字地址码,六位数字出生日期码,三位数字顺序码,其中出生日期码不包含世纪数。〖GB 11643-1999〗中规定的是18位身份证号码:公民身份号码是特征组合码,由十七位数字本体码和一位数字校验码组成。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。地址码表示编码对象常住户口所在县(市、旗、区)的行政区划代码。生日期码表示编码对象出生的年、月、日,其中年份用四位数字表示,年、月、日之间不用分隔符。顺序码表示同一地址码所标识的区域范围内,对同年、月、日出生的人员编定的顺序号。
顺序码的奇数分给男性,偶数分给女性。校验码是根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校验码计算出来的检验码。公式如下:
∑(a[i]*W[i]) mod 11 ( i = 2, 3, ..., 18 ) (1)
"*" 表示乘号
i--------表示身份证号码每一位的序号,从右至左,最左侧为18,最右侧为1。
a[i]-----表示身份证号码第 i 位上的号码
W[i]-----表示第 i 位上的权值 W[i] = 2^(i-1) mod 11
计算公式 (1) 令结果为 R
根据下表找出 R 对应的校验码即为要求身份证号码的校验码C。
R 0 1 2 3 4 5 6 7 8 9 10
C 1 0 X 9 8 7 6 5 4 3 2
由此看出 X 就是 10,罗马数字中的 10 就是X,所以在新标准的身份证号码中可能含有非数字的字母X。
(从左到右的W:7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 )
以下为列子
*-----------------------------
*
*此函数功能:输入的15位或17位或18位的身份证号,返回校验后的最后一位
*
*-----------------------------
FUNCTION sfzjy
Parameters cID
DO CASE
CASE LEN(ALLTRIM(cID)) = 15
cID = STUFF(ALLTRIM(cID),7,0,"19")
CASE LEN(ALLTRIM(cID)) = 18 OR LEN(ALLTRIM(cID)) = 17
cID =LEFT(ALLTRIM(cID),17)
OTHERWISE
RETURN .F.
ENDCASE
If Len(ALLTRIM(cID))#17
Return .f.
Endif
nSum=Val(SubStr(cID,1,1)) * 7 ;
+ Val(SubStr(cID,2,1)) * 9 ;
+ Val(SubStr(cID,3,1)) * 10 ;
+ Val(SubStr(cID,4,1)) * 5 ;
+ Val(SubStr(cID,5,1)) * 8 ;
+ Val(SubStr(cID,6,1)) * 4 ;
+ Val(SubStr(cID,7,1)) * 2 ;
+ Val(SubStr(cID,8,1)) * 1 ;
+ Val(SubStr(cID,9,1)) * 6 ;
+ Val(SubStr(cID,10,1)) * 3 ;
+ Val(SubStr(cID,11,1)) * 7 ;
+ Val(SubStr(cID,12,1)) * 9 ;
+ Val(SubStr(cID,13,1)) * 10 ;
+ Val(SubStr(cID,14,1)) * 5 ;
+ Val(SubStr(cID,15,1)) * 8 ;
+ Val(SubStr(cID,16,1)) * 4 ;
+ Val(SubStr(cID,17,1)) * 2
*计算校验位
check_number=INT((12-nSum % 11)%11)
If check_number=10
check_number='X'
Endif
Return check_number
Endfunc*-----------------------------
*
*此函数功能:输入的15位或18位身份证号,返回正确的18位的身份证号。
*
*---------------------------FUNCTION IDCardTF
PARAMETERS cNumber
#DEFINE InvalidSize "身份证号码长度不正确!"
#DEFINE InvalidChar "身份证号码包括非法字符!"
#DEFINE InvalidDate "出生日期无效!"
#DEFINE InvalidReturnValue ".F."
PRIVATE cString
DO CASE
CASE LEN(cNumber) = 15
cString = STUFF(cNumber,7,0,"19")
CASE LEN(cNumber) = 18
cString =LEFT(ALLTRIM(cNumber),17)
OTHERWISE
MESSAGEBOX(InvalidSize,48,"信息提示")
RETURN InvalidReturnValue
ENDCASE
PRIVATE i,n,iRet
STORE 0 TO iRet
FOR i = 1 TO 17
n = SUBSTR(cString,i,1)
IF NOT ISDIGIT(n)
MESSAGEBOX(invalidChar,48,"信息提示")
RETURN invalidReturnValue
ENDIF
n = 2 ^ (18 - i) % 11 * VAL(n)
iRet = iRet + n
ENDFOR
iRet = iRet % 11 + 1
PRIVATE oldDateSet, oldCentury
PRIVATE oldStrictDate, BirthDay
oldDateSet = SET("DATE")
oldCentury = SET("CENTURY")
oldStrictDate = SET("STRICTDATE")
SET DATE ANSI
SET CENTURY ON
SET STRICTDATE TO 0
BirthDay = CTOD(SUBSTR(cString,7,4)+"-"+SUBSTR(cString,11,2)+"-"+SUBSTR(cString,13,2))
SET STRICTDATE TO &oldStrictDate
SET CENTURY &oldCentury
SET DATE &oldDateSet
IF EMPTY(BirthDay)
MESSAGEBOX(InvalidDate,48,"信息提示")
RETURN InvalidReturnValue
ENDIF
RETURN cString+SUBSTR("10x98765432",iRet,1)
ENDFUNC*-----------------------------
*
*此函数功能:检验输入的15位或18位身份证号码是否为合法
*
*-----------------------------FUNCTION sfzyn
LPARAMETERS lstr &&参数:lstr 传入的号码
LOCAL lstr,relyn,tsfz
LOCAL m1,m2,m3,m4,m,i,r,c,ai,wi
SET TALK OFF
SET DATE TO ANSI
SET CENT ON
relyn=.F. &&返回值
tsfz=ALLT(lstr)
*分别用m1,m2,m3,m4表示四个条件是否成立
STOR .T. TO m1,m2,m3,m4*条件1:只能是15或18位
m1=IIF(LEN(tsfz)=15 OR LEN(tsfz)=18,.T.,.F.)
IF LEN(tsfz)=15 && 15位的号码
FOR i=1 TO 15 &&检查每一位是否为数字
m=ASC(SUBS(tsfz,i,1))
IF m<48 OR m>57 &&数字
m2=.F. &&若有一位不是就不再查
EXIT
ENDIF
ENDFOR
m="19" +SUBS(tsfz, 7,2) &&早期的号都是上个世纪的
m=m+"."+SUBS(tsfz, 9,2)
m=m+"."+SUBS(tsfz,11,2)
m=CTOD(m)
IF ISNULL(m) OR isblank(m)
m3=.F. &&生日不正确
ENDIF
ENDIF
IF LEN(tsfz)=18 && 18位的号码
FOR i=1 TO 17
m=ASC(SUBS(tsfz,i,1))
IF m<48 OR m>57
m2=.F.
EXIT
ENDIF
ENDFOR
m=SUBS(tsfz,7,4)
m=m+"."+SUBS(tsfz,11,2)
m=m+"."+SUBS(tsfz,13,2)
m=CTOD(m)
IF ISNULL(m) OR isblank(m)
m3=.F.
ENDIF
r=0 &&计算校验位
FOR i=18 TO 2 STEP -1
ai=VAL(SUBS(tsfz,19-i,1))
wi=MOD(2^(i-1),11)
r=r+ai*wi
NEXT
r=MOD(r,11)
DO CASE
CASE r=0
c="1"
CASE r=1
c="0"
CASE r=2
c="X"
OTHER
c=ALLTRIM(STR(12-r))
ENDCASE
IF UPPE(SUBS(tsfz,18,1))<>c
m4=.F. &&校验位与原码最末位不同
ENDIF
ENDIF
*四个条件全成立,则返回.t.
relyn=IIF(m1 AND m2 AND m3 AND m4,.T.,.F.)
RETU relyn
ENDFUN
*-----------------------------
*
*此函数功能:输入15位或18位的身份证号,返回被校验后的18位的身份证号,若身份证号非法,则返回空
*
*-----------------------------
FUNC sfjy
PARA msfz
ON ERRO RETU ''
DIME T(17)
PRIV msfz,T,sn,i
msfz=ALLT(msfz)
DO CASE
CASE LEN(msfz)=15
msfz=LEFT(msfz,6)+'19'+SUBS(msfz,7)
CASE LEN(msfz)=18
msfz=LEFT(msfz,17)
OTHE
RETU ''
ENDC
FOR i=1 TO 17
IF !ISDI(SUBS(msfz,i,1))
RETU ''
ENDI
ENDF
IF !LEFT(msfz,2)$'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'
RETU ''
ENDI
IF EMPT(DATE(VAL(SUBS(msfz,7,4)),VAL(SUBS(msfz,11,2)),VAL(SUBS(msfz,13,2))))
RETU ''
ENDI
sn=0
T(1)=7
T(2)=9
T(3)=10
T(4)=5
T(5)=8
T(6)=4
T(7)=2
T(8)=1
T(9)=6
T(10)=3
T(11)=7
T(12)=9
T(13)=10
T(14)=5
T(15)=8
T(16)=4
T(17)=2
FOR i=1 TO 17
sn=sn+VAL(SUBS(msfz,i,1))*T(i)
ENDF
sn=MOD(sn,11)
ON ERRO
RETU msfz+SUBS('10X98765432',sn+1,1)
/^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$/;
18位的
/^[1-9正则]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{4}$/;