class NationalIdentificationNumber::Swedish
Inspired by github.com/c7/personnummer/blob/master/lib/personnummer.rb Copyright © 2008 Peter Hellberg MIT
Attributes
date[R]
Public Class Methods
generate(date=nil, serial=nil)
click to toggle source
Generator for valid Swedish
personnummer: en.wikipedia.org/wiki/Personal_identity_number_(Sweden) By Henrik Nyh <henrik.nyh.se> 2009-01-29 under the MIT license.
# File lib/national_identification_number/swedish.rb, line 11 def self.generate(date=nil, serial=nil) date ||= Date.new(1900+rand(100), 1+rand(12), 1+rand(28)) serial = serial ? serial.to_s : format("%03d", rand(999)+1) # 001-999 date_part = date.strftime('%y%m%d') pnr = [date_part, serial].join digits = [] pnr.split('').each_with_index do |n,i| digits << n.to_i * (2 - i % 2) end sum = digits.join.split('').inject(0) {|sum,digit| sum + digit.to_i } checksum = 10 - sum % 10 checksum = 0 if checksum == 10 "#{date_part}-#{serial}#{checksum}" end
Private Class Methods
luhn_algorithm(number)
click to toggle source
# File lib/national_identification_number/swedish.rb, line 83 def self.luhn_algorithm(number) multiplications = [] number.split(//).each_with_index do |digit, i| if i % 2 == 0 multiplications << digit.to_i*2 else multiplications << digit.to_i end end sum = 0 multiplications.each do |number| number.to_s.each_byte do |character| sum += character.chr.to_i end end if sum % 10 == 0 control_digit = 0 else control_digit = (sum / 10 + 1) * 10 - sum end control_digit end
Protected Instance Methods
repair()
click to toggle source
Calls superclass method
NationalIdentificationNumber::Base#repair
# File lib/national_identification_number/swedish.rb, line 28 def repair super if @number.match(/\A(\d{0}|\d{2})(\d{6})(\-{0,1})(\d{4})\Z/) @number = "#{$2}-#{$4}" else candidate = @number.gsub(/[^\d\-\+]/, '') if candidate.match(/\A(\d{0}|\d{2})(\d{6})(\-{0,1})(\d{4})\Z/) @number = "#{$2}-#{$4}" else @number = candidate end end end
validate()
click to toggle source
# File lib/national_identification_number/swedish.rb, line 42 def validate if @number.match(/(\d{2})(\d{2})(\d{2})([\-\+]{0,1})(\d{3})(\d{1})/) checksum = self.class.luhn_algorithm("#{$1}#{$2}#{$3}#{$5}") if checksum == $6.to_i year = $1.to_i month = $2.to_i day = $3.to_i divider ||= $4 ||'-' serial = $5.to_i today = Date.today if year <= (today.year-2000) && divider == '-' century = 2000 elsif year <= (today.year-2000) && divider == '+' century = 1900 elsif divider == '+' century = 1800 else preliminary_age = age_for_dob(Date.parse("#{1900 + year}-#{month}-#{day}")) rescue 0 #raise preliminary_age.inspect if preliminary_age > 99 # It's unlikely that the person is older than 99, so assume a child when no divider was provided. century = 2000 else century = 1900 end end begin @date = Date.parse("#{century+year}-#{month}-#{day}") @valid = true @number = ("#{$1}#{$2}#{$3}#{divider}#{$5}#{checksum}") rescue ArgumentError end end end end