personnummer 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of personnummer might be problematic. Click here for more details.
- data/Changelog +5 -0
- data/LICENSE +18 -0
- data/README.markdown +14 -0
- data/demo.rb +21 -0
- data/lib/personnummer.rb +145 -0
- metadata +66 -0
data/Changelog
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2008 Peter Hellberg
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
5
|
+
the Software without restriction, including without limitation the rights to
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
7
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
8
|
+
subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
15
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
16
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# Personnummer
|
2
|
+
|
3
|
+
Personnummer is a ruby class that handles [Swedish personal identity number](http://en.wikipedia.org/wiki/Personal_identity_number_(Sweden\)).
|
4
|
+
|
5
|
+
### Getting started
|
6
|
+
|
7
|
+
Install from GitHub: <pre>$ gem install c7-personnummer -s http://gems.github.com</pre>
|
8
|
+
|
9
|
+
### Example usage
|
10
|
+
<pre>>> p = Personnummer.new('830428-5912')
|
11
|
+
=> #<Personnummer:0x301128 @number="830428-5912", @age=25, @valid=true, @region="Skaraborgs l\303\244n",
|
12
|
+
@male=true, @born=#<Date: 4890905/2,0,2299161>>
|
13
|
+
>> p.valid?
|
14
|
+
=> true</pre>
|
data/demo.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Real world scripts would use:
|
2
|
+
# require 'rubygems'
|
3
|
+
# require 'personnummer'
|
4
|
+
#
|
5
|
+
# Instead of:
|
6
|
+
require 'lib/personnummer'
|
7
|
+
|
8
|
+
# Valid personnummer
|
9
|
+
p = Personnummer.new(8304285912)
|
10
|
+
designation = (p.male?) ? 'His' : 'Her'
|
11
|
+
puts "#{designation} control digit is: #{p.control_digit}"
|
12
|
+
|
13
|
+
if p.valid?
|
14
|
+
designation = (p.male?) ? 'He' : 'She'
|
15
|
+
puts "#{designation} was born in #{p.region} aproximately #{p.age} years ago" if p.region
|
16
|
+
end
|
17
|
+
|
18
|
+
# Incomplete personnummer
|
19
|
+
p = Personnummer.new('870312-594')
|
20
|
+
designation = (p.male?) ? 'His' : 'Her'
|
21
|
+
puts "#{designation} control digit is: #{p.control_digit}"
|
data/lib/personnummer.rb
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
class Personnummer
|
4
|
+
# Public readonly attributes
|
5
|
+
attr_reader :age, :born, :region, :control_digit
|
6
|
+
|
7
|
+
def initialize(number)
|
8
|
+
|
9
|
+
@valid = false
|
10
|
+
|
11
|
+
# Store the initial number
|
12
|
+
@number = number.to_s
|
13
|
+
|
14
|
+
# Match the number
|
15
|
+
if @number.match(/(\d{2})(\d{2})(\d{2})([\-\+]{0,1})(\d{3})(\d{0,1})/)
|
16
|
+
|
17
|
+
# Calculate the control digit based on the birth date and serial number
|
18
|
+
@control_digit = luhn_algorithm("#{$~[1]}#{$~[2]}#{$~[3]}#{$~[5]}")
|
19
|
+
|
20
|
+
# Get the different parts of the number
|
21
|
+
year = $~[1].to_i
|
22
|
+
month = $~[2].to_i
|
23
|
+
day = $~[3].to_i
|
24
|
+
divider = $~[4]
|
25
|
+
serial = $~[5].to_i
|
26
|
+
|
27
|
+
# Set default divider if not present
|
28
|
+
divider ||= '-'
|
29
|
+
|
30
|
+
# Make the personnummer valid if the checksum is correct
|
31
|
+
@valid = true if @control_digit == $~[6].to_i && !$~[6].empty?
|
32
|
+
|
33
|
+
# Get the current date
|
34
|
+
today = Date.today
|
35
|
+
|
36
|
+
# Decide which century corresponds to the number
|
37
|
+
if year < (today.year-2000) && divider == '-'
|
38
|
+
century = 2000
|
39
|
+
elsif year < (today.year-2000) && divider == '+'
|
40
|
+
century = 1900
|
41
|
+
elsif divider == '+'
|
42
|
+
century = 1800
|
43
|
+
else
|
44
|
+
century = 1900
|
45
|
+
end
|
46
|
+
|
47
|
+
# Get the date the person was born
|
48
|
+
@born = Date.parse("#{century+year}-#{month}-#{day}")
|
49
|
+
|
50
|
+
# Get the region name
|
51
|
+
@region = region_name(serial)
|
52
|
+
|
53
|
+
# Naïve age calculation
|
54
|
+
@age = today.year - @born.year
|
55
|
+
|
56
|
+
# Check if the person is female based the serial (even == female)
|
57
|
+
@female = (serial % 2 == 0)
|
58
|
+
else
|
59
|
+
raise Exception.new, "The supplied personnummer is invalid"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_s
|
64
|
+
@number
|
65
|
+
end
|
66
|
+
|
67
|
+
def valid?
|
68
|
+
@valid
|
69
|
+
end
|
70
|
+
|
71
|
+
def male?
|
72
|
+
!@female
|
73
|
+
end
|
74
|
+
|
75
|
+
def female?
|
76
|
+
@female
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def luhn_algorithm(number)
|
82
|
+
multiplications = []
|
83
|
+
|
84
|
+
number.split(//).each_with_index do |digit, i|
|
85
|
+
if i % 2 == 0
|
86
|
+
multiplications << digit.to_i*2
|
87
|
+
else
|
88
|
+
multiplications << digit.to_i
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
sum = 0
|
93
|
+
multiplications.each do |number|
|
94
|
+
number.to_s.each_byte do |character|
|
95
|
+
sum += character.chr.to_i
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
if sum % 10 == 0
|
100
|
+
control_digit = 0
|
101
|
+
else
|
102
|
+
control_digit = (sum / 10 + 1) * 10 - sum
|
103
|
+
end
|
104
|
+
|
105
|
+
control_digit
|
106
|
+
end
|
107
|
+
|
108
|
+
def region_name(code)
|
109
|
+
|
110
|
+
# Don't return a region name if the person was born after 1990
|
111
|
+
# (When the previous region code was changed to a serial number)
|
112
|
+
if @born.year > 1990
|
113
|
+
return ''
|
114
|
+
end
|
115
|
+
|
116
|
+
case code
|
117
|
+
when 000..139: 'Stockholms Län'
|
118
|
+
when 140..159: 'Uppsala län'
|
119
|
+
when 160..189: 'Södermanlands län'
|
120
|
+
when 190..239: 'Östergötlands län'
|
121
|
+
when 240..269: 'Jönköpings län'
|
122
|
+
when 270..289: 'Kronobergs län'
|
123
|
+
when 290..319: 'Kalmar län'
|
124
|
+
when 320..329: 'Gotlands län'
|
125
|
+
when 330..349: 'Blekinge län'
|
126
|
+
when 350..389: 'Kristianstads län'
|
127
|
+
when 390..459: 'Malmöhus län'
|
128
|
+
when 460..479: 'Hallands län'
|
129
|
+
when 480..549: 'Göteborgs och Bohus län'
|
130
|
+
when 550..589: 'Älvsborgs län'
|
131
|
+
when 590..619: 'Skaraborgs län'
|
132
|
+
when 620..159: 'Värmlands län'
|
133
|
+
when 650..659: 'Födda utomlands'
|
134
|
+
when 660..689: 'Örebro län'
|
135
|
+
when 690..709: 'Västmanlands län'
|
136
|
+
when 710..739: 'Kopparbergs län'
|
137
|
+
when 750..779: 'Gävleborgs län'
|
138
|
+
when 780..819: 'Västernorrlands län'
|
139
|
+
when 820..849: 'Jämtlands län'
|
140
|
+
when 850..889: 'Västerbottens län'
|
141
|
+
when 890..929: 'Norrbottens län'
|
142
|
+
when 930..999: 'Födda utomlands eller utländska medborgare födda i Sverige'
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: personnummer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Peter Hellberg
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2008-08-06 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Personnummer handles validation of Swedish personal identity numbers.
|
22
|
+
email: peter@c7.se
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- README.markdown
|
31
|
+
- Changelog
|
32
|
+
- LICENSE
|
33
|
+
- demo.rb
|
34
|
+
- lib/personnummer.rb
|
35
|
+
has_rdoc: true
|
36
|
+
homepage: http://c7.se/code/personnummer
|
37
|
+
licenses: []
|
38
|
+
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
|
42
|
+
require_paths:
|
43
|
+
- lib
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
segments:
|
49
|
+
- 0
|
50
|
+
version: "0"
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 0
|
57
|
+
version: "0"
|
58
|
+
requirements: []
|
59
|
+
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 1.3.6
|
62
|
+
signing_key:
|
63
|
+
specification_version: 3
|
64
|
+
summary: Personnummer handles validation of Swedish personal identity numbers.
|
65
|
+
test_files: []
|
66
|
+
|