identitycode 0.1.3 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f8a78b100dec78b3c17fde161be9654a7d69a601
4
- data.tar.gz: abcc6067320e6bce69263e3f66965a972e04337a
3
+ metadata.gz: 8cfc172aeb2d5abd52ea44ebbadc44025ef8010c
4
+ data.tar.gz: ba6ef782a21f0173f63558d42d402a51e5ebcbe4
5
5
  SHA512:
6
- metadata.gz: dde0a94e68ed2c7ffec3b63a9e7ac6b3c32c86c67f65879dc33ea10a16208c1cf8180918b26ebcb84745ced85bfb96c1639b4a020fbda5135e070b73aea97773
7
- data.tar.gz: 52ae5c15f4dae06925f9c79b16071e2bbee70ecdfeed1e37cd18e33aa67c834b29cd82b1f69b3d99811d002e58eb4e60678be2e8d1f4a4ec951c50898394f02e
6
+ metadata.gz: 278c2f861d6a222a31d5f3f9b3bea27600fc587a804a27c46916270ef033e13edde802839657eee38484c18453b9095d09f75983c86b1eac2f208ca14a8676f7
7
+ data.tar.gz: 354d693d5f86494c4c1f94bcba338bbea1a3f4b12296c04c0332b5f3c258560e3c26ebf30c9b146212e34eb5de1bb96a44333257c8ab3633343947cf20d7e860
data/README.md CHANGED
@@ -18,12 +18,18 @@ Or install it yourself as:
18
18
 
19
19
  ## Usage
20
20
 
21
+ This gem supports Estonian and Latvian identity codes. Just specify `EE` or `LV` class accordingly (`IdentityCode::EE` or `IdentityCode::LV`)
22
+
23
+ *NB*: Latvian identity codes don't have sex support
24
+
21
25
  ```ruby
22
26
  > require 'identity_code'
23
- > code = IdentityCode::Isikukood.new('38312203720')
27
+ > code = IdentityCode::EE.new('38312203720')
24
28
  > code.valid?
25
29
  # or
26
- > IdentityCode::Isikukood.valid?('38312203720')
30
+ > IdentityCode::EE.valid?('38312203720')
31
+ => true
32
+ > IdentityCode::LV.valid?('20128315289')
27
33
  => true
28
34
  > code.sex
29
35
  => 'M'
@@ -32,10 +38,12 @@ Or install it yourself as:
32
38
  > code.age
33
39
  => 31
34
40
  # Generate random valid identity code
35
- > IdentityCode::Isikukood.generate
41
+ > IdentityCode::EE.generate
36
42
  => '37504163700'
37
- > IdentityCode::Isikukood.generate(sex: 'M', year: 1983, month: 12, day: 20)
43
+ > IdentityCode::EE.generate(sex: 'M', year: 1983, month: 12, day: 20)
38
44
  => '38312209528'
45
+ > IdentityCode::LV.generate(year: 1983, month: 12, day: 20, separator: true)
46
+ => '201283-15289'
39
47
  ```
40
48
 
41
49
  ## Development
data/identitycode.gemspec CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ['Artem Pakk']
10
10
  spec.email = ['apakk@me.com']
11
11
 
12
- spec.summary = %q{Ruby gem to generate and validate Estonian identity codes}
13
- spec.description = %q{Ruby gem to generate and validate Estonian identity codes}
12
+ spec.summary = %q{Ruby gem to generate and validate Estonian and Latvian identity codes}
13
+ spec.description = %q{Ruby gem to generate and validate Estonian and Latvian identity codes}
14
14
  spec.homepage = 'https://github.com/defeed/identitycode'
15
15
  spec.license = "MIT"
16
16
 
