Validate a South African ID Number
Besides checking the length of a South African ID number for validation, our developer Clive Crous thought there must be an official checksum. After piecing together multiple google searches he has build a ruby class which validates our customer ID numbers. Our online debit engine is enhanced a little further.
Below is the ruby code, enjoy
Download the identity_number.rb file
1 require ‘time‘ # Used for verifying date of birth portion of ID Number
2
3 class SouthAfricanIDNumber
4
5 # The format of a normal South-African ID number is as follows
6 # {YYMMDD}{G}{SSS}{A}{Z}
7 # YYMMDD: Date of birth
8 # G : Gender. 0-4 Female; 5-9 Male.
9 # SSS : Sequence No. for DOB/G combination.
10 # C : Citizenship. 0 SA; 1 Other.
11 # A : Usually 8, or 9 (can be other values)
12 # Z : Control digit.
13
14 def initialize( number )
15 @number = number.to_s
16 end
17
18 def gender
19 self[6] > 4 ? :male : :female
20 end
21
22 def south_african?
23 self[10] == 0
24 end
25
26 def generate_check_digit
27 odd_digits = @number.scan(/../).map{|n|n[0].chr}
28 even_digits = @number.scan(/../).map{|n|n[1].chr}
29
30 sum_of_odd_digits = odd_digits.inject(0){ |total,digit| total + digit.to_i }
31
32 combined_and_multiplied_even_digits = even_digits.join(”).to_i * 2
33
34 sum_of_even_digits_multiplied =
35 combined_and_multiplied_even_digits.to_s.scan(/./).inject(0){|total,digit|total + digit.to_i }
36
37 ( 10 – ( (sum_of_odd_digits + sum_of_even_digits_multiplied) % 10 ) ) % 10
38 end
39
40 def valid_format?
41 @number =~ /^[0-9]{13}$/ ? true : false
42 end
43
44 def valid_birth_date?
45 begin
46 return false unless Time.parse(@number[0..5]).strftime(‘%y%m%d‘) == @number[0..5]
47 rescue
48 return false
49 end
50 true
51 end
52
53 def valid_check_digit?
54 self[12] == generate_check_digit
55 end
56
57 def valid?
58 valid_format? and valid_birth_date? and valid_check_digit?
59 end
60
61 def to_s
62 @number
63 end
64
65 def []( character_enum )
66 begin
67 @number[character_enum].chr.to_i
68 rescue
69 nil
70 end
71 end
72
73 end
74
