身份证号码的验证

时间:2021-07-24 22:36:35

/*-------------------------------------------------------------------------------
* 函数名称:Boolean gf_check_identity(string as_identity)
* 函数功能:验证身份证号输入的正确性(可以对身份证号码的第18位校验位进行判断.)
* 参数说明:string as_identity    身份证号
* 返 回 值:True  成功
*           False 失败
* 调用举例:gf_check_identity('513101198201130014')  
* 修改日期:2005-05-09
* 修 改 人:tecsun
*--------------------------------------------------------------------------------*/
string ls_identity_no
string ls_year,ls_month,ls_day,ls_date
string ls_today
long ll_year
long ll_identity_no_len  

ls_identity_no = as_identity
ls_today = string(today(),'yyyy/mm/dd')

ll_identity_no_len=LEN(ls_identity_no)

if ls_identity_no = ''  then
MessageBox("系统提示","身份证号码不能为空!!",StopSign!,ok!)
return False
elseif ll_identity_no_len <> 15 AND ll_identity_no_len <> 18 then
MessageBox("系统提示","身份证号码位数不正确,请检查输入情况!!",StopSign!,ok!)
return False
end if

if ll_identity_no_len = 15 then //身份证为 15 处理,  认为15位的年 = 19**
ls_year = mid(ls_identity_no, 7, 2)
ls_month = mid(ls_identity_no, 9, 2)
ls_day = mid(ls_identity_no, 11, 2)
ls_year = '19' + ls_year//year is only 20 century
ls_date = ls_year +'/' + ls_month +'/' + ls_day
else
ls_year = mid(ls_identity_no, 7, 4)

if Left(ls_year,2) <> '19' and left(ls_year,2) <> '20' then
  MessageBox("系统提示","身份证号码中的出生年份不正确, 请您重新输入! ",StopSign!,ok!)
  return False
end if

ls_month = mid(ls_identity_no, 11, 2)
ls_day = mid(ls_identity_no, 13, 2)
ls_date = ls_year +'/' + ls_month +'/' + ls_day
end if

if ls_month > '12' then
MessageBox("系统提示","身份证号码中的出生月份不能大于12, 请您重新输入 ",StopSign!,ok!)
return False
elseif ls_month <= '00' then
MessageBox("系统提示","身份证号码中的出生月份不能小于01, 请您重新输入 ",StopSign!,ok!)
return False
end if

if ls_day <= '00' then
MessageBox("系统提示","身份证号码的出生日小于01, 请您重新输入 !",StopSign!,ok!)
return False
end if

CHOOSE CASE ls_month
CASE '01','03','05','07','08','10','12'//大月的处理
  if ls_day > '31' then
   MessageBox("系统提示","身份证号码的出生日大于31, 请您重新输入 !",StopSign!,ok!)
   return False
  end if

CASE '04','06','05','09','11' //小月的处理
  
  if ls_day > '30' then
  MessageBox("系统提示","身份证号码的出生日大于30(本月无31日), 请您重新输入 !",StopSign!,ok!)
  return False
  end if
  
CASE '02'  //平年和闰年的处理
  
  ll_year = long(ls_year)
  
  if (mod(ll_year,4) = 0 and Mod(ll_year,100)<>0) or (Mod(ll_year,400) = 0) then   //闰年,二月份不能多于29天
   if ls_day > '29' then
    MessageBox("系统提示","闰年的二月份没有" + ls_day + "日,请重新输入出生日期!",StopSign!,ok!)
    return False
   end if
  else//平年二月份不能大于28天
   if ls_day > '28' then
    MessageBox("系统提示","平年的二月份没有" + ls_day + "日,请重新输入出生日期!",StopSign!,ok!)
    return False
   end if
  end if
  
END CHOOSE

if ls_date > ls_today then
MessageBox("系统提示","身份证号码的出生日期小于登记日期,不合理请您重新输入 !",StopSign!,ok!)
return False
end if

/*==========================验证身份证的最后一位检验码==================================================+/
根据〖*国家标准GB11643-1999〗中有关公民身份号码的
规定,公民身份号码是特征组合码,由十七位数字本码和一位数字校验
码组成。排列顺序从左至右依次为:六位数字地址区位码,八位数字出
生日期码,三位数字顺序码和一位数字校验码。

地址区位码:表示居民常住户口所在县(市、区)的行政区划代码。

出生日期码:表示居民出生的年、月、日,其中年份用四位数字表示,
年、月、日之间不用分隔符。

数字顺序码:表示同一地址区位码所标识的区域范围内,对同年同月同
日出生的人员编定的顺序号。奇数分给男性,偶数分给女性。

数字校验码:根据前面十七位数字码,按照ISO 7064:1983.MOD 11-2校
验码计算出来的检验码。由(1,2,3,4,5,6,7,8,9,X)构成。

下面举例说明该计算方法并用代码实现。

公式:Ax=(∑(Ai×Wi))(mod 11)…………………………(1)

i----表示身份证号码字符从右至左包括校验码在内的位置序号;
Ai----表示第i位置上的数字号码;
Ax----数字校验码的值;
Wi----示第i位置上的加权因子;
公式:Wi=(2^(i-1))(mod 11)…………………………(2)

设某男性公民身份号码为51310119820113001,首先得到各个变量:

i18 17 16 15 14 13 12 11 10 9  8  7  6  5  4  3  2  1

Ai5  1  3  1  0  1  1  9  8  2  0  1  1  3  0  0  1  Ax
由公式(2)可得:
Wi7  9  10 5  8  4  2  1  6  3  7  9  10 5  8  4  2  1

Ai×Wi  35 9  30 5  0  4  2  9  48 6  0  9  10 15 0  0  2  A1

按照公式(1)计算:

∑(Ai×Wi)=(35+9+30+5+0+4+2+9+48+6+0+9+10+15+0+0+2)=184
184÷11=16+8/11
∑(Ai×Wi)(mod 11)=8

然后根据计算的结果,从下表中查出相应的校验码,X表示结果为10:

∑(Ai×WI)(mod 11)0 1 2 3 4 5 6 7 8 9 10
校验码字符值Ai1 0 X 9 8 7 6 5 4 3 2

根据上面的方法,查出计算结果为8的校验码为4所以该人员的公民身份
号码应该为513101198201130014。


/+===============================================================================================================*/
if ll_identity_no_len = 18 then //18位的校验码的检验
  
long Ai=0
string code,old_id
int j
old_id=trim(sle_1.text)

for j=17 to 1 step -1
Ai=Ai+(long(mid(old_id,j,1)))*(mod(2^((18)-j),11))
next

choose case mod(Ai,11)
  case 0
   code='1'
  case 1
   code='0'
  case 2
   code='X'
  case else
   code=string((12)-mod(Ai,11))
end choose

if right(as_identity,1) <> code then
  messagebox("系统提示","最后一位校验位数字不正确",StopSign!,ok!)
  return False
end if

end if

return True