@@ -0,0 +1,106 @@
1
+ require 'date'
2
+
3
+ module IdentityCode
4
+ class EE
5
+ HOSPITALS = [
6
+ '00', # Kuressaare Haigla (järjekorranumbrid 001 kuni 020)
7
+ '01', # Tartu Ülikooli Naistekliinik, Tartumaa, Tartu (011...019)
8
+ '02', # Ida-Tallinna Keskhaigla, Hiiumaa, Keila, Rapla haigla (021...220)
9
+ '22', # Ida-Viru Keskhaigla (Kohtla-Järve, endine Jõhvi) (221...270)
10
+ '27', # Maarjamõisa Kliinikum (Tartu), Jõgeva Haigla (271...370)
11
+ '37', # Narva Haigla (371...420)
12
+ '42', # Pärnu Haigla (421...470)
13
+ '47', # Pelgulinna Sünnitusmaja (Tallinn), Haapsalu haigla (471...490)
14
+ '49', # Järvamaa Haigla (Paide) (491...520)
15
+ '52', # Rakvere, Tapa haigla (521...570)
16
+ '57', # Valga Haigla (571...600)
17
+ '60', # Viljandi Haigla (601...650)
18
+ '65', # Lõuna-Eesti Haigla (Võru), Pälva Haigla (651...710?)
19
+ '70', # All other hospitals
20
+ '95' # Foreigners who are born in Estonia
21
+ ]
22
+
23
+ def self.generate(opts = {})
24
+ first_digit = 0
25
+
26
+ sex = opts[:sex] || (rand.round == 0 ? :M : :F)
27
+ year = opts[:year] || rand(Date.today.year - 90..Date.today.year - 1)
28
+ year = rand(Date.today.year - 50..Date.today.year - 19) if opts[:safe_age]
29
+ month = opts[:month] || rand(1..12)
30
+ day = opts[:day] || rand(1..NUM_DAYS[month])
31
+
32
+ first_digit += 1 if (1800..1899).include?(year)
33
+ first_digit += 3 if (1900..1999).include?(year)
34
+ first_digit += 5 if year >= 2000
35
+ first_digit += 1 if sex.upcase.to_sym == :F
36
+
37
+ result = first_digit.to_s
38
+ result += "%02d" % year.to_s[2..3].to_i
39
+ result += "%02d" % month
40
+ result += "%02d" % day
41
+ result += HOSPITALS[(rand * HOSPITALS.size - 1).round]
42
+ result += rand(0..9).to_s
43
+ result += new(result).control_code.to_s
44
+ end
45
+
46
+ def self.valid?(code)
47
+ new(code).valid?
48
+ end
49
+
50
+ def initialize(code)
51
+ @code = code.to_s
52
+ end
53
+
54
+ def valid?
55
+ @code.length == 11 &&
56
+ @code[10].chr.to_i == control_code
57
+ end
58
+
59
+ def birth_date
60
+ return unless valid?
61
+ year = century + @code[1..2].to_i
62
+ month = @code[3..4].to_i
63
+ day = @code[5..6].to_i
64
+ return unless Date.valid_date?(year, month, day)
65
+ Date.new(year, month, day)
66
+ end
67
+
68
+ def age
69
+ return unless valid?
70
+ now = Time.now.utc.to_date
71
+ now.year - (birth_date.year + IdentityCode::age_correction(birth_date))
72
+ end
73
+
74
+ def sex
75
+ return unless valid?
76
+ @code[0].to_i.odd? ? :M : :F
77
+ end
78
+
79
+ def control_code
80
+ scales1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1]
81
+ checknum = scales1.each_with_index.map do |scale, i|
82
+ @code[i].chr.to_i * scale
83
+ end.inject(0, :+) % 11
84
+ return checknum unless checknum == 10
85
+
86
+ scales2 = [3, 4, 5, 6, 7, 8, 9, 1, 2, 3]
87
+ checknum = scales2.each_with_index.map do |scale, i|
88
+ @code[i].chr.to_i * scale
89
+ end.inject(0, :+) % 11
90
+
91
+ checknum == 10 ? 0 : checknum
92
+ end
93
+
94
+ private
95
+
96
+ def century
97
+ case @code[0].chr.to_i
98
+ when 1..2 then 1800
99
+ when 3..4 then 1900
100
+ when 5..6 then 2000
101
+ else
102
+ 2100
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,83 @@
1
+ require 'date'
2
+
3
+ module IdentityCode
4
+ class LV
5
+ def initialize(code)
6
+ @code = code.to_s.gsub('-', '')
7
+ end
8
+
9
+ def self.generate(opts = {})
10
+ year = opts[:year] || rand(Date.today.year - 90..Date.today.year - 1)
11
+ year = rand(Date.today.year - 50..Date.today.year - 19) if opts[:safe_age]
12
+ month = opts[:month] || rand(1..12)
13
+ day = opts[:day] || rand(1..NUM_DAYS[month])
14
+
15
+ century_code = begin
16
+ case year
17
+ when 1800..1899 then 0
18
+ when 1900..1999 then 1
19
+ when 2000..2099 then 2
20
+ else
21
+ 9
22
+ end
23
+ end.to_s
24
+
25
+ result = "%02d" % day
26
+ result += "%02d" % month
27
+ result += "%02d" % year.to_s[2..3].to_i
28
+ result += '-' if opts[:separator]
29
+ result += century_code
30
+ result += "%03d" % rand(0..999).to_s
31
+ result += new(result).control_code.to_s
32
+ end
33
+
34
+ def self.valid?(code)
35
+ new(code).valid?
36
+ end
37
+
38
+ def valid?
39
+ @code.length == 11 &&
40
+ @code[10].chr.to_i == control_code
41
+ end
42
+
43
+ def birth_date
44
+ return unless valid?
45
+ year = century + @code[4..5].to_i
46
+ month = @code[2..3].to_i
47
+ day = @code[0..1].to_i
48
+ return unless Date.valid_date?(year, month, day)
49
+ Date.new(year, month, day)
50
+ end
51
+
52
+ def age
53
+ return unless valid?
54
+ now = Time.now.utc.to_date
55
+ now.year - (birth_date.year + IdentityCode.age_correction(birth_date))
56
+ end
57
+
58
+ def control_code
59
+ array = @code.split('').map(&:to_i)
60
+ multipliers = [1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
61
+ hash = Hash[multipliers.zip(array)]
62
+
63
+ check = 0
64
+ hash.map do |k, v|
65
+ check += k * v
66
+ end
67
+
68
+ ((1 - check) % 11) % 10
69
+ end
70
+
71
+ private
72
+
73
+ def century
74
+ case @code[6].chr.to_i
75
+ when 0 then 1800
76
+ when 1 then 1900
77
+ when 2 then 2000
78
+ else
79
+ 2100
80
+ end
81
+ end
82
+ end
83
+ end
@@ -1,3 +1,3 @@
1
1
  module IdentityCode
2
- VERSION = '0.1.3'
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/identity_code.rb CHANGED
@@ -1,129 +1,50 @@
1
1
  require 'identity_code/version'
2
- require 'date'
2
+ require 'identity_code/ee'
3
+ require 'identity_code/lv'
3
4
 
4
5
  module IdentityCode
5
- class Isikukood
6
- HOSPITALS = [
7
- '00', # Kuressaare Haigla (järjekorranumbrid 001 kuni 020)
8
- '01', # Tartu Ülikooli Naistekliinik, Tartumaa, Tartu (011...019)
9
- '02', # Ida-Tallinna Keskhaigla, Hiiumaa, Keila, Rapla haigla (021...220)
10
- '22', # Ida-Viru Keskhaigla (Kohtla-Järve, endine Jõhvi) (221...270)
11
- '27', # Maarjamõisa Kliinikum (Tartu), Jõgeva Haigla (271...370)
12
- '37', # Narva Haigla (371...420)
13
- '42', # Pärnu Haigla (421...470)
14
- '47', # Pelgulinna Sünnitusmaja (Tallinn), Haapsalu haigla (471...490)
15
- '49', # Järvamaa Haigla (Paide) (491...520)
16
- '52', # Rakvere, Tapa haigla (521...570)
17
- '57', # Valga Haigla (571...600)
18
- '60', # Viljandi Haigla (601...650)
19
- '65', # Lõuna-Eesti Haigla (Võru), Pälva Haigla (651...710?)
20
- '70', # All other hospitals
21
- '95' # Foreigners who are born in Estonia
22
- ]
23
-
24
- NUM_DAYS = {
25
- 1 => 31,
26
- 2 => 28,
27
- 3 => 31,
28
- 4 => 30,
29
- 5 => 31,
30
- 6 => 30,
31
- 7 => 31,
32
- 8 => 31,
33
- 9 => 30,
34
- 10 => 31,
35
- 11 => 30,
36
- 12 => 31
37
- }
38
-
39
- def self.generate(opts = {})
40
- first_digit = 0
41
-
42
- sex = opts[:sex] || (rand.round == 0 ? 'M' : 'F')
43
- year = opts[:year] || rand(Date.today.year - 90..Date.today.year - 1)
44
- year = rand(Date.today.year - 50..Date.today.year - 19) if opts[:safe_age]
45
- month = opts[:month] || rand(1..12)
46
- day = opts[:day] || rand(1..NUM_DAYS[month])
47
-
48
- first_digit += 1 if (1800..1899).include?(year)
49
- first_digit += 3 if (1900..1999).include?(year)
50
- first_digit += 5 if year >= 2000
51
- first_digit += 1 if sex == 'F'
52
-
53
- result = first_digit.to_s
54
- result += "%02d" % year.to_s[2..3].to_i
55
- result += "%02d" % month
56
- result += "%02d" % day
57
- result += HOSPITALS[(rand * HOSPITALS.size - 1).round]
58
- result += rand(0..9).to_s
59
- result += new(result).control_code.to_s
60
- end
61
-
62
- def self.valid?(code)
63
- new(code).valid?
64
- end
65
-
66
- def initialize(code)
67
- @code = code.to_s
68
- end
69
-
70
- def valid?
71
- @code.length == 11 &&
72
- @code[10].chr.to_i == control_code
73
- end
74
-
75
- def birth_date
76
- return unless valid?
77
- year = century + @code[1..2].to_i
78
- month = @code[3..4].to_i
79
- day = @code[5..6].to_i
80
- return unless Date.valid_date?(year, month, day)
81
- Date.new(year, month, day)
82
- end
83
-
84
- def age
85
- return unless valid?
86
- now = Time.now.utc.to_date
87
- now.year - (birth_date.year + age_correction)
88
- end
89
-
90
- def sex
91
- return unless valid?
92
- @code[0].to_i.odd? ? 'M' : 'F'
93
- end
94
-
95
- def control_code
96
- scales1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1]
97
- checknum = scales1.each_with_index.map do |scale, i|
98
- @code[i].chr.to_i * scale
99
- end.inject(0, :+) % 11
100
- return checknum unless checknum == 10
101
-
102
- scales2 = [3, 4, 5, 6, 7, 8, 9, 1, 2, 3]
103
- checknum = scales2.each_with_index.map do |scale, i|
104
- @code[i].chr.to_i * scale
105
- end.inject(0, :+) % 11
6
+ NUM_DAYS = {
7
+ 1 => 31,
8
+ 2 => 28,
9
+ 3 => 31,
10
+ 4 => 30,
11
+ 5 => 31,
12
+ 6 => 30,
13
+ 7 => 31,
14
+ 8 => 31,
15
+ 9 => 30,
16
+ 10 => 31,
17
+ 11 => 30,
18
+ 12 => 31
19
+ }.freeze
20
+
21
+ SUPPORTED_COUNTRY_CODES = %i(ee lv).freeze
22
+
23
+ def self.generate(opts = {})
24
+ country_code = opts.delete(:country)
25
+ raise 'Country param is missing or invalid (ee or lv)' unless begin
26
+ country_code &&
27
+ SUPPORTED_COUNTRY_CODES.include?(country_code.downcase.to_sym)
28
+ end
29
+
30
+ Object.const_get("IdentityCode::#{country_code.upcase}").generate(opts)
31
+ end
106
32
 
