class Henkilotunnus::Hetu

Constants

CENTURIES
CHECKSUM_CHARS
GENDERS
PERSON_NUMBER_RANGE

Attributes

pin[R]

Public Class Methods

compute_checksum(raw_dob, person_number) click to toggle source
# File lib/henkilotunnus/hetu.rb, line 21
def self.compute_checksum(raw_dob, person_number)
  CHECKSUM_CHARS[ (raw_dob + person_number).to_i % 31 ]
end
generate(opts={}) click to toggle source
# File lib/henkilotunnus/hetu.rb, line 12
def self.generate(opts={})
  dob = opts.fetch(:date, Time.at(rand(Date.new(1800, 1, 1).to_time.to_i...Date.today.to_time.to_i)).to_date)
  raw_dob = dob.strftime("%d%m%y")
  person_number = opts.fetch(:person_number, rand(PERSON_NUMBER_RANGE)).to_s.rjust(3, "0")
  century_sign = CENTURIES.key(dob.year - (dob.year % 100))

  new(raw_dob + century_sign + person_number + compute_checksum(raw_dob, person_number))
end
new(pin) click to toggle source
# File lib/henkilotunnus/hetu.rb, line 27
def initialize(pin)
  @pin = format(pin || '')
end
valid?(pin) click to toggle source
# File lib/henkilotunnus/hetu.rb, line 8
def self.valid?(pin)
  new(pin).valid?
end

Public Instance Methods

age() click to toggle source
# File lib/henkilotunnus/hetu.rb, line 55
def age
  dob = date_of_birth
  # TODO: Should use EEST timezone for everything as Finland has only a single timezone (but with DST!).
  now = Time.now.utc.to_date
  now.year - dob.year - ((now.month > dob.month || (now.month == dob.month && now.day >= dob.day)) ? 0 : 1)
end
century() click to toggle source
# File lib/henkilotunnus/hetu.rb, line 70
def century
  CENTURIES[century_sign]
end
century_sign() click to toggle source
# File lib/henkilotunnus/hetu.rb, line 35
def century_sign
  pin[6]
end
checksum() click to toggle source
# File lib/henkilotunnus/hetu.rb, line 74
def checksum
  pin[10]
end
date_of_birth() click to toggle source
# File lib/henkilotunnus/hetu.rb, line 62
def date_of_birth
  dob = raw_dob
  day = dob[0..1].to_i
  month = dob[2..3].to_i
  year = century + dob[4..5].to_i
  Date.new(year, month, day)
end
female?() click to toggle source
# File lib/henkilotunnus/hetu.rb, line 51
def female?
  gender == 'female'
end
gender() click to toggle source
# File lib/henkilotunnus/hetu.rb, line 43
def gender
  GENDERS[person_number.to_i % 2]
end
male?() click to toggle source
# File lib/henkilotunnus/hetu.rb, line 47
def male?
  gender == 'male'
end
person_number() click to toggle source
# File lib/henkilotunnus/hetu.rb, line 39
def person_number
  pin[7..9]
end
to_s() click to toggle source
# File lib/henkilotunnus/hetu.rb, line 78
def to_s
  pin
end
valid?() click to toggle source
# File lib/henkilotunnus/hetu.rb, line 31
def valid?
  valid_format? && valid_checksum? && valid_person_number?
end

Private Instance Methods

compute_checksum() click to toggle source
# File lib/henkilotunnus/hetu.rb, line 104
def compute_checksum
  self.class.compute_checksum(raw_dob, person_number)
end
format(s) click to toggle source
# File lib/henkilotunnus/hetu.rb, line 88
def format(s)
  s.to_s.gsub(/\s+/, '').upcase
end
raw_dob() click to toggle source
# File lib/henkilotunnus/hetu.rb, line 84
def raw_dob
  pin[0..5]
end
valid_checksum?() click to toggle source
# File lib/henkilotunnus/hetu.rb, line 96
def valid_checksum?
  compute_checksum == checksum
end
valid_format?() click to toggle source
# File lib/henkilotunnus/hetu.rb, line 92
def valid_format?
  !!(pin =~ /^\d{6}[-+A]\d{3}[0-9A-Z]$/)
end
valid_person_number?() click to toggle source
# File lib/henkilotunnus/hetu.rb, line 100
def valid_person_number?
  PERSON_NUMBER_RANGE.cover?(person_number.to_i)
end