c7-personnummer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data/Changelog +1 -0
  2. data/LICENSE +18 -0
  3. data/README.markdown +14 -0
  4. data/demo.rb +21 -0
  5. data/lib/personnummer.rb +141 -0
  6. metadata +57 -0
data/Changelog ADDED
@@ -0,0 +1 @@
1
+ 0.0.1 Released
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>&gt;&gt; p = Personnummer.new('830428-5912')
11
+ =&gt; #&lt;Personnummer:0x301128 @number="830428-5912", @age=25, @valid=true, @region="Skaraborgs l\303\244n",
12
+ @male=true, @born=#&lt;Date: 4890905/2,0,2299161&gt;&gt;
13
+ &gt;&gt; p.valid?
14
+ =&gt; 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('830428-5912')
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}"
@@ -0,0 +1,141 @@
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
+ @valid = false
9
+
10
+ # Store the initial number
11
+ @number = number
12
+
13
+ # Match the number
14
+ if number.match(/(\d{2})(\d{2})(\d{2})([\-\+])(\d{3})(\d{0,1})/)
15
+
16
+ # Calculate the control digit based on the birth date and serial number
17
+ @control_digit = luhn_algorithm("#{$~[1]}#{$~[2]}#{$~[3]}#{$~[5]}")
18
+
19
+ # Get the different parts of the number
20
+ year = $~[1].to_i
21
+ month = $~[2].to_i
22
+ day = $~[3].to_i
23
+ divider = $~[4]
24
+ serial = $~[5].to_i
25
+
26
+ # Make the personnummer valid if the checksum is correct
27
+ @valid = true if @control_digit == $~[6].to_i && !$~[6].empty?
28
+
29
+ # Get the current date
30
+ today = Date.today
31
+
32
+ # Decide which century corresponds to the number
33
+ if year < (today.year-2000) && divider == '-'
34
+ century = 2000
35
+ elsif year < (today.year-2000) && divider == '+'
36
+ century = 1900
37
+ elsif divider == '+'
38
+ century = 1800
39
+ else
40
+ century = 1900
41
+ end
42
+
43
+ # Get the date the person was born
44
+ @born = Date.parse("#{century+year}-#{month}-#{day}")
45
+
46
+ # Get the region name
47
+ @region = region_name(serial)
48
+
49
+ # Naïve age calculation
50
+ @age = today.year - @born.year
51
+
52
+ # Check if the person is female based the serial (even == female)
53
+ @female = (serial % 2 == 0)
54
+ else
55
+ raise Exception.new, "The supplied personnummer is invalid"
56
+ end
57
+ end
58
+
59
+ def to_s
60
+ @number
61
+ end
62
+
63
+ def valid?
64
+ @valid
65
+ end
66
+
67
+ def male?
68
+ !@female
69
+ end
70
+
71
+ def female?
72
+ @female
73
+ end
74
+
75
+ private
76
+
77
+ def luhn_algorithm(number)
78
+ multiplications = []
79
+
80
+ number.split(//).each_with_index do |digit, i|
81
+ if i % 2 == 0
82
+ multiplications << digit.to_i*2
83
+ else
84
+ multiplications << digit.to_i
85
+ end
86
+ end
87
+
88
+ sum = 0
89
+ multiplications.each do |number|
90
+ number.to_s.each_byte do |character|
91
+ sum += character.chr.to_i
92
+ end
93
+ end
94
+
95
+ if sum % 10 == 0
96
+ control_digit = 0
97
+ else
98
+ control_digit = (sum / 10 + 1) * 10 - sum
99
+ end
100
+
101
+ control_digit
102
+ end
103
+
104
+ def region_name(code)
105
+
106
+ # Don't return a region name if the person was born before 1990
107
+ # (When the previous region code was changed to a serial number)
108
+ if @born.year > 1990
109
+ return ''
110
+ end
111
+
112
+ case code
113
+ when 000..139: 'Stockholms Län'
114
+ when 140..159: 'Uppsala län'
115
+ when 160..189: 'Södermanlands län'
116
+ when 190..239: 'Östergötlands län'
117
+ when 240..269: 'Jönköpings län'
118
+ when 270..289: 'Kronobergs län'
119
+ when 290..319: 'Kalmar län'
120
+ when 320..329: 'Gotlands län'
121
+ when 330..349: 'Blekinge län'
122
+ when 350..389: 'Kristianstads län'
123
+ when 390..459: 'Malmöhus län'
124
+ when 460..479: 'Hallands län'
125
+ when 480..549: 'Göteborgs och Bohus län'
126
+ when 550..589: 'Älvsborgs län'
127
+ when 590..619: 'Skaraborgs län'
128
+ when 620..159: 'Värmlands län'
129
+ when 650..659: 'Födda utomlands'
130
+ when 660..689: 'Örebro län'
131
+ when 690..709: 'Västmanlands län'
132
+ when 710..739: 'Kopparbergs län'
133
+ when 750..779: 'Gävleborgs län'
134
+ when 780..819: 'Västernorrlands län'
135
+ when 820..849: 'Jämtlands län'
136
+ when 850..889: 'Västerbottens län'
137
+ when 890..929: 'Norrbottens län'
138
+ when 930..999: 'Födda utomlands eller utländska medborgare födda i Sverige'
139
+ end
140
+ end
141
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: c7-personnummer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Peter Hellberg
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-08-06 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Personnummer handles validation of Swedish personal identity numbers.
17
+ email: peter@c7.se
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - README.markdown
26
+ - Changelog
27
+ - LICENSE
28
+ - demo.rb
29
+ - lib/personnummer.rb
30
+ has_rdoc: false
31
+ homepage: http://c7.se/code/personnummer
32
+ post_install_message:
33
+ rdoc_options: []
34
+
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: "0"
42
+ version:
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ requirements: []
50
+
51
+ rubyforge_project:
52
+ rubygems_version: 1.2.0
53
+ signing_key:
54
+ specification_version: 2
55
+ summary: Personnummer handles validation of Swedish personal identity numbers.
56
+ test_files: []
57
+