107
- checknum == 10 ? 0 : checknum
33
+ def self.valid?(opts = {})
34
+ country_code = opts.delete(:country)
35
+ raise 'Country param is missing or invalid (ee or lv)' unless begin
36
+ country_code &&
37
+ SUPPORTED_COUNTRY_CODES.include?(country_code.downcase.to_sym)
108
38
  end
109
39
 
110
- private
111
-
112
- def age_correction
113
- now = Time.now.utc.to_date
114
- return 0 if now.month > birth_date.month
115
- return 0 if now.month == birth_date.month && now.day >= birth_date.day
116
- 1
117
- end
40
+ code = opts.delete(:code)
41
+ Object.const_get("IdentityCode::#{country_code.upcase}").valid?(code)
42
+ end
118
43
 
119
- def century
120
- case @code[0].chr.to_i
121
- when 1..2 then 1800
122
- when 3..4 then 1900
123
- when 5..6 then 2000
124
- else
125
- 2100
126
- end
127
- end
44
+ def self.age_correction(birth_date)
45
+ now = Time.now.utc.to_date
46
+ return 0 if now.month > birth_date.month
47
+ return 0 if now.month == birth_date.month && now.day >= birth_date.day
48
+ 1
128
49
  end
129
50
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: identitycode
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Artem Pakk
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-11-19 00:00:00.000000000 Z
11
+ date: 2016-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,7 +38,7 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
- description: Ruby gem to generate and validate Estonian identity codes
41
+ description: Ruby gem to generate and validate Estonian and Latvian identity codes
42
42
  email:
43
43
  - apakk@me.com
44
44
  executables: []
@@ -55,6 +55,8 @@ files:
55
55
  - bin/setup
56
56
  - identitycode.gemspec
57
57
  - lib/identity_code.rb
58
+ - lib/identity_code/ee.rb
59
+ - lib/identity_code/lv.rb
58
60
  - lib/identity_code/version.rb
59
61
  homepage: https://github.com/defeed/identitycode
60
62
  licenses:
@@ -76,8 +78,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
76
78
  version: '0'
77
79
  requirements: []
78
80
  rubyforge_project:
79
- rubygems_version: 2.4.8
81
+ rubygems_version: 2.4.5.1
80
82
  signing_key:
81
83
  specification_version: 4
82
- summary: Ruby gem to generate and validate Estonian identity codes
84
+ summary: Ruby gem to generate and validate Estonian and Latvian identity codes
83
85
  test_files: []