BSOne.SFC/Tocsg.Lib/VCL/Tocsg.Valid.pas

132 lines
3.3 KiB
Plaintext

{*******************************************************}
{ }
{ 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.