tin_valid 1.0.0 → 1.1.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/CHANGELOG.md +10 -0
- data/README.md +9 -0
- data/lib/tin_valid/austria_tin.rb +1 -0
- data/lib/tin_valid/belgium_tin.rb +11 -15
- data/lib/tin_valid/bulgaria_tin.rb +10 -16
- data/lib/tin_valid/croatia_tin.rb +7 -1
- data/lib/tin_valid/cyprus_tin.rb +5 -2
- data/lib/tin_valid/czechia_tin.rb +24 -23
- data/lib/tin_valid/denmark_tin.rb +10 -8
- data/lib/tin_valid/estonia_tin.rb +7 -8
- data/lib/tin_valid/finland_tin.rb +71 -0
- data/lib/tin_valid/france_tin.rb +28 -0
- data/lib/tin_valid/germany_tin.rb +10 -2
- data/lib/tin_valid/greece_tin.rb +10 -2
- data/lib/tin_valid/helpers.rb +14 -0
- data/lib/tin_valid/hungary_tin.rb +7 -1
- data/lib/tin_valid/ireland_tin.rb +7 -1
- data/lib/tin_valid/italy_tin.rb +3 -12
- data/lib/tin_valid/latvia_tin.rb +6 -2
- data/lib/tin_valid/lithuania_tin.rb +5 -2
- data/lib/tin_valid/luxembourg_tin.rb +7 -8
- data/lib/tin_valid/malta_tin.rb +7 -1
- data/lib/tin_valid/netherlands_tin.rb +8 -1
- data/lib/tin_valid/poland_tin.rb +9 -8
- data/lib/tin_valid/portugal_tin.rb +9 -1
- data/lib/tin_valid/romania_tin.rb +7 -8
- data/lib/tin_valid/slovakia_tin.rb +12 -9
- data/lib/tin_valid/slovenia_tin.rb +7 -1
- data/lib/tin_valid/spain_tin.rb +7 -1
- data/lib/tin_valid/sweden_tin.rb +7 -9
- data/lib/tin_valid/united_kingdom_tin.rb +12 -2
- data/lib/tin_valid/version.rb +1 -1
- data/lib/tin_valid.rb +4 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2a4dc099cefbd5653c35bb0a8d78061e7e9239a917f2f872e7036651c429c014
|
4
|
+
data.tar.gz: c540ebe0de3b7f4c69c65c2d05b0d2d67b1beca905e4ee2e99416b361d4991c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d34baae639710a1f82adc36eedce1bb6b961e7fbe3f2128d091b5c61f6956276dc047207d62ac46325577028e5db562a955a4603056d0096469ce48e7698adbf
|
7
|
+
data.tar.gz: 97e1d3b264372400e0575a30d15087d53bb3220c49e2126a5aa24417407b806e8018e4bf26cef7e7ff8a1d749e74c907801a8b3e2ae52ddae85008394682ba28
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.1.0] - 2025-04-18
|
4
|
+
|
5
|
+
Features:
|
6
|
+
- Add Finland 🇫🇮
|
7
|
+
- Add France 🇫🇷
|
8
|
+
|
9
|
+
Fixes:
|
10
|
+
- Test against clearly invalid codes 00000… and 123456…
|
11
|
+
- Check that all dates are in the past
|
12
|
+
|
3
13
|
## [1.0.0] - 2025-04-17
|
4
14
|
|
5
15
|
Features:
|
data/README.md
CHANGED
@@ -10,6 +10,8 @@ Validate Tax Identification Numbers (TINs) for the following European countries:
|
|
10
10
|
- Czechia 🇨🇿
|
11
11
|
- Denmark 🇩🇰
|
12
12
|
- Estonia 🇪🇪
|
13
|
+
- Finland 🇫🇮
|
14
|
+
- France 🇫🇷
|
13
15
|
- Germany 🇩🇪
|
14
16
|
- Greece 🇬🇷
|
15
17
|
- Hungary 🇭🇺
|
@@ -80,6 +82,13 @@ TinValid::DenmarkTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
|
80
82
|
# Optional birth_date
|
81
83
|
TinValid::EstoniaTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
82
84
|
|
85
|
+
# Finland
|
86
|
+
# Optional birth_date
|
87
|
+
TinValid::FinlandTin.new(tin: "…", birth_date: Date.new(…)).valid?
|
88
|
+
|
89
|
+
# France
|
90
|
+
TinValid::FranceTin.new(tin: "…").valid?
|
91
|
+
|
83
92
|
# Germany
|
84
93
|
TinValid::GermanyTin.new(tin: "…").valid?
|
85
94
|
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
module TinValid
|
4
4
|
class BelgiumTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
5
7
|
def initialize(tin:, birth_date: nil)
|
6
8
|
@tin = tin
|
7
9
|
@birth_date = birth_date
|
@@ -37,6 +39,15 @@ module TinValid
|
|
37
39
|
def check = match[:check].to_i
|
38
40
|
|
39
41
|
def valid_check?(year, month, day, number)
|
42
|
+
# A month (in the range 00...12, 00 is acceptable for person not born in
|
43
|
+
# Belgium and with an uncertain date of birth).
|
44
|
+
month = 1 if month == "00"
|
45
|
+
|
46
|
+
# A day of month (in the range 00...31 depending on month and year, 00 is
|
47
|
+
# acceptable for person not born in Belgium and with an uncertain date of
|
48
|
+
# birth).
|
49
|
+
day = 1 if day == "00"
|
50
|
+
|
40
51
|
tin_date = date(year, month, day)
|
41
52
|
return false if tin_date.nil?
|
42
53
|
return false if birth_date && birth_date != tin_date
|
@@ -54,20 +65,5 @@ module TinValid
|
|
54
65
|
#
|
55
66
|
# 2. 97 - remainder of the previous division is the check number
|
56
67
|
def digit_check(number) = 97 - (number.to_i % 97)
|
57
|
-
|
58
|
-
def date(year, month, day)
|
59
|
-
# A month (in the range 00...12, 00 is acceptable for person not born in
|
60
|
-
# Belgium and with an uncertain date of birth).
|
61
|
-
month = 1 if month == "00"
|
62
|
-
|
63
|
-
# A day of month (in the range 00...31 depending on month and year, 00 is
|
64
|
-
# acceptable for person not born in Belgium and with an uncertain date of
|
65
|
-
# birth).
|
66
|
-
day = 1 if day == "00"
|
67
|
-
|
68
|
-
Date.new(year.to_i, month.to_i, day.to_i)
|
69
|
-
rescue Date::Error
|
70
|
-
nil
|
71
|
-
end
|
72
68
|
end
|
73
69
|
end
|
@@ -1,11 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class BulgariaTin
|
4
|
+
class BulgariaTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
5
7
|
def initialize(tin:, birth_date: nil)
|
6
|
-
|
8
|
+
@tin = tin
|
9
|
+
@birth_date = birth_date
|
7
10
|
end
|
8
11
|
|
12
|
+
attr_reader :tin, :birth_date
|
13
|
+
|
9
14
|
def valid?
|
10
15
|
match = MATCHER.match(tin)
|
11
16
|
return false unless match
|
@@ -37,9 +42,9 @@ module TinValid
|
|
37
42
|
day = day.to_i
|
38
43
|
|
39
44
|
if birth_date.nil?
|
40
|
-
|
41
|
-
|
42
|
-
|
45
|
+
date("18#{year}", month - 20, day) ||
|
46
|
+
date("19#{year}", month, day) ||
|
47
|
+
date("20#{year}", month - 40, day)
|
43
48
|
elsif birth_year < 1900
|
44
49
|
birth_date == date("18#{year}", month - 20, day)
|
45
50
|
elsif birth_year < 2000
|
@@ -53,17 +58,6 @@ module TinValid
|
|
53
58
|
|
54
59
|
def birth_year = birth_date.year
|
55
60
|
|
56
|
-
def past_date?(year, month, day)
|
57
|
-
found_date = date(year, month, day)
|
58
|
-
found_date && found_date < Date.today
|
59
|
-
end
|
60
|
-
|
61
|
-
def date(year, month, day)
|
62
|
-
Date.new(year.to_i, month.to_i, day.to_i)
|
63
|
-
rescue Date::Error
|
64
|
-
nil
|
65
|
-
end
|
66
|
-
|
67
61
|
def check
|
68
62
|
weights = [2, 4, 8, 5, 10, 9, 7, 3, 6]
|
69
63
|
|
data/lib/tin_valid/cyprus_tin.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class CyprusTin
|
4
|
+
class CyprusTin
|
5
5
|
def initialize(tin:, kind: nil)
|
6
|
-
|
6
|
+
@tin = tin
|
7
|
+
@kind = kind
|
7
8
|
end
|
8
9
|
|
10
|
+
attr_reader :tin, :kind
|
11
|
+
|
9
12
|
def valid?
|
10
13
|
matcher.match?(tin) && check == tin[-1]
|
11
14
|
end
|
@@ -1,11 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class CzechiaTin
|
4
|
+
class CzechiaTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
5
7
|
def initialize(tin:, birth_date: nil)
|
6
|
-
|
8
|
+
@tin = tin
|
9
|
+
@birth_date = birth_date
|
7
10
|
end
|
8
11
|
|
12
|
+
attr_reader :tin, :birth_date
|
13
|
+
|
9
14
|
def valid? = valid_v1? || valid_v2?
|
10
15
|
|
11
16
|
private
|
@@ -33,6 +38,7 @@ module TinValid
|
|
33
38
|
def valid_v1?
|
34
39
|
match = MATCHER_V1.match(tin)
|
35
40
|
return false unless match
|
41
|
+
return false if tin == "000000000"
|
36
42
|
return true if birth_date.nil?
|
37
43
|
return false if year_of_birth >= 1954
|
38
44
|
|
@@ -46,11 +52,10 @@ module TinValid
|
|
46
52
|
birth_date == date(year, month, match[:day])
|
47
53
|
end
|
48
54
|
|
49
|
-
# rubocop:disable Metrics/AbcSize
|
50
|
-
# rubocop:disable Metrics/MethodLength
|
51
55
|
def valid_v2?
|
52
56
|
match = MATCHER_V2.match(tin)
|
53
57
|
return false unless match
|
58
|
+
return false if tin == "0000000000"
|
54
59
|
return true if birth_date.nil?
|
55
60
|
return false if year_of_birth < 1954
|
56
61
|
|
@@ -59,30 +64,26 @@ module TinValid
|
|
59
64
|
# 54 - 99 for people born between 1954 and 1999.
|
60
65
|
year = "#{birth_century}#{match[:year]}"
|
61
66
|
|
62
|
-
|
63
|
-
# 21…32 only for men) or month + 50 (in the range 51...62 only for women)
|
64
|
-
# or month + 70 (in the range 71…82 only for women).
|
65
|
-
month = match[:month].to_i
|
66
|
-
if month > 70
|
67
|
-
month -= 70
|
68
|
-
elsif month > 50
|
69
|
-
month -= 50
|
70
|
-
elsif month > 20
|
71
|
-
month -= 20
|
72
|
-
end
|
73
|
-
|
74
|
-
birth_date == date(year, month, match[:day])
|
67
|
+
birth_date == date(year, month_integer(match[:month]), match[:day])
|
75
68
|
end
|
76
|
-
# rubocop:enable Metrics/AbcSize
|
77
|
-
# rubocop:enable Metrics/MethodLength
|
78
69
|
|
79
70
|
def year_of_birth = birth_date&.year
|
80
71
|
def birth_century = birth_date.strftime("%Y")[..1]
|
81
72
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
73
|
+
# Month (in the range 1...12 only for men) or month + 20 (in the range
|
74
|
+
# 21…32 only for men) or month + 50 (in the range 51...62 only for women)
|
75
|
+
# or month + 70 (in the range 71…82 only for women).
|
76
|
+
def month_integer(number)
|
77
|
+
number = number.to_i
|
78
|
+
if number > 70
|
79
|
+
number - 70
|
80
|
+
elsif number > 50
|
81
|
+
number - 50
|
82
|
+
elsif number > 20
|
83
|
+
number - 20
|
84
|
+
else
|
85
|
+
number
|
86
|
+
end
|
86
87
|
end
|
87
88
|
end
|
88
89
|
end
|
@@ -1,14 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class DenmarkTin
|
4
|
+
class DenmarkTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
5
7
|
def initialize(tin:, birth_date: nil)
|
6
|
-
|
8
|
+
@tin = tin
|
9
|
+
@birth_date = birth_date
|
7
10
|
end
|
8
11
|
|
12
|
+
attr_reader :tin, :birth_date
|
13
|
+
|
14
|
+
# rubocop:disable Metrics/AbcSize
|
9
15
|
def valid?
|
10
16
|
match = MATCHER.match(tin)
|
11
17
|
return false unless match
|
18
|
+
return false if tin == "0000000000"
|
12
19
|
|
13
20
|
if birth_date
|
14
21
|
year = "#{birth_century}#{match[:year]}"
|
@@ -19,6 +26,7 @@ module TinValid
|
|
19
26
|
|
20
27
|
match[:check].to_i == checksum
|
21
28
|
end
|
29
|
+
# rubocop:enable Metrics/AbcSize
|
22
30
|
|
23
31
|
private
|
24
32
|
|
@@ -38,12 +46,6 @@ module TinValid
|
|
38
46
|
def birth_century = birth_date.strftime("%Y")[..1]
|
39
47
|
def birth_year = birth_date.year
|
40
48
|
|
41
|
-
def date(year, month, day)
|
42
|
-
Date.new(year.to_i, month.to_i, day.to_i)
|
43
|
-
rescue Date::Error
|
44
|
-
nil
|
45
|
-
end
|
46
|
-
|
47
49
|
def checksum
|
48
50
|
# 1. Multiply the values of each position by the corresponding weight:
|
49
51
|
weights =
|
@@ -1,11 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class EstoniaTin
|
4
|
+
class EstoniaTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
5
7
|
def initialize(tin:, birth_date: nil)
|
6
|
-
|
8
|
+
@tin = tin
|
9
|
+
@birth_date = birth_date
|
7
10
|
end
|
8
11
|
|
12
|
+
attr_reader :tin, :birth_date
|
13
|
+
|
9
14
|
def valid?
|
10
15
|
match = MATCHER.match(tin)
|
11
16
|
return false unless match
|
@@ -36,12 +41,6 @@ module TinValid
|
|
36
41
|
def birth_century = birth_date.strftime("%Y")[..1]
|
37
42
|
def birth_year = birth_date.year
|
38
43
|
|
39
|
-
def date(year, month, day)
|
40
|
-
Date.new(year.to_i, month.to_i, day.to_i)
|
41
|
-
rescue Date::Error
|
42
|
-
nil
|
43
|
-
end
|
44
|
-
|
45
44
|
def checksum
|
46
45
|
# 1. Multiply the values of each position by the corresponding weight:
|
47
46
|
# 2. Add up the results of the above multiplications;
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TinValid
|
4
|
+
class FinlandTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
7
|
+
def initialize(tin:, birth_date: nil)
|
8
|
+
@tin = tin
|
9
|
+
@birth_date = birth_date
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :tin, :birth_date
|
13
|
+
|
14
|
+
def valid?
|
15
|
+
match = MATCHER.match(tin)
|
16
|
+
return false unless match
|
17
|
+
|
18
|
+
tin_date = date(
|
19
|
+
"#{tin_century(match[:century])}#{match[:year]}",
|
20
|
+
match[:month],
|
21
|
+
match[:day],
|
22
|
+
)
|
23
|
+
return false unless tin_date
|
24
|
+
return false if birth_date && birth_date != tin_date
|
25
|
+
|
26
|
+
tin[-1] == check
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
MATCHER = %r{
|
32
|
+
\A
|
33
|
+
(?<day>[0-3][0-9])
|
34
|
+
(?<month>[0-1][0-9])
|
35
|
+
(?<year>[0-9][0-9])
|
36
|
+
(?<century>[-+A-FU-Y])
|
37
|
+
[0-9]{3}
|
38
|
+
[0-9A-Z]
|
39
|
+
\z
|
40
|
+
}x
|
41
|
+
private_constant :MATCHER
|
42
|
+
|
43
|
+
def tin_century(character)
|
44
|
+
case character
|
45
|
+
when "+" then 18
|
46
|
+
when "-", "U", "V", "W", "X", "Y" then 19
|
47
|
+
else 20
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def check
|
52
|
+
# 1. Concatenate C1, C2, C3, C4, C5, C6, C8, C9, C10
|
53
|
+
# (warning: C7 is not part of the check digit);
|
54
|
+
number = "#{tin[0..5]}#{tin[7..9]}".to_i
|
55
|
+
|
56
|
+
# 2. Calculate the modulo 31 of the abovementioned number;
|
57
|
+
remainder = number % 31
|
58
|
+
|
59
|
+
# 4. The result of calculating modulo 31 will give as a result a number,
|
60
|
+
# which will provide the check mark through the following table:
|
61
|
+
case remainder
|
62
|
+
when ..9 then remainder.to_s
|
63
|
+
when ..15 then (remainder + 55).chr
|
64
|
+
when 16 then "H"
|
65
|
+
when ..21 then (remainder + 57).chr
|
66
|
+
when 21 then "P"
|
67
|
+
else (remainder + 59).chr
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TinValid
|
4
|
+
class FranceTin
|
5
|
+
def initialize(tin:)
|
6
|
+
@tin = tin
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :tin
|
10
|
+
|
11
|
+
def valid?
|
12
|
+
return false unless /\A[0-3][0-9]{12}\z/.match?(tin)
|
13
|
+
return false if tin == "0000000000000"
|
14
|
+
|
15
|
+
tin[-3..].to_i == check
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def check
|
21
|
+
# 1. Concatenate C1, C2, C3, C4, C5, C6, C7, C8, C9, C10;
|
22
|
+
# 2. Get modulo 511 of the result of the previous result;
|
23
|
+
# 3. Check digit = remainder if remainder < 100, C11 = 0
|
24
|
+
# (if remainder < 10, C11 = 0 and C12 = 0).
|
25
|
+
tin[..-4].to_i % 511
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,7 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class GermanyTin
|
4
|
+
class GermanyTin
|
5
|
+
def initialize(tin:)
|
6
|
+
@tin = tin
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :tin
|
10
|
+
|
5
11
|
def valid?
|
6
12
|
valid_v1? || valid_v2?
|
7
13
|
end
|
@@ -12,7 +18,9 @@ module TinValid
|
|
12
18
|
# 1. 13 characters
|
13
19
|
# 2. Only digits
|
14
20
|
# 3. C5 is a 0
|
15
|
-
/\A[0-9]{4}0[0-9]{8}\z/.match?(tin)
|
21
|
+
return false unless /\A[0-9]{4}0[0-9]{8}\z/.match?(tin)
|
22
|
+
|
23
|
+
tin.to_i != 0
|
16
24
|
end
|
17
25
|
|
18
26
|
# rubocop:disable Metrics/AbcSize
|
data/lib/tin_valid/greece_tin.rb
CHANGED
@@ -1,9 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class GreeceTin
|
4
|
+
class GreeceTin
|
5
|
+
def initialize(tin:)
|
6
|
+
@tin = tin
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :tin
|
10
|
+
|
5
11
|
def valid?
|
6
|
-
/\A[0-9]{9}\z/.match?(tin)
|
12
|
+
return false unless /\A[0-9]{9}\z/.match?(tin)
|
13
|
+
|
14
|
+
tin != "000000000" && tin != "123456789"
|
7
15
|
end
|
8
16
|
end
|
9
17
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TinValid
|
4
|
+
module Helpers
|
5
|
+
private
|
6
|
+
|
7
|
+
def date(year, month, day)
|
8
|
+
found_date = Date.new(year.to_i, month.to_i, day.to_i)
|
9
|
+
found_date if found_date < Date.today
|
10
|
+
rescue Date::Error
|
11
|
+
nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -1,7 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class IrelandTin
|
4
|
+
class IrelandTin
|
5
|
+
def initialize(tin:)
|
6
|
+
@tin = tin
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :tin
|
10
|
+
|
5
11
|
def valid?
|
6
12
|
/\A[0-9]{7}[A-W][A-IW]?\z/.match?(tin) &&
|
7
13
|
tin.chars[7] == check
|
data/lib/tin_valid/italy_tin.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
module TinValid
|
4
4
|
# rubocop:disable Metrics/ClassLength
|
5
5
|
class ItalyTin
|
6
|
+
include TinValid::Helpers
|
7
|
+
|
6
8
|
def initialize(tin:, birth_date: nil)
|
7
9
|
@tin = tin
|
8
10
|
@birth_date = birth_date
|
@@ -35,7 +37,7 @@ module TinValid
|
|
35
37
|
if birth_date
|
36
38
|
birth_date == date("#{birth_century}#{year}", month, day)
|
37
39
|
else
|
38
|
-
date
|
40
|
+
date("19#{year}", month, day) || date("20#{year}", month, day)
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
@@ -60,17 +62,6 @@ module TinValid
|
|
60
62
|
string.chars.map { NUMERICAL_REPLACEMENTS.fetch(_1, _1) }.join.to_i
|
61
63
|
end
|
62
64
|
|
63
|
-
def date?(year, month, day)
|
64
|
-
found_date = date(year, month, day)
|
65
|
-
found_date && found_date < Date.today
|
66
|
-
end
|
67
|
-
|
68
|
-
def date(year, month, day)
|
69
|
-
Date.new(year.to_i, month.to_i, day.to_i)
|
70
|
-
rescue Date::Error
|
71
|
-
nil
|
72
|
-
end
|
73
|
-
|
74
65
|
MATCHER = %r{
|
75
66
|
\A
|
76
67
|
[A-Z]{6}
|
data/lib/tin_valid/latvia_tin.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class LatviaTin
|
4
|
+
class LatviaTin
|
5
5
|
def initialize(tin:, birth_date: nil)
|
6
|
-
|
6
|
+
@tin = tin
|
7
|
+
@birth_date = birth_date
|
7
8
|
end
|
8
9
|
|
10
|
+
attr_reader :tin, :birth_date
|
11
|
+
|
9
12
|
def valid? = valid_v1? || valid_v2?
|
10
13
|
|
11
14
|
private
|
@@ -35,6 +38,7 @@ module TinValid
|
|
35
38
|
def valid_v1?
|
36
39
|
match = MATCHER_V1.match(tin)
|
37
40
|
return false unless match
|
41
|
+
return false if tin == "00000000000"
|
38
42
|
|
39
43
|
if birth_date
|
40
44
|
tin[..5] == birth_date.strftime("%d%m%y") &&
|
@@ -1,11 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class LithuaniaTin
|
4
|
+
class LithuaniaTin
|
5
5
|
def initialize(tin:, birth_date: nil)
|
6
|
-
|
6
|
+
@tin = tin
|
7
|
+
@birth_date = birth_date
|
7
8
|
end
|
8
9
|
|
10
|
+
attr_reader :tin, :birth_date
|
11
|
+
|
9
12
|
def valid?
|
10
13
|
matcher = MATCHER.match(tin)
|
11
14
|
return false unless matcher
|
@@ -1,11 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class LuxembourgTin
|
4
|
+
class LuxembourgTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
5
7
|
def initialize(tin:, birth_date: nil)
|
6
|
-
|
8
|
+
@tin = tin
|
9
|
+
@birth_date = birth_date
|
7
10
|
end
|
8
11
|
|
12
|
+
attr_reader :tin, :birth_date
|
13
|
+
|
9
14
|
def valid?
|
10
15
|
match = MATCHER.match(tin)
|
11
16
|
return false unless match
|
@@ -69,12 +74,6 @@ module TinValid
|
|
69
74
|
checksum == 0
|
70
75
|
end
|
71
76
|
|
72
|
-
def date(year, month, day)
|
73
|
-
Date.new(year.to_i, month.to_i, day.to_i)
|
74
|
-
rescue Date::Error
|
75
|
-
nil
|
76
|
-
end
|
77
|
-
|
78
77
|
def table_d(number_i, number_j) = TABLE_D.dig(number_i, number_j)
|
79
78
|
def table_p(number_m, number_n) = TABLE_P.dig(number_m, number_n)
|
80
79
|
|
data/lib/tin_valid/malta_tin.rb
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class NetherlandsTin
|
4
|
+
class NetherlandsTin
|
5
|
+
def initialize(tin:)
|
6
|
+
@tin = tin
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :tin
|
10
|
+
|
5
11
|
def valid?
|
6
12
|
return false unless /\A[0-9]{9}\z/.match?(tin)
|
13
|
+
return false if tin == "000000000"
|
7
14
|
|
8
15
|
tin[-1].to_i == check
|
9
16
|
end
|
data/lib/tin_valid/poland_tin.rb
CHANGED
@@ -1,11 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class PolandTin
|
4
|
+
class PolandTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
5
7
|
def initialize(tin:, birth_date: nil)
|
6
|
-
|
8
|
+
@tin = tin
|
9
|
+
@birth_date = birth_date
|
7
10
|
end
|
8
11
|
|
12
|
+
attr_reader :tin, :birth_date
|
13
|
+
|
9
14
|
def valid? = valid_v1? || valid_v2?
|
10
15
|
|
11
16
|
private
|
@@ -25,6 +30,7 @@ module TinValid
|
|
25
30
|
|
26
31
|
def valid_v1?
|
27
32
|
return false unless MATCHER_V1.match?(tin)
|
33
|
+
return false if tin == "0000000000"
|
28
34
|
|
29
35
|
tin[-1].to_i == check
|
30
36
|
end
|
@@ -32,6 +38,7 @@ module TinValid
|
|
32
38
|
def valid_v2?
|
33
39
|
match = MATCHER_V2.match(tin)
|
34
40
|
return false unless match
|
41
|
+
return false if tin == "00000000000"
|
35
42
|
return true unless birth_date
|
36
43
|
|
37
44
|
tin_date = date(
|
@@ -68,11 +75,5 @@ module TinValid
|
|
68
75
|
else 0
|
69
76
|
end
|
70
77
|
end
|
71
|
-
|
72
|
-
def date(year, month, day)
|
73
|
-
Date.new(year.to_i, month.to_i, day.to_i)
|
74
|
-
rescue Date::Error
|
75
|
-
nil
|
76
|
-
end
|
77
78
|
end
|
78
79
|
end
|
@@ -1,9 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class PortugalTin
|
4
|
+
class PortugalTin
|
5
|
+
def initialize(tin:)
|
6
|
+
@tin = tin
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :tin
|
10
|
+
|
5
11
|
def valid?
|
6
12
|
return false unless /\A[0-9]{9}\z/.match?(tin)
|
13
|
+
return false if tin == "000000000"
|
14
|
+
return false if tin == "123456789"
|
7
15
|
|
8
16
|
tin[-1].to_i == check
|
9
17
|
end
|
@@ -1,11 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class RomaniaTin
|
4
|
+
class RomaniaTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
5
7
|
def initialize(tin:, birth_date: nil)
|
6
|
-
|
8
|
+
@tin = tin
|
9
|
+
@birth_date = birth_date
|
7
10
|
end
|
8
11
|
|
12
|
+
attr_reader :tin, :birth_date
|
13
|
+
|
9
14
|
def valid? = valid_v1? || valid_v2?
|
10
15
|
|
11
16
|
private
|
@@ -74,11 +79,5 @@ module TinValid
|
|
74
79
|
when 5..6 then 20
|
75
80
|
end
|
76
81
|
end
|
77
|
-
|
78
|
-
def date(year, month, day)
|
79
|
-
Date.new(year.to_i, month.to_i, day.to_i)
|
80
|
-
rescue Date::Error
|
81
|
-
nil
|
82
|
-
end
|
83
82
|
end
|
84
83
|
end
|
@@ -1,12 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class SlovakiaTin
|
4
|
+
class SlovakiaTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
5
7
|
def initialize(tin:, birth_date: nil)
|
6
|
-
|
8
|
+
@tin = tin
|
9
|
+
@birth_date = birth_date
|
7
10
|
end
|
8
11
|
|
9
|
-
|
12
|
+
attr_reader :tin, :birth_date
|
13
|
+
|
14
|
+
def valid?
|
15
|
+
return false if %w[0000000000 000000000 1234567890].include?(tin)
|
16
|
+
|
17
|
+
valid_v2? || valid_v1?
|
18
|
+
end
|
10
19
|
|
11
20
|
def normalized = tin.tr("/", "")
|
12
21
|
|
@@ -54,11 +63,5 @@ module TinValid
|
|
54
63
|
def valid_v2? = MATCHER_V2.match?(tin)
|
55
64
|
|
56
65
|
def birth_century = birth_date.year.to_s[..1]
|
57
|
-
|
58
|
-
def date(year, month, day)
|
59
|
-
Date.new(year.to_i, month.to_i, day.to_i)
|
60
|
-
rescue Date::Error
|
61
|
-
nil
|
62
|
-
end
|
63
66
|
end
|
64
67
|
end
|
data/lib/tin_valid/spain_tin.rb
CHANGED
data/lib/tin_valid/sweden_tin.rb
CHANGED
@@ -1,11 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class SwedenTin
|
4
|
+
class SwedenTin
|
5
|
+
include TinValid::Helpers
|
6
|
+
|
5
7
|
def initialize(tin:, birth_date: nil)
|
6
|
-
|
8
|
+
@tin = tin
|
9
|
+
@birth_date = birth_date
|
7
10
|
end
|
8
11
|
|
12
|
+
attr_reader :tin, :birth_date
|
13
|
+
|
9
14
|
def valid?
|
10
15
|
VERSIONS.any? do |matcher|
|
11
16
|
match = matcher.match(tin)
|
@@ -106,12 +111,5 @@ module TinValid
|
|
106
111
|
date("20#{year}", month, day)
|
107
112
|
end
|
108
113
|
end
|
109
|
-
|
110
|
-
def date(year, month, day)
|
111
|
-
found_date = Date.new(year.to_i, month.to_i, day.to_i)
|
112
|
-
found_date if found_date < Date.today
|
113
|
-
rescue Date::Error
|
114
|
-
nil
|
115
|
-
end
|
116
114
|
end
|
117
115
|
end
|
@@ -1,14 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module TinValid
|
4
|
-
class UnitedKingdomTin
|
4
|
+
class UnitedKingdomTin
|
5
|
+
def initialize(tin:)
|
6
|
+
@tin = tin
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :tin
|
10
|
+
|
5
11
|
def valid?
|
6
12
|
valid_v1? || valid_v2?
|
7
13
|
end
|
8
14
|
|
9
15
|
private
|
10
16
|
|
11
|
-
def valid_v1?
|
17
|
+
def valid_v1?
|
18
|
+
return false if %w[1234567890 0000000000].include?(tin)
|
19
|
+
|
20
|
+
/\A[0-9]{10}\z/.match?(tin)
|
21
|
+
end
|
12
22
|
|
13
23
|
def valid_v2?
|
14
24
|
return false unless /\A[A-Z]{2}[0-9]{6}[A-D]?\z/.match?(tin)
|
data/lib/tin_valid/version.rb
CHANGED
data/lib/tin_valid.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "date"
|
4
4
|
require_relative "tin_valid/version"
|
5
|
+
require_relative "tin_valid/helpers"
|
5
6
|
require_relative "tin_valid/austria_tin"
|
6
7
|
require_relative "tin_valid/belgium_tin"
|
7
8
|
require_relative "tin_valid/bulgaria_tin"
|
@@ -10,6 +11,8 @@ require_relative "tin_valid/cyprus_tin"
|
|
10
11
|
require_relative "tin_valid/czechia_tin"
|
11
12
|
require_relative "tin_valid/denmark_tin"
|
12
13
|
require_relative "tin_valid/estonia_tin"
|
14
|
+
require_relative "tin_valid/finland_tin"
|
15
|
+
require_relative "tin_valid/france_tin"
|
13
16
|
require_relative "tin_valid/germany_tin"
|
14
17
|
require_relative "tin_valid/greece_tin"
|
15
18
|
require_relative "tin_valid/hungary_tin"
|
@@ -26,7 +29,7 @@ require_relative "tin_valid/romania_tin"
|
|
26
29
|
require_relative "tin_valid/slovakia_tin"
|
27
30
|
require_relative "tin_valid/slovenia_tin"
|
28
31
|
require_relative "tin_valid/spain_tin"
|
29
|
-
require_relative "tin_valid/united_kingdom_tin"
|
30
32
|
require_relative "tin_valid/sweden_tin"
|
33
|
+
require_relative "tin_valid/united_kingdom_tin"
|
31
34
|
|
32
35
|
module TinValid; end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tin_valid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sunny Ripert
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-04-
|
10
|
+
date: 2025-04-18 00:00:00.000000000 Z
|
11
11
|
dependencies: []
|
12
12
|
email:
|
13
13
|
- sunny@sunfox.org
|
@@ -31,8 +31,11 @@ files:
|
|
31
31
|
- lib/tin_valid/czechia_tin.rb
|
32
32
|
- lib/tin_valid/denmark_tin.rb
|
33
33
|
- lib/tin_valid/estonia_tin.rb
|
34
|
+
- lib/tin_valid/finland_tin.rb
|
35
|
+
- lib/tin_valid/france_tin.rb
|
34
36
|
- lib/tin_valid/germany_tin.rb
|
35
37
|
- lib/tin_valid/greece_tin.rb
|
38
|
+
- lib/tin_valid/helpers.rb
|
36
39
|
- lib/tin_valid/hungary_tin.rb
|
37
40
|
- lib/tin_valid/ireland_tin.rb
|
38
41
|
- lib/tin_valid/italy_tin.rb
|