luhn 2.0.0 → 3.0.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 +4 -4
- data/README.md +10 -16
- data/lib/luhn/{civic_number.rb → personal_identity_number.rb} +15 -16
- data/lib/luhn/version.rb +3 -1
- data/lib/luhn.rb +6 -7
- data/spec/helper.rb +9 -7
- data/spec/spec_luhn.rb +16 -14
- data/spec/spec_personal_identity_number.rb +71 -0
- metadata +3 -7
- data/lib/luhn/extensions/numeric.rb +0 -11
- data/lib/luhn/extensions/string.rb +0 -10
- data/lib/luhn/extensions.rb +0 -3
- data/spec/spec_civic_number.rb +0 -67
- data/spec/spec_extensions.rb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf4e123f559d73199fd452f9f768f7fbf6cfa224995946e4c73492265868d506
|
4
|
+
data.tar.gz: a9d036b18565b4f9ddda1d1812f300d9c629a7b5f4ae826caaa6663f1ef309f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 155f6543bfcf8effc9d5fea6c6319dd162d2f380409f52cdc95462d6d3b6907bc32296b7c3a8006227f6130e1ef7470713e6934c6894c954c4068cfe5a414e0c
|
7
|
+
data.tar.gz: 2aa60ea0ea0f5463db677b1486fb7e4693615cfc0c304a22f790b5f9062483ede9ad10442b878cff365d783401f4ac8e934b64c6eb9cf908efb67c6d0a0104ce
|
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# Ruby class for handling basic Luhn number generation and verification
|
2
2
|
|
3
|
-
Includes a class to handle Swedish
|
3
|
+
Includes a class to handle Swedish personal identity numbers (Personnummer).
|
4
4
|
|
5
5
|
The interface supports checking validity (length, valid date and satisfies luhn),
|
6
|
-
returning the sex, the control digit, and generating random
|
6
|
+
returning the sex, the control digit, and generating random identity numbers.
|
7
7
|
|
8
8
|
## Install
|
9
9
|
|
@@ -16,25 +16,19 @@ $ gem install luhn
|
|
16
16
|
### Basic Luhn
|
17
17
|
|
18
18
|
```ruby
|
19
|
-
Luhn.valid?(
|
20
|
-
Luhn.control_digit(
|
19
|
+
Luhn.valid?("0465827879483596") # true
|
20
|
+
Luhn.control_digit("046582787948359") # 6
|
21
21
|
Luhn.generate(n) # returns a random number of n length that satisfies luhn
|
22
|
-
|
23
|
-
'0465827879483596'.valid_luhn? # true
|
24
|
-
0465827879483596.valid_luhn? # true
|
25
22
|
```
|
26
23
|
|
27
|
-
### Swedish
|
24
|
+
### Swedish personal identity numbers
|
28
25
|
|
29
26
|
```ruby
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
'391030-3183'.civic_number? # true
|
37
|
-
3910303183.civic_number? # true
|
27
|
+
number = Luhn::PersonalIdentityNumber.new("19391030-3183")
|
28
|
+
number.valid? # true
|
29
|
+
number.sex # "male"
|
30
|
+
number.male? # true
|
31
|
+
number.control_digit # 3
|
38
32
|
```
|
39
33
|
|
40
34
|
## About the Luhn algorithm
|
@@ -1,8 +1,11 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Luhn
|
3
|
-
class
|
4
|
+
class PersonalIdentityNumber
|
4
5
|
attr_reader :value
|
5
6
|
|
7
|
+
BirthDate = Data.define(:year, :month, :day)
|
8
|
+
|
6
9
|
def initialize string
|
7
10
|
self.value = string
|
8
11
|
end
|
@@ -12,7 +15,7 @@ module Luhn
|
|
12
15
|
end
|
13
16
|
|
14
17
|
def valid_date?
|
15
|
-
(1..12).
|
18
|
+
(1..12).cover?(birth_date.month) && (1..31).cover?(birth_date.day)
|
16
19
|
end
|
17
20
|
|
18
21
|
def control_digit
|
@@ -20,19 +23,20 @@ module Luhn
|
|
20
23
|
end
|
21
24
|
|
22
25
|
def sex
|
23
|
-
|
26
|
+
return "unknown" unless valid?
|
27
|
+
(value[8...9].to_i.even? ? "female" : "male")
|
24
28
|
end
|
25
29
|
|
26
30
|
def female?
|
27
|
-
sex ==
|
31
|
+
sex == "female"
|
28
32
|
end
|
29
33
|
|
30
34
|
def male?
|
31
|
-
sex ==
|
35
|
+
sex == "male"
|
32
36
|
end
|
33
37
|
|
34
38
|
def birth_date
|
35
|
-
|
39
|
+
BirthDate.new(
|
36
40
|
value[0...2].to_i,
|
37
41
|
value[2...4].to_i,
|
38
42
|
value[4...6].to_i
|
@@ -49,21 +53,16 @@ module Luhn
|
|
49
53
|
value
|
50
54
|
end
|
51
55
|
|
52
|
-
# For backwards compability
|
53
|
-
def civic_number
|
54
|
-
value
|
55
|
-
end
|
56
|
-
|
57
56
|
def self.generate
|
58
|
-
date = Time.local(Time.now.year - rand(
|
59
|
-
Luhn.generate(10, :
|
57
|
+
date = Time.local(Time.now.year - rand(1..99), rand(1..12), rand(1..31))
|
58
|
+
Luhn.generate(10, prefix: date.strftime("%y%m%d"))
|
60
59
|
end
|
61
60
|
|
62
61
|
private
|
63
62
|
|
64
63
|
def value= string
|
65
|
-
val = string.to_s.gsub(/\D/,
|
66
|
-
@value = val.length == 12 ? val[2...12] : val
|
64
|
+
val = string.to_s.gsub(/\D/, "")
|
65
|
+
@value = ((val.length == 12) ? val[2...12] : val)
|
67
66
|
end
|
68
67
|
end
|
69
68
|
end
|
data/lib/luhn/version.rb
CHANGED
data/lib/luhn.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
#
|
2
|
-
require "luhn/extensions"
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
3
|
module Luhn
|
5
4
|
def self.valid? value
|
@@ -22,10 +21,10 @@ module Luhn
|
|
22
21
|
end
|
23
22
|
|
24
23
|
def self.generate size, options = {}
|
25
|
-
generated = options[:prefix] ||
|
24
|
+
generated = options[:prefix] || ""
|
26
25
|
(size - generated.size - 1).times { |i| generated += rand(10).to_s }
|
27
26
|
|
28
|
-
generated +
|
27
|
+
generated + new(generated).control_digit.to_s
|
29
28
|
end
|
30
29
|
|
31
30
|
def valid?
|
@@ -46,14 +45,14 @@ module Luhn
|
|
46
45
|
def checksum(operation)
|
47
46
|
i = 0
|
48
47
|
compare_method = (operation == :even) ? :== : :>
|
49
|
-
|
48
|
+
number.reverse.chars.inject(0) do |sum, c|
|
50
49
|
n = c.to_i
|
51
50
|
weight = (i % 2).send(compare_method, 0) ? n * 2 : n
|
52
51
|
i += 1
|
53
|
-
sum
|
52
|
+
sum + ((weight < 10) ? weight : (weight - 9))
|
54
53
|
end
|
55
54
|
end
|
56
55
|
end
|
57
56
|
end
|
58
57
|
|
59
|
-
require "luhn/
|
58
|
+
require "luhn/personal_identity_number"
|
data/spec/helper.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
require
|
5
|
-
|
6
|
-
require
|
7
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$:.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
|
4
|
+
require "rubygems"
|
5
|
+
gem "minitest"
|
6
|
+
require "luhn"
|
7
|
+
require "minitest/benchmark" if ENV["BENCH"]
|
8
|
+
require "minitest/spec"
|
9
|
+
require "minitest/autorun"
|
data/spec/spec_luhn.rb
CHANGED
@@ -1,35 +1,37 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "helper"
|
2
4
|
|
3
5
|
describe Luhn do
|
4
6
|
it "identifies if the number is valid" do
|
5
|
-
Luhn.valid?(
|
7
|
+
Luhn.valid?("1111111116").must_equal true
|
6
8
|
end
|
7
9
|
|
8
|
-
it
|
9
|
-
Luhn.valid?(
|
10
|
+
it "identifies if the number is invalid" do
|
11
|
+
Luhn.valid?("1111111111").must_equal false
|
10
12
|
end
|
11
13
|
|
12
|
-
it
|
13
|
-
Luhn.valid?(
|
14
|
+
it "requires numbers" do
|
15
|
+
Luhn.valid?("frefre").must_equal false
|
14
16
|
end
|
15
17
|
|
16
|
-
it
|
17
|
-
luhn_string = Luhn.generate(rand(32)
|
18
|
+
it "generates a number string that satisfies luhn" do
|
19
|
+
luhn_string = Luhn.generate(rand(1..32))
|
18
20
|
Luhn.valid?(luhn_string).must_equal true
|
19
21
|
end
|
20
22
|
|
21
|
-
it
|
23
|
+
it "generate a number string with the size of the argument" do
|
22
24
|
luhn_string = Luhn.generate(5)
|
23
25
|
luhn_string.size.must_equal 5
|
24
26
|
end
|
25
27
|
|
26
|
-
it
|
27
|
-
luhn_string = Luhn.generate(10, :
|
28
|
-
luhn_string.must_match
|
28
|
+
it "generate a a valid luhn with a given prefix" do
|
29
|
+
luhn_string = Luhn.generate(10, prefix: "00001")
|
30
|
+
luhn_string.must_match(/^00001/)
|
29
31
|
Luhn.valid?(luhn_string).must_equal true
|
30
32
|
end
|
31
33
|
|
32
|
-
it
|
33
|
-
Luhn.control_digit(
|
34
|
+
it "calculates the control digit" do
|
35
|
+
Luhn.control_digit("111111111").must_equal 6
|
34
36
|
end
|
35
37
|
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "helper"
|
4
|
+
|
5
|
+
describe Luhn::PersonalIdentityNumber do
|
6
|
+
it "identifies if the personal identity number is valid" do
|
7
|
+
Luhn::PersonalIdentityNumber.new("3910304298").valid?.must_equal true
|
8
|
+
|
9
|
+
Luhn::PersonalIdentityNumber.new("193910304298").valid?.must_equal true
|
10
|
+
end
|
11
|
+
|
12
|
+
it "identifies if the personal identity number is invalid" do
|
13
|
+
Luhn::PersonalIdentityNumber.new("3910304290").valid?.must_equal false
|
14
|
+
end
|
15
|
+
|
16
|
+
it "requires a length of 10 to be valid" do
|
17
|
+
luhn_string = Luhn.generate(8, prefix: "391030")
|
18
|
+
Luhn::PersonalIdentityNumber.new(luhn_string).valid?.must_equal false
|
19
|
+
end
|
20
|
+
|
21
|
+
it "requires the personal identity number to be a valid date" do
|
22
|
+
luhn_string = Luhn.generate(10, prefix: "3999")
|
23
|
+
Luhn::PersonalIdentityNumber.new(luhn_string).valid?.must_equal false
|
24
|
+
end
|
25
|
+
|
26
|
+
it "calculates the control digit for a valid personal identity number" do
|
27
|
+
Luhn::PersonalIdentityNumber.new("3910304298").control_digit.must_equal 8
|
28
|
+
end
|
29
|
+
|
30
|
+
it "calculates the correct control digit for an invalid personal identity number" do
|
31
|
+
Luhn::PersonalIdentityNumber.new("3910304290").control_digit.must_equal 8
|
32
|
+
end
|
33
|
+
|
34
|
+
it "identifies if the personal identity number belongs to a male" do
|
35
|
+
Luhn::PersonalIdentityNumber.new("3910304298").sex.must_equal "male"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "identifies if the personal identity number belongs to a female" do
|
39
|
+
Luhn::PersonalIdentityNumber.new("3910303183").sex.must_equal "female"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "cleans up personal identity number with the full year supplied" do
|
43
|
+
Luhn::PersonalIdentityNumber.new("19391030-3183").to_s.must_equal "3910303183"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "knows the date of birth" do
|
47
|
+
personal_identity_number = Luhn::PersonalIdentityNumber.new("3001018194")
|
48
|
+
personal_identity_number.birth_date.year.must_equal 30
|
49
|
+
personal_identity_number.birth_date.month.must_equal 1
|
50
|
+
personal_identity_number.birth_date.day.must_equal 1
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#formatted" do
|
54
|
+
it "formats the personal identity number" do
|
55
|
+
personal_identity_number = Luhn::PersonalIdentityNumber.new("3001018194")
|
56
|
+
|
57
|
+
personal_identity_number.formatted.must_equal "300101-8194"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "returns the origial if the personal identity number is to short" do
|
61
|
+
personal_identity_number = Luhn::PersonalIdentityNumber.new("300101819")
|
62
|
+
|
63
|
+
personal_identity_number.formatted.must_equal "300101819"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "generates a valid random personal identity number" do
|
68
|
+
personal_identity_number = Luhn::PersonalIdentityNumber.generate
|
69
|
+
Luhn::PersonalIdentityNumber.new(personal_identity_number).valid?.must_equal true
|
70
|
+
end
|
71
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: luhn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel Junström
|
@@ -32,15 +32,11 @@ files:
|
|
32
32
|
- LICENSE
|
33
33
|
- README.md
|
34
34
|
- lib/luhn.rb
|
35
|
-
- lib/luhn/
|
36
|
-
- lib/luhn/extensions.rb
|
37
|
-
- lib/luhn/extensions/numeric.rb
|
38
|
-
- lib/luhn/extensions/string.rb
|
35
|
+
- lib/luhn/personal_identity_number.rb
|
39
36
|
- lib/luhn/version.rb
|
40
37
|
- spec/helper.rb
|
41
|
-
- spec/spec_civic_number.rb
|
42
|
-
- spec/spec_extensions.rb
|
43
38
|
- spec/spec_luhn.rb
|
39
|
+
- spec/spec_personal_identity_number.rb
|
44
40
|
homepage: http://github.com/joeljunstrom/ruby_luhn
|
45
41
|
licenses: []
|
46
42
|
metadata: {}
|
data/lib/luhn/extensions.rb
DELETED
data/spec/spec_civic_number.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
describe Luhn::CivicNumber do
|
4
|
-
it 'identifies if the civic number is valid' do
|
5
|
-
Luhn::CivicNumber.new('3910304298').valid?.must_equal true
|
6
|
-
end
|
7
|
-
|
8
|
-
it 'identifies if the civic number is invalid' do
|
9
|
-
Luhn::CivicNumber.new('3910304290').valid?.must_equal false
|
10
|
-
end
|
11
|
-
|
12
|
-
it 'requires a length of 10 to be valid' do
|
13
|
-
luhn_string = Luhn.generate(8, :prefix => '391030')
|
14
|
-
Luhn::CivicNumber.new(luhn_string).valid?.must_equal false
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'requires the civic number to be a valid date' do
|
18
|
-
luhn_string = Luhn.generate(10, :prefix => '3999')
|
19
|
-
Luhn::CivicNumber.new(luhn_string).valid?.must_equal false
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'calculates the control digit for a valid civic number' do
|
23
|
-
Luhn::CivicNumber.new('3910304298').control_digit.must_equal 8
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'calculates the correct control digit for an invalid civic number' do
|
27
|
-
Luhn::CivicNumber.new('3910304290').control_digit.must_equal 8
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'identifies if the civic number belongs to a male' do
|
31
|
-
Luhn::CivicNumber.new('3910304298').sex.must_equal 'male'
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'identifies if the civic number belongs to a female' do
|
35
|
-
Luhn::CivicNumber.new('3910303183').sex.must_equal 'female'
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'cleans up civic number with the full year supplied' do
|
39
|
-
Luhn::CivicNumber.new('19391030-3183').civic_number.must_equal '3910303183'
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'knows the date of birth' do
|
43
|
-
civic_number = Luhn::CivicNumber.new('3001018194')
|
44
|
-
civic_number.birth_date.year.must_equal 30
|
45
|
-
civic_number.birth_date.month.must_equal 1
|
46
|
-
civic_number.birth_date.day.must_equal 1
|
47
|
-
end
|
48
|
-
|
49
|
-
describe "#formatted" do
|
50
|
-
it "formats the civic number" do
|
51
|
-
civic_number = Luhn::CivicNumber.new('3001018194')
|
52
|
-
|
53
|
-
civic_number.formatted.must_equal "300101-8194"
|
54
|
-
end
|
55
|
-
|
56
|
-
it "returns the origial if the civic number is to short" do
|
57
|
-
civic_number = Luhn::CivicNumber.new('300101819')
|
58
|
-
|
59
|
-
civic_number.formatted.must_equal "300101819"
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
it 'generates a valid random civic number' do
|
64
|
-
civic_number = Luhn::CivicNumber.generate
|
65
|
-
Luhn::CivicNumber.new(civic_number).valid?.must_equal true
|
66
|
-
end
|
67
|
-
end
|
data/spec/spec_extensions.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
describe String do
|
4
|
-
it 'knows if it is a valid luhn' do
|
5
|
-
'3910304298'.valid_luhn?.must_equal true
|
6
|
-
end
|
7
|
-
|
8
|
-
it 'knows if it is an civic number' do
|
9
|
-
'3910304298'.civic_number?.must_equal true
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
describe Numeric do
|
14
|
-
it 'knows if it is a valid luhn' do
|
15
|
-
3910304298.valid_luhn?.must_equal true
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'knows if it is an civic number' do
|
19
|
-
3910304298.civic_number?.must_equal true
|
20
|
-
end
|
21
|
-
end
|