*!* 以下为我收集的关于身份证号码的自定义函数(十豆三)
*!* 关于身份证号码最后一位的校验码的算法如下:*!* 我国现行使用公民身份证号码有两种尊循两个国家标准,〖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。*!* **********************************************************************************!* 感谢yesyesyes提供的信息:*!* 15位身份证那时是我国第一次发身份证*!* 发证当时已满100岁的人,就给他们那些号(因为年份只有2位)*!* 十五位身份证第十三至十五位为分配顺序代码*!* 分配顺序码中“999、998、997、996”四个顺序号分别为男女性百岁以上老人专用的特定编号。*!* **********************************************************************************!* 感谢清风提供的信息:*!* 这里所说的“百岁”应该是指19世纪也就是18XX年出生的人,而不是指办身份证时此人已有100岁。这种特例不多,所以男女各设了两个序号*!* 还得提醒一下,1901年与2001年不会发生冲突,因为2000后就直接使用18位号码了,如果是15位的,那肯定是2000年以前的。*!* *****************************************************************************
*---------------------------------------------------------------*此函数功能:输入的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 MyIdentityCardVerify &&校验身份证号是否合法 Lparameters lstr &&参数:lstr 传入的号码 Private lstr,relyn,tsfz,m1,m2,m3,m4,m,I,r,c,ai,wi relyn=.F. &&返回值 tsfz=Alltrim(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(Substr(tsfz,I,1)) If m<48 Or m>57 &&数字 m2=.F. &&若有一位不是就不再查 Exit Endif Endfor m="19" +Substr(tsfz, 7,2) &&早期的号都是上个世纪的 m=m+"."+Substr(tsfz, 9,2) m=m+"."+Substr(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(Substr(tsfz,I,1)) If m<48 Or m>57 m2=.F. Exit Endif Endfor m=Substr(tsfz,7,4) m=m+"."+Substr(tsfz,11,2) m=m+"."+Substr(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(Substr(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" Otherwise c=Alltrim(Str(12-r)) Endcase If Upper(Substr(tsfz,18,1))<>c m4=.F. &&校验位与原码最末位不同 Endif Endif *四个条件全成立,则返回.t. relyn=Iif(m1 And m2 And m3 And m4,.T.,.F.) Return relynEndfunc
*--------------------------------------------------------------------------------------------*此函数功能:输入15位或18位的身份证号,返回被校验后的18位的身份证号,若身份证号非法,则返回空*--------------------------------------------------------------------------------------------Function sfjy Parameters msfz On Error Return '' Dimension T(17) Private msfz,T,sn,i msfz=Alltrim(msfz) Do Case Case Len(msfz)=15 msfz=Left(msfz,6)+'19'+Substr(msfz,7) Case Len(msfz)=18 msfz=Left(msfz,17) Otherwise Return '' Endcase For i=1 To 17 If !Isdigit(Substr(msfz,i,1)) Return '' Endif Endfor 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' Return '' Endif If Empty(Date(Val(Substr(msfz,7,4)),Val(Substr(msfz,11,2)),Val(Substr(msfz,13,2)))) Return '' Endif 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(Substr(msfz,i,1))*T(i) Endfor sn=Mod(sn,11) On Error Return msfz+Substr('10X98765432',sn+1,1)Endfunc
*------------------------------------------------------------------*此函数功能:输入的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_numberEndfunc
*******************************************身份证号出错信息(对字段:sfzherrc的编码解释)*1、"身份证号不满15位!"2、性别与身份证不符3、出生月份出错(不在1-12范围内)4、出生日期出错(不在1-31范围内)*5、18位校验位出错(sfzherrc中紧跟括号内的内容为正确的第18位校验码)6、18位身份证出生年份出错(不是19)*检查原则:不满15位只检查位数,15位检查出生年、月、日的超界关系、性别对应关系(男:身份证第15位为13579,女:身份证第15位为02468)*检查原则:18位身份证除检查15位的检查原则外增加检查最后一位检验码的关系校验*以下附身份证号的算法函数,可供大家参考!!************************************************************************身份号码第18位校验位的算法〖中华人民共和国国家标准 GB 11643-1999〗(依此算法写的函数存放在过*程文件myproc.prg中<附后>)* 15位的身份证编码首先把出生年扩展为4位,简单的就是增加一个19,但对于1900前年出生的人不适用* ∑(ai×Wi)(mod 11)……………………………………(1)* 公式(1)中:* i----表示号码字符从由至左包括校验码在内的位置序号;* ai----表示第i位置上的号码字符值;* Wi----示第i位置上的加权因子,其数值依据公式Wi=2^(n-1)(mod 11)计算得出((n-1)为幂)。* i 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1* ai 3 4 0 5 2 4 1 9 8 0 0 1 0 1 0 0 1 a1* Wi 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1* ai×Wi 21 36 0 25 16 16 2 9 48 0 0 9 0 5 0 0 2 a1* 根据公式(1)进行计算:* ∑(ai×Wi) =(21+36+0+25+16+16+2+9+48++0+0+9+0+5+0+0+2) = 189* 189 ÷ 11 = 17 + 2/11* ∑(ai×Wi)(mod 11) = 2* 然后根据计算的结果,从下面的表中查出相应的校验码,其中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
*-----------------------------*身份证升位程序*作者:窦学田*功能:计算身份证的校验码*入口参数:15位号码 或17位号码*返回:18位身份证号码*-----------------------------Function NewIdCode() Parameters OldId Local id1,id2,i2,NewIdCode id1=Strtran(OldId,' ','') id2=0 If Len(id1)=15 id1=Left(OldId,6)+'19'+Right(OldId,9) Endif If Len(id1)=17 For i2=1 To 17 id2=id2+Val(Substr(id1,18-i2,1))*(Mod(2^i2,11)) Endfor id1=id1+Iif(Mod(1-id2,11)=10,'X',Str(Mod(1-id2,11),1)) Endif NewIdCode=id1 Return NewIdCodeEndfunc
*-----------------------------*测试18位的身份证是否正确*作者:窦学田*功能:测试18位身份证的校验码*入口参数:18位号码*返回:出错信息*-----------------------------Function GetOld() Parameters sID s1=' 7 910 5 8 4 2 1 6 3 7 910 5 8 4 2' s2='10X98765432' sID=Upper(Alltrim(sID)) If Len(sID)=15 sID=Stuff(sID,7,0,"19") Endif NewId=Left(sID,17) jym=0 For i=1 To 17 jym=jym+Val(Substr(s1,i*2-1,2))*Val(Substr(NewId,i,1)) Endfor NewId= NewId+ Substr(s2,Mod(jym,11)+1,1) If Len(sID)=18 If Right(sID,1)<>Right(NewId,1) &&正确 Messagebox(sID+"为错误身份证号码!",48,"警告") Endif EndifEndfunc
*---------------------------------------------------*测试身份证的年月日的合法性YMDS(year,month,date,sex)*作者:窦学田*功能:测试18位身份证的年月日的合法性*入口参数:原表中的性别代码,原身份证号码*返回:综合出错信息*---------------------------------------------------Function CheckYMDS() Parameters F_xbdm,F_ID Local rtn_errcode rtn_errcode='' sfxb=Iif(F_xbdm='1','13579','02468') If Len(Alltrim(F_ID))=15 sfsex=Substr(F_ID,15,1) If !sfsex$sfxb &&测试性别 rtn_errcode=Iif(Empty(rtn_errcode),"2",Alltrim(rtn_errcode)+'+2') Endif sfy=Substr(F_ID,9,2) &&月 sfr=Substr(F_ID,11,2) &&日 If !(Val(sfy)<=12) rtn_errcode=Iif(Empty(rtn_errcode),"3",Alltrim(rtn_errcode)+'+3') Endif If !(Val(sfr)<=31) rtn_errcode=Iif(Empty(rtn_errcode),"4",Alltrim(rtn_errcode)+'+4') Endif Else sfsex=Substr(F_ID,17,1) If !sfsex$sfxb &&测试性别 rtn_errcode=Iif(Empty(rtn_errcode),"2",Alltrim(rtn_errcode)+'+2') Endif sfy=Substr(F_ID,11,2) &&月 sfr=Substr(F_ID,13,2) &&日 If !(Val(sfy)<=12) &&月 rtn_errcode=Iif(Empty(rtn_errcode),"3",Alltrim(rtn_errcode)+'+3') Endif If !(Val(sfr)<=31) &&日 rtn_errcode=Iif(Empty(rtn_errcode),"4",Alltrim(rtn_errcode)+'+4') Endif Endif *以下测试第18位校验码的正确性 s1=' 7 910 5 8 4 2 1 6 3 7 910 5 8 4 2' s2='10X98765432' F_ID=Upper(Alltrim(F_ID)) If Len(F_ID)=15 F_ID=Stuff(F_ID,7,0,"19") Endif NewId=Left(F_ID,17) jym=0 For i=1 To 17 jym=jym+Val(Substr(s1,i*2-1,2))*Val(Substr(NewId,i,1)) Endfor NewId= NewId+ Substr(s2,Mod(jym,11)+1,1) If Len(F_ID)=18 If Right(F_ID,1)<>Right(NewId,1) &&不正确 &&返回出错信息及正确的第18位校验码 rtn_errcode=Iif(Empty(rtn_errcode),"5"+'(应为'+Right(NewId,1)+')',Alltrim(rtn_errcode)+'+5'+'(应为'+Right(NewId,1)+')') Endif Endif If Substr(F_ID,7,2)<>'19' &&测试年(19) rtn_errcode=Iif(Empty(rtn_errcode),"6",Alltrim(rtn_errcode)+'+6') Endif Return rtn_errcodeEndfunc
*------------------------------------------------------* 从身份证在返回相关资料* 第一个参数为[字符型]:身份证号码* 第二个参数为返回资料[数值型]:1.返回为行政区号[字符符]* 2.返回为出生日期[日期型]* 3.返回为性别男女[字符型]* 没有第二参数时返回正确的18位身份证号码* 梦幻幻影 2005-04-22 17:12:18 **------------------------------------------------------Function IDCardCheck ( c_IDCard,nRetValue ) If Vartype(m.c_IDCard) <> [C] Or Not Inlist(Len(Alltrim(m.c_IDCard)),15,18) Return .F. Endif If Len(Alltrim(m.c_IDCard)) = 15 m.c_IDCard = Substr(m.c_IDCard,1,6)+[19]+Substr(m.c_IDCard,7) + [X] Endif m.nRetValue = Iif(Vartype(m.nRetValue) = [N],m.nRetValue,0) Local nEndCode,ReString m.nEndCode = 0 For i=17 To 1 Step -1 m.nEndCode = m.nEndCode +(2^i%11)*Val(Substr(c_idcard,18-i,1)) Endfor Do Case Case m.nRetValue = 1 &&返回行政区号 m.ReString = Substr(m.c_IDCard,1,6) Case m.nRetValue = 2 &&返回出生日期 m.ReString = Substr(m.c_IDCard,7,8) Local nYear,nMonth,nDay m.nYear = Val(Substr(m.ReString,1,4)) m.nMonth = Val(Substr(m.ReString,5,2)) m.nDay = Val(Substr(m.ReString,7,2)) If !Between(m.nMonth, 1, 12) Return .F. Endif Do Case Case Inlist(m.nMonth,4,6,9,11) If !Between(m.nDay,1,30) Return .F. Endif Case m.nMonth = 2 If !Between(m.nDay,1,Iif(Int(m.nYear/4) = m.nYear/4,29,28)) Return .F. Endif Otherwise If !Between(m.nDay,1,31) Return .F. Endif Endcase Return Date(m.nYear,m.nMonth,m.nDay) Case m.nRetValue = 3 &&返回性别 m.ReString = Substr(Right(m.c_IDCard,2),1,1) m.ReString = Iif(Mod(Val(m.ReString),2)=0,[女],[男]) Otherwise m.ReString = Substr([10X98765432],Mod(m.nEndCode,11)+1,1) m.ReString = Substr(m.c_IDCard,1,17) + m.ReString Endcase Return m.ReStringEndfunc
*------------------------------------------------------*感谢:dfwxj(清风)*------------------------------------------------------Function sfjy Parameters msfz On Error Return '' Private msfz,sn,i,dic dic='0709100508040201060307091005080402' msfz=Alltrim(msfz) *出生日期预处理,仅接受15或18位字符串 Do Case Case Len(msfz)=15 If Right(msfz,3)$'996,997,998,999' msfz=Left(msfz,6)+'18'+Substr(msfz,7) Else msfz=Left(msfz,6)+'19'+Substr(msfz,7) Endif Case Len(msfz)=18 msfz=Left(msfz,17) Otherwise Return '' Endcase *检查身份证号字符的合法性 For i=1 To 17 If !Isdigit(Substr(msfz,i,1)) Return '' Endif Endfor *检查行政区划合法性 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' Return '' Endif *检查出生日期合法性 If Empty(Date(Val(Substr(msfz,7,4)),Val(Substr(msfz,11,2)),Val(Substr(msfz,13,2)))) Return '' Endif *生成校检码 sn=0 For i=1 To 17 sn=sn+Val(Substr(msfz,i,1))*Val(Substr(dic,i*2-1,2)) Endfor sn=Mod(sn,11) On Error Return msfz+Substr('10X98765432',sn+1,1)Endfunc
*------------------------------------------------------*作者:Linzhiyang,发表于『动感游标』 http://www.vfp.cn*若转载,请保留本注释部分*功能:计算身份证的校验码*入口参数:15位号码 或17位号码*返回:18位身份证号码*------------------------------------------------------Function NewIdCode Parameters OldId Local id1,id2,i,NewId id1=Strtran(OldId," ","") id2=0 Do Case Case Len(id1)=15 id1=Left(OldId,6)+"19"+Right(OldId,9) For i=1 To 17 id2=id2+Val(Substr(id1,18-i,1))*(Mod(2^i,11)) Endfor id1=id1+Iif(Mod(1-id2,11)=10,"X",Str(Mod(1-id2,11),1)) Case Len(id1)=17 For i=1 To 17 id2=id2+Val(Substr(id1,18-i,1))*(Mod(2^i,11)) Endfor id1=id1+Iif(Mod(1-id2,11)=10,"X",Str(Mod(1-id2,11),1)) Otherwise id1="Error" Endcase NewId=id1 Return NewIdEndfunc
*----------------*18位身份证校验码*----------------Function valid_Id_Card_Num Lparameters cIdCardNo18 Local s,i,b,Y,LastChart, StrValid, Wi StrValid = '10X98765432' Wi = '7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2,1' S=0 For i = 1 To 17 b = Val(Substr(cIdCardNo18,i,1)) S = S + b * Val(Getwordnum(wi,i,',')) Endfor Y= Mod(s,11) + 1 LastChart = Substr(StrValid,Y,1) Return LastChartEndfunc
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/apple_8180/archive/2006/07/19/941626.aspx |