personnummer 0.0.4 → 0.0.5

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/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ coverage/*
2
+ coverage.data
3
+ personnummer-*.gem
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/Changelog CHANGED
@@ -1,10 +1,14 @@
1
+ 0.0.5 Released
2
+
3
+ 2011-11-25: Tests!
4
+
1
5
  0.0.4 Released
2
6
 
3
- 2011-01-10: Ruby 1.9 compatibility fixes
7
+ 2011-01-09: Ruby 1.9 support
4
8
 
5
9
  0.0.3 Released
6
10
 
7
- 2010-04-19: (Less) naïve age calculation
11
+ 2010-04-19: (Less) naïve age calculation
8
12
 
9
13
  0.0.2 Released
10
14
 
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in personnummer.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,60 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ personnummer (0.0.3)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ archive-tar-minitar (0.5.2)
10
+ columnize (0.3.4)
11
+ configatron (2.8.3)
12
+ yamler (>= 0.1.0)
13
+ cover_me (1.2.0)
14
+ configatron
15
+ hashie
16
+ diff-lcs (1.1.3)
17
+ guard (0.8.4)
18
+ thor (~> 0.14.6)
19
+ guard-bundler (0.1.3)
20
+ bundler (>= 1.0.0)
21
+ guard (>= 0.2.2)
22
+ guard-rspec (0.4.5)
23
+ guard (>= 0.4.0)
24
+ hashie (1.1.0)
25
+ linecache19 (0.5.12)
26
+ ruby_core_source (>= 0.1.4)
27
+ rspec (2.7.0)
28
+ rspec-core (~> 2.7.0)
29
+ rspec-expectations (~> 2.7.0)
30
+ rspec-mocks (~> 2.7.0)
31
+ rspec-core (2.7.1)
32
+ rspec-expectations (2.7.0)
33
+ diff-lcs (~> 1.1.2)
34
+ rspec-mocks (2.7.0)
35
+ ruby-debug-base19 (0.11.25)
36
+ columnize (>= 0.3.1)
37
+ linecache19 (>= 0.5.11)
38
+ ruby_core_source (>= 0.1.4)
39
+ ruby-debug19 (0.11.6)
40
+ columnize (>= 0.3.1)
41
+ linecache19 (>= 0.5.11)
42
+ ruby-debug-base19 (>= 0.11.19)
43
+ ruby_core_source (0.1.5)
44
+ archive-tar-minitar (>= 0.5.2)
45
+ thor (0.14.6)
46
+ timecop (0.3.5)
47
+ yamler (0.1.0)
48
+
49
+ PLATFORMS
50
+ ruby
51
+
52
+ DEPENDENCIES
53
+ cover_me
54
+ guard
55
+ guard-bundler
56
+ guard-rspec
57
+ personnummer!
58
+ rspec
59
+ ruby-debug19
60
+ timecop
data/Guardfile ADDED
@@ -0,0 +1,14 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'bundler' do
5
+ watch('Gemfile')
6
+ watch(/^.+\.gemspec/)
7
+ end
8
+
9
+ guard 'rspec', :version => 2, :all_after_pass => false, :all_on_start => false do
10
+ watch(%r{^spec/.+_spec\.rb$})
11
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
12
+ watch('spec/spec_helper.rb') { "spec" }
13
+ end
14
+
data/README.markdown CHANGED
@@ -2,13 +2,14 @@
2
2
 
3
3
  Personnummer is a ruby class that handles [Swedish personal identity number](http://en.wikipedia.org/wiki/Personal_identity_number_(Sweden\)).
4
4
 
5
- ### Getting started
5
+ ### Installation
6
6
 
7
- Install from GitHub: <pre>$ gem install c7-personnummer -s http://gems.github.com</pre>
7
+ $ gem install personnummer
8
8
 
9
9
  ### Example usage
10
+
10
11
  <pre>&gt;&gt; p = Personnummer.new('830428-5912')
11
12
  =&gt; #&lt;Personnummer:0x301128 @number="830428-5912", @age=25, @valid=true, @region="Skaraborgs l\303\244n",
12
13
  @male=true, @born=#&lt;Date: 4890905/2,0,2299161&gt;&gt;
13
14
  &gt;&gt; p.valid?
14
- =&gt; true</pre>
15
+ =&gt; true</pre>
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ namespace :cover_me do
7
+ desc "Generates and opens code coverage report."
8
+ task :report do
9
+ require 'cover_me'
10
+ CoverMe.complete!
11
+ end
12
+ end
13
+
14
+ task :default => :spec
data/lib/personnummer.rb CHANGED
@@ -1,18 +1,16 @@
1
- # encoding: utf-8
1
+ # -*- encoding: utf-8 -*-
2
2
  require 'date'
3
3
 
4
4
  class Personnummer
5
5
  # Public readonly attributes
6
- attr_reader :age, :born, :region, :control_digit
6
+ attr_reader :born, :region, :control_digit
7
7
 
8
8
  def initialize(number)
9
-
10
9
  @valid = false
11
- # Store the initial number
12
- @number = number.to_s
13
10
 
14
11
  # Match the number
15
- if @number.match(/(\d{2})(\d{2})(\d{2})([\-\+]{0,1})(\d{3})(\d{0,1})/)
12
+ number = number.to_s
13
+ if number.match(/(\d{2})(\d{2})(\d{2})([\-\+]{0,1})(\d{3})(\d{0,1})/)
16
14
 
17
15
  # Calculate the control digit based on the birth date and serial number
18
16
  @control_digit = luhn_algorithm("#{$~[1]}#{$~[2]}#{$~[3]}#{$~[5]}")
@@ -21,11 +19,13 @@ class Personnummer
21
19
  year = $~[1].to_i
22
20
  month = $~[2].to_i
23
21
  day = $~[3].to_i
24
- divider = $~[4]
25
- serial = $~[5].to_i
22
+ @divider = $~[4]
23
+ @serial = $~[5].to_i
26
24
 
27
25
  # Set default divider if not present
28
- divider ||= '-'
26
+ if @divider.empty?
27
+ @divider = '-'
28
+ end
29
29
 
30
30
  # Make the personnummer valid if the checksum is correct
31
31
  @valid = true if @control_digit == $~[6].to_i && !$~[6].empty?
@@ -34,11 +34,11 @@ class Personnummer
34
34
  today = Date.today
35
35
 
36
36
  # Decide which century corresponds to the number
37
- if year < (today.year-2000) && divider == '-'
37
+ if year < (today.year-2000) && @divider == '-'
38
38
  century = 2000
39
- elsif year < (today.year-2000) && divider == '+'
39
+ elsif year < (today.year-2000) && @divider == '+'
40
40
  century = 1900
41
- elsif divider == '+'
41
+ elsif @divider == '+'
42
42
  century = 1800
43
43
  else
44
44
  century = 1900
@@ -48,20 +48,25 @@ class Personnummer
48
48
  @born = Date.parse("#{century+year}-#{month}-#{day}")
49
49
 
50
50
  # Get the region name
51
- @region = region_name(serial)
52
-
53
- # (Less) naïve age calculation
54
- @age = ((today - @born).to_i/365)
51
+ @region = region_name(@serial)
55
52
 
56
53
  # Check if the person is female based the serial (even == female)
57
- @female = (serial % 2 == 0)
54
+ @female = (@serial % 2 == 0)
55
+ else
56
+ raise ArgumentError.new, "The supplied personnummer is invalid"
57
+ end
58
+ end
59
+
60
+ def age
61
+ if Date.today > @born
62
+ (Date.today - @born).to_i/365
58
63
  else
59
- raise Exception.new, "The supplied personnummer is invalid"
64
+ 0
60
65
  end
61
66
  end
62
67
 
63
68
  def to_s
64
- @number
69
+ "%s%s%03d%d" % [@born.strftime("%y%m%d"), @divider, @serial, @control_digit]
65
70
  end
66
71
 
67
72
  def valid?
@@ -129,7 +134,7 @@ private
129
134
  when 480..549 then 'Göteborgs och Bohus län'
130
135
  when 550..589 then 'Älvsborgs län'
131
136
  when 590..619 then 'Skaraborgs län'
132
- when 620..159 then 'Värmlands län'
137
+ when 620..649 then 'Värmlands län'
133
138
  when 650..659 then 'Födda utomlands'
134
139
  when 660..689 then 'Örebro län'
135
140
  when 690..709 then 'Västmanlands län'
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "personnummer"
6
+ s.version = "0.0.5"
7
+ s.authors = ["Peter Hellberg", "Victor Koronen"]
8
+ s.email = ["peter@c7.se"]
9
+ s.homepage = "https://github.com/c7/personnummer/"
10
+ s.summary = %q{Personnummer handles validation of Swedish personal identity numbers.}
11
+ s.description = %q{Personnummer handles validation of Swedish personal identity numbers.}
12
+
13
+ s.has_rdoc = false
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_development_dependency "ruby-debug19"
21
+ s.add_development_dependency "rspec"
22
+ s.add_development_dependency "guard"
23
+ s.add_development_dependency "guard-bundler"
24
+ s.add_development_dependency "guard-rspec"
25
+ s.add_development_dependency "cover_me"
26
+ s.add_development_dependency "timecop"
27
+ end
@@ -0,0 +1,145 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'spec_helper'
3
+ require 'personnummer'
4
+ require 'timecop'
5
+
6
+ describe Personnummer do
7
+ describe "initialize" do
8
+ it "accepts a valid personnummer (with control digit)" do
9
+ expect{ Personnummer.new(9001010017) }.not_to raise_error(ArgumentError)
10
+ expect{ Personnummer.new('900101-0017') }.not_to raise_error(ArgumentError)
11
+ expect{ Personnummer.new('100101+0017') }.not_to raise_error(ArgumentError)
12
+ end
13
+
14
+ it "accepts a valid personnummer (without control digit)" do
15
+ expect{ Personnummer.new(900101001) }.not_to raise_error(ArgumentError)
16
+ expect{ Personnummer.new('900101-001') }.not_to raise_error(ArgumentError)
17
+ expect{ Personnummer.new('100101+001') }.not_to raise_error(ArgumentError)
18
+ end
19
+
20
+ it "throws ArgumentError on an invalid personnummer" do
21
+ expect{ Personnummer.new(nil) }.to raise_error(ArgumentError)
22
+ expect{ Personnummer.new(17) }.to raise_error(ArgumentError)
23
+ expect{ Personnummer.new('112233-4455') }.to raise_error(ArgumentError)
24
+ end
25
+ end
26
+
27
+ describe "age" do
28
+ it "calculates age correctly" do
29
+ p = Personnummer.new('900101-001')
30
+
31
+ Timecop.freeze(Date.parse('1980-01-01')) do
32
+ p.age.should == 0
33
+ end
34
+ Timecop.freeze(Date.parse('1990-01-01')) do
35
+ p.age.should == 0
36
+ end
37
+ Timecop.freeze(Date.parse('2000-01-01')) do
38
+ p.age.should == 10
39
+ end
40
+ Timecop.freeze(Date.parse('2090-01-01')) do
41
+ p.age.should == 100
42
+ end
43
+ end
44
+ end
45
+
46
+ describe "born" do
47
+ it "returns the correct date" do
48
+ Timecop.freeze(Date.parse('2010-01-01')) do
49
+ Personnummer.new('900101-001').born.should == Date.parse('1990-01-01')
50
+ Personnummer.new('010101-001').born.should == Date.parse('2001-01-01')
51
+ Personnummer.new('100101+001').born.should == Date.parse('1810-01-01')
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "region" do
57
+ it "returns '' for persons born on or after 1991-01-01" do
58
+ Personnummer.new('910101-001').region.should == ''
59
+ end
60
+
61
+ it "returns the correct region for persons born before 1991-01-01" do
62
+ it_maps_range_to_region 000..139, 'Stockholms Län'
63
+ it_maps_range_to_region 140..159, 'Uppsala län'
64
+ it_maps_range_to_region 160..189, 'Södermanlands län'
65
+ it_maps_range_to_region 190..239, 'Östergötlands län'
66
+ it_maps_range_to_region 240..269, 'Jönköpings län'
67
+ it_maps_range_to_region 270..289, 'Kronobergs län'
68
+ it_maps_range_to_region 290..319, 'Kalmar län'
69
+ it_maps_range_to_region 320..329, 'Gotlands län'
70
+ it_maps_range_to_region 330..349, 'Blekinge län'
71
+ it_maps_range_to_region 350..389, 'Kristianstads län'
72
+ it_maps_range_to_region 390..459, 'Malmöhus län'
73
+ it_maps_range_to_region 460..479, 'Hallands län'
74
+ it_maps_range_to_region 480..549, 'Göteborgs och Bohus län'
75
+ it_maps_range_to_region 550..589, 'Älvsborgs län'
76
+ it_maps_range_to_region 590..619, 'Skaraborgs län'
77
+ it_maps_range_to_region 620..649, 'Värmlands län'
78
+ it_maps_range_to_region 650..659, 'Födda utomlands'
79
+ it_maps_range_to_region 660..689, 'Örebro län'
80
+ it_maps_range_to_region 690..709, 'Västmanlands län'
81
+ it_maps_range_to_region 710..739, 'Kopparbergs län'
82
+ it_maps_range_to_region 750..779, 'Gävleborgs län'
83
+ it_maps_range_to_region 780..819, 'Västernorrlands län'
84
+ it_maps_range_to_region 820..849, 'Jämtlands län'
85
+ it_maps_range_to_region 850..889, 'Västerbottens län'
86
+ it_maps_range_to_region 890..929, 'Norrbottens län'
87
+ it_maps_range_to_region 930..999, 'Födda utomlands eller utländska medborgare födda i Sverige'
88
+ end
89
+ end
90
+
91
+ describe "control_digit" do
92
+ it "responds with the right control digit" do
93
+ Personnummer.new(9001010017).control_digit.should == 7
94
+ Personnummer.new('900101-0017').control_digit.should == 7
95
+ Personnummer.new('900101-001').control_digit.should == 7
96
+ end
97
+ end
98
+
99
+ describe "to_s" do
100
+ it "uses the standard string representation" do
101
+ Personnummer.new(9001010017).to_s.should == '900101-0017'
102
+ Personnummer.new('900101-0017').to_s.should == '900101-0017'
103
+ Personnummer.new('900101-001').to_s.should == '900101-0017'
104
+ end
105
+ end
106
+
107
+ describe "valid?" do
108
+ it "marks a valid personnummer with control digit as valid" do
109
+ Personnummer.new('900101-0017').should be_valid
110
+ end
111
+
112
+ it "marks a valid personnummer without control digit as invalid" do
113
+ Personnummer.new('900101-001').should_not be_valid
114
+ end
115
+
116
+ it "throws ArgumentError on an invalid personnummer" do
117
+ expect{ Personnummer.new('112233-4455') }.to raise_error(ArgumentError)
118
+ end
119
+ end
120
+
121
+ describe "gender" do
122
+ it "recognizes males" do
123
+ Personnummer.new('900101-001').should be_male
124
+ Personnummer.new('900101-003').should be_male
125
+ Personnummer.new('900101-005').should be_male
126
+ Personnummer.new('900101-007').should be_male
127
+ Personnummer.new('900101-009').should be_male
128
+ end
129
+
130
+ it "recognizes females" do
131
+ Personnummer.new('900101-000').should be_female
132
+ Personnummer.new('900101-002').should be_female
133
+ Personnummer.new('900101-004').should be_female
134
+ Personnummer.new('900101-006').should be_female
135
+ Personnummer.new('900101-008').should be_female
136
+ end
137
+ end
138
+
139
+ private
140
+
141
+ def it_maps_range_to_region(range, region)
142
+ Personnummer.new('901231-%03d' % range.first).region.should == region
143
+ Personnummer.new('901231-%03d' % range.last).region.should == region
144
+ end
145
+ end
@@ -0,0 +1,6 @@
1
+ $: << File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ require 'cover_me'
4
+
5
+ RSpec.configure do |config|
6
+ end
metadata CHANGED
@@ -1,68 +1,139 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: personnummer
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 4
9
- version: 0.0.4
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Peter Hellberg
9
+ - Victor Koronen
13
10
  autorequire:
14
11
  bindir: bin
15
12
  cert_chain: []
16
-
17
- date: 2011-01-10 00:00:00 +01:00
18
- default_executable:
19
- dependencies: []
20
-
13
+ date: 2011-11-25 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: ruby-debug19
17
+ requirement: &70323661135380 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: *70323661135380
26
+ - !ruby/object:Gem::Dependency
27
+ name: rspec
28
+ requirement: &70323661134940 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: *70323661134940
37
+ - !ruby/object:Gem::Dependency
38
+ name: guard
39
+ requirement: &70323661134520 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *70323661134520
48
+ - !ruby/object:Gem::Dependency
49
+ name: guard-bundler
50
+ requirement: &70323661134100 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *70323661134100
59
+ - !ruby/object:Gem::Dependency
60
+ name: guard-rspec
61
+ requirement: &70323661133680 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *70323661133680
70
+ - !ruby/object:Gem::Dependency
71
+ name: cover_me
72
+ requirement: &70323661133260 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: *70323661133260
81
+ - !ruby/object:Gem::Dependency
82
+ name: timecop
83
+ requirement: &70323661132840 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: *70323661132840
21
92
  description: Personnummer handles validation of Swedish personal identity numbers.
22
- email: peter@c7.se
93
+ email:
94
+ - peter@c7.se
23
95
  executables: []
24
-
25
96
  extensions: []
26
-
27
97
  extra_rdoc_files: []
28
-
29
- files:
30
- - README.markdown
98
+ files:
99
+ - .gitignore
100
+ - .rspec
31
101
  - Changelog
102
+ - Gemfile
103
+ - Gemfile.lock
104
+ - Guardfile
32
105
  - LICENSE
106
+ - README.markdown
107
+ - Rakefile
33
108
  - demo.rb
34
109
  - lib/personnummer.rb
35
- has_rdoc: true
36
- homepage: http://c7.se/code/personnummer
110
+ - personnummer.gemspec
111
+ - spec/lib/personnummer_spec.rb
112
+ - spec/spec_helper.rb
113
+ homepage: https://github.com/c7/personnummer/
37
114
  licenses: []
38
-
39
115
  post_install_message:
40
116
  rdoc_options: []
41
-
42
- require_paths:
117
+ require_paths:
43
118
  - lib
44
- required_ruby_version: !ruby/object:Gem::Requirement
119
+ required_ruby_version: !ruby/object:Gem::Requirement
45
120
  none: false
46
- requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- segments:
50
- - 0
51
- version: "0"
52
- required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
126
  none: false
54
- requirements:
55
- - - ">="
56
- - !ruby/object:Gem::Version
57
- segments:
58
- - 0
59
- version: "0"
127
+ requirements:
128
+ - - ! '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
60
131
  requirements: []
61
-
62
132
  rubyforge_project:
63
- rubygems_version: 1.3.7
133
+ rubygems_version: 1.8.6
64
134
  signing_key:
65
135
  specification_version: 3
66
136
  summary: Personnummer handles validation of Swedish personal identity numbers.
67
- test_files: []
68
-
137
+ test_files:
138
+ - spec/lib/personnummer_spec.rb
139
+ - spec/spec_helper.rb