{*******************************************************} { } { Tocsg.Valid } { } { Copyright (C) 2025 kku } { } {*******************************************************} unit Tocsg.Valid; interface uses System.SysUtils, Winapi.Windows; function IsValidKoreanRegNo(sRegNo: String): Boolean; implementation uses System.DateUtils, Tocsg.Exception; const // 주민번호, 외국인등록번호 검증 가중치 arrWeights: array[1..12] of Integer = (2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5); // 주민번호에서 생년월일 검증 function IsValidDateFromSSN(const SSN: string): Boolean; var nYear, nMonth, nDay, nFYear, n: Integer; dtTemp: TDateTime; begin Result := false; if Length(SSN) < 7 then exit; try nYear := StrToIntDef(Copy(SSN, 1, 2), -1); if nYear = -1 then exit; nMonth := StrToIntDef(Copy(SSN, 3, 2), -1); if nMonth = -1 then exit; nDay := StrToIntDef(Copy(SSN, 5, 2), -1); if nDay = -1 then exit; n := StrToIntDef(SSN[7], -1); if n = -1 then exit; case n of 1, 2: nFYear := 1900 + nYear; 3, 4: nFYear := 2000 + nYear; 5, 6: nFYear := 1900 + nYear; // 외국인 등록번호 (2000년 이전) 7, 8: nFYear := 2000 + nYear; // 외국인 등록번호 (2000년 이후) else exit; end; Result := TryEncodeDate(nFYear, nMonth, nDay, dtTemp); except on E: Exception do ETgException.TraceException(E, 'Fail .. IsValidDateFromSSN()'); end; end; function IsValidForeignRegNo(sRegNo: String): Boolean; var i, nSum, nCheck, nLastDigit: Integer; begin Result := false; if Length(sRegNo) < 13 then exit; // 외국인 등록번호는 7번째 자리가 5~8번이어야 함 if not (sRegNo[7] in ['5', '6', '7', '8']) then exit; // 가중치 계산 nSum := 0; for i := 1 to 12 do nSum := nSum + StrToInt(sRegNo[i]) * arrWeights[i]; // 검증 숫자 계산 nCheck := (11 - (nSum mod 11) + 2) mod 10; nLastDigit := StrToInt(sRegNo[13]); Result := nCheck = nLastDigit; end; // 주민번호 검증 // 외국인등록번호 검증 추가 25_0623 10:45:05 kku // 2017년 이후 새로운 주민번호 방식(예: 지역번호 변경 등)에는 대응하지 않음 function IsValidKoreanRegNo(sRegNo: String): Boolean; var i, nSum, nCheck, nCalc: Integer; begin Result := false; sRegNo := StringReplace(sRegNo, '-', '', [rfReplaceAll]); // 생년월일 유효성 체크 if not IsValidDateFromSSN(sRegNo) then exit; // 13자리 숫자인지 확인 if Length(sRegNo) < 13 then exit; // 외국인 등록번호는 7번째 자리가 5~8번임 if sRegNo[7] in ['5', '6', '7', '8'] then begin Result := IsValidForeignRegNo(sRegNo); exit; end; // 숫자만으로 이루어졌는지 확인 for i := 1 to 13 do if not CharInSet(sRegNo[i], ['0'..'9']) then exit; // 가중치 계산 nSum := 0; for i := 1 to 12 do nSum := nSum + (Ord(sRegNo[i]) - Ord('0')) * arrWeights[i]; // 검증 숫자 계산 nCalc := (11 - (nSum mod 11)) mod 10; nCheck := Ord(sRegNo[13]) - Ord('0'); Result := nCalc = nCheck; end; end.