c7-personnummer 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+