function ValidatePID(const APID: string): string; {内部函数,取身份证号校验位,最后一位,对18位有效} function GetVerifyBit(sIdentityNum: string): Char; var nNum: Integer; begin Result := #0; nNum := StrToInt(sIdentityNum[1]) * 7 + StrToInt(sIdentityNum[2]) * 9 + StrToInt(sIdentityNum[3]) * 10 + StrToInt(sIdentityNum[4]) * 5 + StrToInt(sIdentityNum[5]) * 8 + StrToInt(sIdentityNum[6]) * 4 + StrToInt(sIdentityNum[7]) * 2 + StrToInt(sIdentityNum[8]) * 1 + StrToInt(sIdentityNum[9]) * 6 + StrToInt(sIdentityNum[10]) * 3 + StrToInt(sIdentityNum[11]) * 7 + StrToInt(sIdentityNum[12]) * 9 + StrToInt(sIdentityNum[13]) * 10 + StrToInt(sIdentityNum[14]) * 5 + StrToInt(sIdentityNum[15]) * 8 + StrToInt(sIdentityNum[16]) * 4 + StrToInt(sIdentityNum[17]) * 2; nNum := nNum mod 11; case nNum of 0: Result := '1'; 1: Result := '0'; 2: Result := 'X'; 3: Result := '9'; 4: Result := '8'; 5: Result := '7'; 6: Result := '6'; 7: Result := '5'; 8: Result := '4'; 9: Result := '3'; 10: Result := '2'; end; end; var L : Integer; sCentury : string; sYear2Bit : string; sMonth : string; sDate : string; iCentury : Integer; iMonth : Integer; iDate : Integer; CRCFact : string;//18位证号的实际值 CRCTh : string; //18位证号的理论值 FebDayAmt: Byte;//2月天数 begin L := Length(APID); if (L in [15, 18]) = False then begin Result := Format('身份证号不是15位或18位(%0:s, 实际位数:%1:d)', [APID, L]); Exit; end; CRCFact := ''; if L = 18 then begin sCentury := Copy(APID, 7, 2); iCentury := StrToInt(sCentury); if (iCentury in [18..20]) = False then begin Result := Format('身份证号码无效:18位证号的年份前两位必须在18-20之间(%0:S)', [sCentury]); Exit; end; sYear2Bit := Copy(APID, 9, 2); sMonth := Copy(APID, 11, 2); sDate := Copy(APID, 13, 2); CRCFact := Copy(APID, 18, 1); end else begin sCentury := '19'; sYear2Bit := Copy(APID, 7, 2); sMonth := Copy(APID, 9, 2); sDate := Copy(APID, 11, 2); end; iMonth := StrToInt(sMonth); iDate := StrToInt(sDate); if (iMonth in [01..12]) = False then begin Result := Format('身份证号码无效:月份必须在01-12之间(%0:s)', [sMonth]); Exit; end; if (iMonth in [1, 3, 5, 7, 8, 10, 12]) then begin if (iDate in [01..31]) = False then begin Result := Format('身份证号码无效:日期无效,不能为零或超出当月最大值(%0:s)', [sDate]); Exit; end; end; if (iMonth in [4, 6, 9, 11]) then begin if (iDate in [01..30]) = False then begin Result := Format('身份证号码无效:日期无效,不能为零或超出当月最大值(%0:s)', [sDate]); Exit; end; end; if IsLeapYear(StrToInt(sCentury + sYear2Bit)) = True then begin FebDayAmt := 29; end else begin FebDayAmt := 28; end; if (iMonth in [2]) then begin if (iDate in [01..FebDayAmt]) = False then begin Result := Format('身份证号码无效:日期无效,不能为零或超出当月最大值(%0:s)', [sDate]); Exit; end; end; if CRCFact <> '' then begin CRCTh := GetVerifyBit(APID); if CRCFact <> CRCTh then begin Result := Format('身份证号码无效:校验位(第18位)错:(%0:s)', [APID]); Exit; end; end; end;