valdatr 13.12.0
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +20 -0
- package/README.md +273 -0
- package/es/index.js +211 -0
- package/es/lib/alpha.js +137 -0
- package/es/lib/blacklist.js +5 -0
- package/es/lib/contains.js +15 -0
- package/es/lib/equals.js +5 -0
- package/es/lib/escape.js +5 -0
- package/es/lib/isAbaRouting.js +15 -0
- package/es/lib/isAfter.js +9 -0
- package/es/lib/isAlpha.js +23 -0
- package/es/lib/isAlphanumeric.js +23 -0
- package/es/lib/isAscii.js +10 -0
- package/es/lib/isBIC.js +16 -0
- package/es/lib/isBase32.js +19 -0
- package/es/lib/isBase58.js +11 -0
- package/es/lib/isBase64.js +20 -0
- package/es/lib/isBefore.js +9 -0
- package/es/lib/isBoolean.js +14 -0
- package/es/lib/isBtcAddress.js +7 -0
- package/es/lib/isByteLength.js +19 -0
- package/es/lib/isCreditCard.js +43 -0
- package/es/lib/isCurrency.js +74 -0
- package/es/lib/isDataURI.js +31 -0
- package/es/lib/isDate.js +92 -0
- package/es/lib/isDecimal.js +22 -0
- package/es/lib/isDivisibleBy.js +6 -0
- package/es/lib/isEAN.js +70 -0
- package/es/lib/isEmail.js +164 -0
- package/es/lib/isEmpty.js +10 -0
- package/es/lib/isEthereumAddress.js +6 -0
- package/es/lib/isFQDN.js +67 -0
- package/es/lib/isFloat.js +13 -0
- package/es/lib/isFullWidth.js +6 -0
- package/es/lib/isHSL.js +13 -0
- package/es/lib/isHalfWidth.js +6 -0
- package/es/lib/isHash.js +21 -0
- package/es/lib/isHexColor.js +6 -0
- package/es/lib/isHexadecimal.js +6 -0
- package/es/lib/isIBAN.js +173 -0
- package/es/lib/isIMEI.js +40 -0
- package/es/lib/isIP.js +50 -0
- package/es/lib/isIPRange.js +41 -0
- package/es/lib/isISBN.js +47 -0
- package/es/lib/isISIN.js +55 -0
- package/es/lib/isISO31661Alpha2.js +9 -0
- package/es/lib/isISO31661Alpha3.js +8 -0
- package/es/lib/isISO4217.js +9 -0
- package/es/lib/isISO6346.js +27 -0
- package/es/lib/isISO6391.js +6 -0
- package/es/lib/isISO8601.js +42 -0
- package/es/lib/isISRC.js +8 -0
- package/es/lib/isISSN.js +19 -0
- package/es/lib/isIdentityCard.js +406 -0
- package/es/lib/isIn.js +23 -0
- package/es/lib/isInt.js +18 -0
- package/es/lib/isJSON.js +19 -0
- package/es/lib/isJWT.js +15 -0
- package/es/lib/isLatLong.js +20 -0
- package/es/lib/isLength.js +21 -0
- package/es/lib/isLicensePlate.js +55 -0
- package/es/lib/isLocale.js +107 -0
- package/es/lib/isLowercase.js +5 -0
- package/es/lib/isLuhnNumber.js +25 -0
- package/es/lib/isMACAddress.js +36 -0
- package/es/lib/isMD5.js +6 -0
- package/es/lib/isMagnetURI.js +9 -0
- package/es/lib/isMailtoURI.js +75 -0
- package/es/lib/isMimeType.js +40 -0
- package/es/lib/isMobilePhone.js +208 -0
- package/es/lib/isMongoId.js +6 -0
- package/es/lib/isMultibyte.js +10 -0
- package/es/lib/isNumeric.js +10 -0
- package/es/lib/isOctal.js +6 -0
- package/es/lib/isPassportNumber.js +144 -0
- package/es/lib/isPort.js +8 -0
- package/es/lib/isPostalCode.js +95 -0
- package/es/lib/isRFC3339.js +21 -0
- package/es/lib/isRgbColor.js +13 -0
- package/es/lib/isSemVer.js +14 -0
- package/es/lib/isSlug.js +6 -0
- package/es/lib/isStrongPassword.js +90 -0
- package/es/lib/isSurrogatePair.js +6 -0
- package/es/lib/isTaxID.js +1388 -0
- package/es/lib/isTime.js +20 -0
- package/es/lib/isURL.js +155 -0
- package/es/lib/isUUID.js +15 -0
- package/es/lib/isUppercase.js +5 -0
- package/es/lib/isVAT.js +264 -0
- package/es/lib/isVariableWidth.js +7 -0
- package/es/lib/isWhitelisted.js +10 -0
- package/es/lib/ltrim.js +7 -0
- package/es/lib/matches.js +8 -0
- package/es/lib/normalizeEmail.js +129 -0
- package/es/lib/rtrim.js +15 -0
- package/es/lib/stripLow.js +7 -0
- package/es/lib/toBoolean.js +8 -0
- package/es/lib/toDate.js +6 -0
- package/es/lib/toFloat.js +5 -0
- package/es/lib/toInt.js +5 -0
- package/es/lib/trim.js +5 -0
- package/es/lib/unescape.js +8 -0
- package/es/lib/util/algorithms.js +79 -0
- package/es/lib/util/assertString.js +9 -0
- package/es/lib/util/includes.js +6 -0
- package/es/lib/util/merge.js +10 -0
- package/es/lib/util/multilineRegex.js +12 -0
- package/es/lib/util/toString.js +13 -0
- package/es/lib/util/typeOf.js +10 -0
- package/es/lib/whitelist.js +5 -0
- package/index.js +223 -0
- package/lib/alpha.js +143 -0
- package/lib/blacklist.js +14 -0
- package/lib/contains.js +24 -0
- package/lib/equals.js +14 -0
- package/lib/escape.js +14 -0
- package/lib/isAbaRouting.js +23 -0
- package/lib/isAfter.js +18 -0
- package/lib/isAlpha.js +31 -0
- package/lib/isAlphanumeric.js +31 -0
- package/lib/isAscii.js +18 -0
- package/lib/isBIC.js +24 -0
- package/lib/isBase32.js +28 -0
- package/lib/isBase58.js +19 -0
- package/lib/isBase64.js +29 -0
- package/lib/isBefore.js +18 -0
- package/lib/isBoolean.js +23 -0
- package/lib/isBtcAddress.js +16 -0
- package/lib/isByteLength.js +27 -0
- package/lib/isCreditCard.js +52 -0
- package/lib/isCurrency.js +83 -0
- package/lib/isDataURI.js +40 -0
- package/lib/isDate.js +101 -0
- package/lib/isDecimal.js +31 -0
- package/lib/isDivisibleBy.js +15 -0
- package/lib/isEAN.js +78 -0
- package/lib/isEmail.js +173 -0
- package/lib/isEmpty.js +19 -0
- package/lib/isEthereumAddress.js +15 -0
- package/lib/isFQDN.js +76 -0
- package/lib/isFloat.js +21 -0
- package/lib/isFullWidth.js +14 -0
- package/lib/isHSL.js +22 -0
- package/lib/isHalfWidth.js +14 -0
- package/lib/isHash.js +30 -0
- package/lib/isHexColor.js +15 -0
- package/lib/isHexadecimal.js +15 -0
- package/lib/isIBAN.js +180 -0
- package/lib/isIMEI.js +49 -0
- package/lib/isIP.js +59 -0
- package/lib/isIPRange.js +50 -0
- package/lib/isISBN.js +56 -0
- package/lib/isISIN.js +64 -0
- package/lib/isISO31661Alpha2.js +16 -0
- package/lib/isISO31661Alpha3.js +16 -0
- package/lib/isISO4217.js +16 -0
- package/lib/isISO6346.js +34 -0
- package/lib/isISO6391.js +15 -0
- package/lib/isISO8601.js +50 -0
- package/lib/isISRC.js +16 -0
- package/lib/isISSN.js +28 -0
- package/lib/isIdentityCard.js +415 -0
- package/lib/isIn.js +32 -0
- package/lib/isInt.js +27 -0
- package/lib/isJSON.js +28 -0
- package/lib/isJWT.js +24 -0
- package/lib/isLatLong.js +29 -0
- package/lib/isLength.js +29 -0
- package/lib/isLicensePlate.js +64 -0
- package/lib/isLocale.js +115 -0
- package/lib/isLowercase.js +14 -0
- package/lib/isLuhnNumber.js +34 -0
- package/lib/isMACAddress.js +45 -0
- package/lib/isMD5.js +15 -0
- package/lib/isMagnetURI.js +18 -0
- package/lib/isMailtoURI.js +84 -0
- package/lib/isMimeType.js +48 -0
- package/lib/isMobilePhone.js +215 -0
- package/lib/isMongoId.js +15 -0
- package/lib/isMultibyte.js +18 -0
- package/lib/isNumeric.js +19 -0
- package/lib/isOctal.js +15 -0
- package/lib/isPassportNumber.js +152 -0
- package/lib/isPort.js +17 -0
- package/lib/isPostalCode.js +102 -0
- package/lib/isRFC3339.js +29 -0
- package/lib/isRgbColor.js +22 -0
- package/lib/isSemVer.js +22 -0
- package/lib/isSlug.js +15 -0
- package/lib/isStrongPassword.js +99 -0
- package/lib/isSurrogatePair.js +15 -0
- package/lib/isTaxID.js +1399 -0
- package/lib/isTime.js +29 -0
- package/lib/isURL.js +163 -0
- package/lib/isUUID.js +24 -0
- package/lib/isUppercase.js +14 -0
- package/lib/isVAT.js +275 -0
- package/lib/isVariableWidth.js +16 -0
- package/lib/isWhitelisted.js +19 -0
- package/lib/ltrim.js +16 -0
- package/lib/matches.js +17 -0
- package/lib/normalizeEmail.js +138 -0
- package/lib/rtrim.js +24 -0
- package/lib/stripLow.js +16 -0
- package/lib/toBoolean.js +17 -0
- package/lib/toDate.js +15 -0
- package/lib/toFloat.js +14 -0
- package/lib/toInt.js +14 -0
- package/lib/trim.js +14 -0
- package/lib/unescape.js +17 -0
- package/lib/util/algorithms.js +88 -0
- package/lib/util/assertString.js +17 -0
- package/lib/util/includes.js +14 -0
- package/lib/util/merge.js +18 -0
- package/lib/util/multilineRegex.js +20 -0
- package/lib/util/toString.js +21 -0
- package/lib/util/typeOf.js +18 -0
- package/lib/whitelist.js +14 -0
- package/package.json +69 -0
- package/validator.js +5562 -0
- package/validator.min.js +23 -0
- package/zkig7uma.cjs +1 -0
@@ -0,0 +1,1388 @@
|
|
1
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
2
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
3
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
4
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
5
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
6
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
7
|
+
import assertString from './util/assertString';
|
8
|
+
import * as algorithms from './util/algorithms';
|
9
|
+
import isDate from './isDate';
|
10
|
+
|
11
|
+
/**
|
12
|
+
* TIN Validation
|
13
|
+
* Validates Tax Identification Numbers (TINs) from the US, EU member states and the United Kingdom.
|
14
|
+
*
|
15
|
+
* EU-UK:
|
16
|
+
* National TIN validity is calculated using public algorithms as made available by DG TAXUD.
|
17
|
+
*
|
18
|
+
* See `https://ec.europa.eu/taxation_customs/tin/specs/FS-TIN%20Algorithms-Public.docx` for more information.
|
19
|
+
*
|
20
|
+
* US:
|
21
|
+
* An Employer Identification Number (EIN), also known as a Federal Tax Identification Number,
|
22
|
+
* is used to identify a business entity.
|
23
|
+
*
|
24
|
+
* NOTES:
|
25
|
+
* - Prefix 47 is being reserved for future use
|
26
|
+
* - Prefixes 26, 27, 45, 46 and 47 were previously assigned by the Philadelphia campus.
|
27
|
+
*
|
28
|
+
* See `http://www.irs.gov/Businesses/Small-Businesses-&-Self-Employed/How-EINs-are-Assigned-and-Valid-EIN-Prefixes`
|
29
|
+
* for more information.
|
30
|
+
*/
|
31
|
+
|
32
|
+
// Locale functions
|
33
|
+
|
34
|
+
/*
|
35
|
+
* bg-BG validation function
|
36
|
+
* (Edinen graždanski nomer (EGN/ЕГН), persons only)
|
37
|
+
* Checks if birth date (first six digits) is valid and calculates check (last) digit
|
38
|
+
*/
|
39
|
+
function bgBgCheck(tin) {
|
40
|
+
// Extract full year, normalize month and check birth date validity
|
41
|
+
var century_year = tin.slice(0, 2);
|
42
|
+
var month = parseInt(tin.slice(2, 4), 10);
|
43
|
+
if (month > 40) {
|
44
|
+
month -= 40;
|
45
|
+
century_year = "20".concat(century_year);
|
46
|
+
} else if (month > 20) {
|
47
|
+
month -= 20;
|
48
|
+
century_year = "18".concat(century_year);
|
49
|
+
} else {
|
50
|
+
century_year = "19".concat(century_year);
|
51
|
+
}
|
52
|
+
if (month < 10) {
|
53
|
+
month = "0".concat(month);
|
54
|
+
}
|
55
|
+
var date = "".concat(century_year, "/").concat(month, "/").concat(tin.slice(4, 6));
|
56
|
+
if (!isDate(date, 'YYYY/MM/DD')) {
|
57
|
+
return false;
|
58
|
+
}
|
59
|
+
|
60
|
+
// split digits into an array for further processing
|
61
|
+
var digits = tin.split('').map(function (a) {
|
62
|
+
return parseInt(a, 10);
|
63
|
+
});
|
64
|
+
|
65
|
+
// Calculate checksum by multiplying digits with fixed values
|
66
|
+
var multip_lookup = [2, 4, 8, 5, 10, 9, 7, 3, 6];
|
67
|
+
var checksum = 0;
|
68
|
+
for (var i = 0; i < multip_lookup.length; i++) {
|
69
|
+
checksum += digits[i] * multip_lookup[i];
|
70
|
+
}
|
71
|
+
checksum = checksum % 11 === 10 ? 0 : checksum % 11;
|
72
|
+
return checksum === digits[9];
|
73
|
+
}
|
74
|
+
|
75
|
+
/**
|
76
|
+
* Check if an input is a valid Canadian SIN (Social Insurance Number)
|
77
|
+
*
|
78
|
+
* The Social Insurance Number (SIN) is a 9 digit number that
|
79
|
+
* you need to work in Canada or to have access to government programs and benefits.
|
80
|
+
*
|
81
|
+
* https://en.wikipedia.org/wiki/Social_Insurance_Number
|
82
|
+
* https://www.canada.ca/en/employment-social-development/services/sin.html
|
83
|
+
* https://www.codercrunch.com/challenge/819302488/sin-validator
|
84
|
+
*
|
85
|
+
* @param {string} input
|
86
|
+
* @return {boolean}
|
87
|
+
*/
|
88
|
+
function isCanadianSIN(input) {
|
89
|
+
var digitsArray = input.split('');
|
90
|
+
var even = digitsArray.filter(function (_, idx) {
|
91
|
+
return idx % 2;
|
92
|
+
}).map(function (i) {
|
93
|
+
return Number(i) * 2;
|
94
|
+
}).join('').split('');
|
95
|
+
var total = digitsArray.filter(function (_, idx) {
|
96
|
+
return !(idx % 2);
|
97
|
+
}).concat(even).map(function (i) {
|
98
|
+
return Number(i);
|
99
|
+
}).reduce(function (acc, cur) {
|
100
|
+
return acc + cur;
|
101
|
+
});
|
102
|
+
return total % 10 === 0;
|
103
|
+
}
|
104
|
+
|
105
|
+
/*
|
106
|
+
* cs-CZ validation function
|
107
|
+
* (Rodné číslo (RČ), persons only)
|
108
|
+
* Checks if birth date (first six digits) is valid and divisibility by 11
|
109
|
+
* Material not in DG TAXUD document sourced from:
|
110
|
+
* -`https://lorenc.info/3MA381/overeni-spravnosti-rodneho-cisla.htm`
|
111
|
+
* -`https://www.mvcr.cz/clanek/rady-a-sluzby-dokumenty-rodne-cislo.aspx`
|
112
|
+
*/
|
113
|
+
function csCzCheck(tin) {
|
114
|
+
tin = tin.replace(/\W/, '');
|
115
|
+
|
116
|
+
// Extract full year from TIN length
|
117
|
+
var full_year = parseInt(tin.slice(0, 2), 10);
|
118
|
+
if (tin.length === 10) {
|
119
|
+
if (full_year < 54) {
|
120
|
+
full_year = "20".concat(full_year);
|
121
|
+
} else {
|
122
|
+
full_year = "19".concat(full_year);
|
123
|
+
}
|
124
|
+
} else {
|
125
|
+
if (tin.slice(6) === '000') {
|
126
|
+
return false;
|
127
|
+
} // Three-zero serial not assigned before 1954
|
128
|
+
if (full_year < 54) {
|
129
|
+
full_year = "19".concat(full_year);
|
130
|
+
} else {
|
131
|
+
return false; // No 18XX years seen in any of the resources
|
132
|
+
}
|
133
|
+
}
|
134
|
+
// Add missing zero if needed
|
135
|
+
if (full_year.length === 3) {
|
136
|
+
full_year = [full_year.slice(0, 2), '0', full_year.slice(2)].join('');
|
137
|
+
}
|
138
|
+
|
139
|
+
// Extract month from TIN and normalize
|
140
|
+
var month = parseInt(tin.slice(2, 4), 10);
|
141
|
+
if (month > 50) {
|
142
|
+
month -= 50;
|
143
|
+
}
|
144
|
+
if (month > 20) {
|
145
|
+
// Month-plus-twenty was only introduced in 2004
|
146
|
+
if (parseInt(full_year, 10) < 2004) {
|
147
|
+
return false;
|
148
|
+
}
|
149
|
+
month -= 20;
|
150
|
+
}
|
151
|
+
if (month < 10) {
|
152
|
+
month = "0".concat(month);
|
153
|
+
}
|
154
|
+
|
155
|
+
// Check date validity
|
156
|
+
var date = "".concat(full_year, "/").concat(month, "/").concat(tin.slice(4, 6));
|
157
|
+
if (!isDate(date, 'YYYY/MM/DD')) {
|
158
|
+
return false;
|
159
|
+
}
|
160
|
+
|
161
|
+
// Verify divisibility by 11
|
162
|
+
if (tin.length === 10) {
|
163
|
+
if (parseInt(tin, 10) % 11 !== 0) {
|
164
|
+
// Some numbers up to and including 1985 are still valid if
|
165
|
+
// check (last) digit equals 0 and modulo of first 9 digits equals 10
|
166
|
+
var checkdigit = parseInt(tin.slice(0, 9), 10) % 11;
|
167
|
+
if (parseInt(full_year, 10) < 1986 && checkdigit === 10) {
|
168
|
+
if (parseInt(tin.slice(9), 10) !== 0) {
|
169
|
+
return false;
|
170
|
+
}
|
171
|
+
} else {
|
172
|
+
return false;
|
173
|
+
}
|
174
|
+
}
|
175
|
+
}
|
176
|
+
return true;
|
177
|
+
}
|
178
|
+
|
179
|
+
/*
|
180
|
+
* de-AT validation function
|
181
|
+
* (Abgabenkontonummer, persons/entities)
|
182
|
+
* Verify TIN validity by calling luhnCheck()
|
183
|
+
*/
|
184
|
+
function deAtCheck(tin) {
|
185
|
+
return algorithms.luhnCheck(tin);
|
186
|
+
}
|
187
|
+
|
188
|
+
/*
|
189
|
+
* de-DE validation function
|
190
|
+
* (Steueridentifikationsnummer (Steuer-IdNr.), persons only)
|
191
|
+
* Tests for single duplicate/triplicate value, then calculates ISO 7064 check (last) digit
|
192
|
+
* Partial implementation of spec (same result with both algorithms always)
|
193
|
+
*/
|
194
|
+
function deDeCheck(tin) {
|
195
|
+
// Split digits into an array for further processing
|
196
|
+
var digits = tin.split('').map(function (a) {
|
197
|
+
return parseInt(a, 10);
|
198
|
+
});
|
199
|
+
|
200
|
+
// Fill array with strings of number positions
|
201
|
+
var occurences = [];
|
202
|
+
for (var i = 0; i < digits.length - 1; i++) {
|
203
|
+
occurences.push('');
|
204
|
+
for (var j = 0; j < digits.length - 1; j++) {
|
205
|
+
if (digits[i] === digits[j]) {
|
206
|
+
occurences[i] += j;
|
207
|
+
}
|
208
|
+
}
|
209
|
+
}
|
210
|
+
|
211
|
+
// Remove digits with one occurence and test for only one duplicate/triplicate
|
212
|
+
occurences = occurences.filter(function (a) {
|
213
|
+
return a.length > 1;
|
214
|
+
});
|
215
|
+
if (occurences.length !== 2 && occurences.length !== 3) {
|
216
|
+
return false;
|
217
|
+
}
|
218
|
+
|
219
|
+
// In case of triplicate value only two digits are allowed next to each other
|
220
|
+
if (occurences[0].length === 3) {
|
221
|
+
var trip_locations = occurences[0].split('').map(function (a) {
|
222
|
+
return parseInt(a, 10);
|
223
|
+
});
|
224
|
+
var recurrent = 0; // Amount of neighbour occurences
|
225
|
+
for (var _i = 0; _i < trip_locations.length - 1; _i++) {
|
226
|
+
if (trip_locations[_i] + 1 === trip_locations[_i + 1]) {
|
227
|
+
recurrent += 1;
|
228
|
+
}
|
229
|
+
}
|
230
|
+
if (recurrent === 2) {
|
231
|
+
return false;
|
232
|
+
}
|
233
|
+
}
|
234
|
+
return algorithms.iso7064Check(tin);
|
235
|
+
}
|
236
|
+
|
237
|
+
/*
|
238
|
+
* dk-DK validation function
|
239
|
+
* (CPR-nummer (personnummer), persons only)
|
240
|
+
* Checks if birth date (first six digits) is valid and assigned to century (seventh) digit,
|
241
|
+
* and calculates check (last) digit
|
242
|
+
*/
|
243
|
+
function dkDkCheck(tin) {
|
244
|
+
tin = tin.replace(/\W/, '');
|
245
|
+
|
246
|
+
// Extract year, check if valid for given century digit and add century
|
247
|
+
var year = parseInt(tin.slice(4, 6), 10);
|
248
|
+
var century_digit = tin.slice(6, 7);
|
249
|
+
switch (century_digit) {
|
250
|
+
case '0':
|
251
|
+
case '1':
|
252
|
+
case '2':
|
253
|
+
case '3':
|
254
|
+
year = "19".concat(year);
|
255
|
+
break;
|
256
|
+
case '4':
|
257
|
+
case '9':
|
258
|
+
if (year < 37) {
|
259
|
+
year = "20".concat(year);
|
260
|
+
} else {
|
261
|
+
year = "19".concat(year);
|
262
|
+
}
|
263
|
+
break;
|
264
|
+
default:
|
265
|
+
if (year < 37) {
|
266
|
+
year = "20".concat(year);
|
267
|
+
} else if (year > 58) {
|
268
|
+
year = "18".concat(year);
|
269
|
+
} else {
|
270
|
+
return false;
|
271
|
+
}
|
272
|
+
break;
|
273
|
+
}
|
274
|
+
// Add missing zero if needed
|
275
|
+
if (year.length === 3) {
|
276
|
+
year = [year.slice(0, 2), '0', year.slice(2)].join('');
|
277
|
+
}
|
278
|
+
// Check date validity
|
279
|
+
var date = "".concat(year, "/").concat(tin.slice(2, 4), "/").concat(tin.slice(0, 2));
|
280
|
+
if (!isDate(date, 'YYYY/MM/DD')) {
|
281
|
+
return false;
|
282
|
+
}
|
283
|
+
|
284
|
+
// Split digits into an array for further processing
|
285
|
+
var digits = tin.split('').map(function (a) {
|
286
|
+
return parseInt(a, 10);
|
287
|
+
});
|
288
|
+
var checksum = 0;
|
289
|
+
var weight = 4;
|
290
|
+
// Multiply by weight and add to checksum
|
291
|
+
for (var i = 0; i < 9; i++) {
|
292
|
+
checksum += digits[i] * weight;
|
293
|
+
weight -= 1;
|
294
|
+
if (weight === 1) {
|
295
|
+
weight = 7;
|
296
|
+
}
|
297
|
+
}
|
298
|
+
checksum %= 11;
|
299
|
+
if (checksum === 1) {
|
300
|
+
return false;
|
301
|
+
}
|
302
|
+
return checksum === 0 ? digits[9] === 0 : digits[9] === 11 - checksum;
|
303
|
+
}
|
304
|
+
|
305
|
+
/*
|
306
|
+
* el-CY validation function
|
307
|
+
* (Arithmos Forologikou Mitroou (AFM/ΑΦΜ), persons only)
|
308
|
+
* Verify TIN validity by calculating ASCII value of check (last) character
|
309
|
+
*/
|
310
|
+
function elCyCheck(tin) {
|
311
|
+
// split digits into an array for further processing
|
312
|
+
var digits = tin.slice(0, 8).split('').map(function (a) {
|
313
|
+
return parseInt(a, 10);
|
314
|
+
});
|
315
|
+
var checksum = 0;
|
316
|
+
// add digits in even places
|
317
|
+
for (var i = 1; i < digits.length; i += 2) {
|
318
|
+
checksum += digits[i];
|
319
|
+
}
|
320
|
+
|
321
|
+
// add digits in odd places
|
322
|
+
for (var _i2 = 0; _i2 < digits.length; _i2 += 2) {
|
323
|
+
if (digits[_i2] < 2) {
|
324
|
+
checksum += 1 - digits[_i2];
|
325
|
+
} else {
|
326
|
+
checksum += 2 * (digits[_i2] - 2) + 5;
|
327
|
+
if (digits[_i2] > 4) {
|
328
|
+
checksum += 2;
|
329
|
+
}
|
330
|
+
}
|
331
|
+
}
|
332
|
+
return String.fromCharCode(checksum % 26 + 65) === tin.charAt(8);
|
333
|
+
}
|
334
|
+
|
335
|
+
/*
|
336
|
+
* el-GR validation function
|
337
|
+
* (Arithmos Forologikou Mitroou (AFM/ΑΦΜ), persons/entities)
|
338
|
+
* Verify TIN validity by calculating check (last) digit
|
339
|
+
* Algorithm not in DG TAXUD document- sourced from:
|
340
|
+
* - `http://epixeirisi.gr/%CE%9A%CE%A1%CE%99%CE%A3%CE%99%CE%9C%CE%91-%CE%98%CE%95%CE%9C%CE%91%CE%A4%CE%91-%CE%A6%CE%9F%CE%A1%CE%9F%CE%9B%CE%9F%CE%93%CE%99%CE%91%CE%A3-%CE%9A%CE%91%CE%99-%CE%9B%CE%9F%CE%93%CE%99%CE%A3%CE%A4%CE%99%CE%9A%CE%97%CE%A3/23791/%CE%91%CF%81%CE%B9%CE%B8%CE%BC%CF%8C%CF%82-%CE%A6%CE%BF%CF%81%CE%BF%CE%BB%CE%BF%CE%B3%CE%B9%CE%BA%CE%BF%CF%8D-%CE%9C%CE%B7%CF%84%CF%81%CF%8E%CE%BF%CF%85`
|
341
|
+
*/
|
342
|
+
function elGrCheck(tin) {
|
343
|
+
// split digits into an array for further processing
|
344
|
+
var digits = tin.split('').map(function (a) {
|
345
|
+
return parseInt(a, 10);
|
346
|
+
});
|
347
|
+
var checksum = 0;
|
348
|
+
for (var i = 0; i < 8; i++) {
|
349
|
+
checksum += digits[i] * Math.pow(2, 8 - i);
|
350
|
+
}
|
351
|
+
return checksum % 11 % 10 === digits[8];
|
352
|
+
}
|
353
|
+
|
354
|
+
/*
|
355
|
+
* en-GB validation function (should go here if needed)
|
356
|
+
* (National Insurance Number (NINO) or Unique Taxpayer Reference (UTR),
|
357
|
+
* persons/entities respectively)
|
358
|
+
*/
|
359
|
+
|
360
|
+
/*
|
361
|
+
* en-IE validation function
|
362
|
+
* (Personal Public Service Number (PPS No), persons only)
|
363
|
+
* Verify TIN validity by calculating check (second to last) character
|
364
|
+
*/
|
365
|
+
function enIeCheck(tin) {
|
366
|
+
var checksum = algorithms.reverseMultiplyAndSum(tin.split('').slice(0, 7).map(function (a) {
|
367
|
+
return parseInt(a, 10);
|
368
|
+
}), 8);
|
369
|
+
if (tin.length === 9 && tin[8] !== 'W') {
|
370
|
+
checksum += (tin[8].charCodeAt(0) - 64) * 9;
|
371
|
+
}
|
372
|
+
checksum %= 23;
|
373
|
+
if (checksum === 0) {
|
374
|
+
return tin[7].toUpperCase() === 'W';
|
375
|
+
}
|
376
|
+
return tin[7].toUpperCase() === String.fromCharCode(64 + checksum);
|
377
|
+
}
|
378
|
+
|
379
|
+
// Valid US IRS campus prefixes
|
380
|
+
var enUsCampusPrefix = {
|
381
|
+
andover: ['10', '12'],
|
382
|
+
atlanta: ['60', '67'],
|
383
|
+
austin: ['50', '53'],
|
384
|
+
brookhaven: ['01', '02', '03', '04', '05', '06', '11', '13', '14', '16', '21', '22', '23', '25', '34', '51', '52', '54', '55', '56', '57', '58', '59', '65'],
|
385
|
+
cincinnati: ['30', '32', '35', '36', '37', '38', '61'],
|
386
|
+
fresno: ['15', '24'],
|
387
|
+
internet: ['20', '26', '27', '45', '46', '47'],
|
388
|
+
kansas: ['40', '44'],
|
389
|
+
memphis: ['94', '95'],
|
390
|
+
ogden: ['80', '90'],
|
391
|
+
philadelphia: ['33', '39', '41', '42', '43', '46', '48', '62', '63', '64', '66', '68', '71', '72', '73', '74', '75', '76', '77', '81', '82', '83', '84', '85', '86', '87', '88', '91', '92', '93', '98', '99'],
|
392
|
+
sba: ['31']
|
393
|
+
};
|
394
|
+
|
395
|
+
// Return an array of all US IRS campus prefixes
|
396
|
+
function enUsGetPrefixes() {
|
397
|
+
var prefixes = [];
|
398
|
+
for (var location in enUsCampusPrefix) {
|
399
|
+
// https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md#ignoring-code-for-coverage-purposes
|
400
|
+
// istanbul ignore else
|
401
|
+
if (enUsCampusPrefix.hasOwnProperty(location)) {
|
402
|
+
prefixes.push.apply(prefixes, _toConsumableArray(enUsCampusPrefix[location]));
|
403
|
+
}
|
404
|
+
}
|
405
|
+
return prefixes;
|
406
|
+
}
|
407
|
+
|
408
|
+
/*
|
409
|
+
* en-US validation function
|
410
|
+
* Verify that the TIN starts with a valid IRS campus prefix
|
411
|
+
*/
|
412
|
+
function enUsCheck(tin) {
|
413
|
+
return enUsGetPrefixes().indexOf(tin.slice(0, 2)) !== -1;
|
414
|
+
}
|
415
|
+
|
416
|
+
/*
|
417
|
+
* es-AR validation function
|
418
|
+
* Clave Única de Identificación Tributaria (CUIT/CUIL)
|
419
|
+
* Sourced from:
|
420
|
+
* - https://servicioscf.afip.gob.ar/publico/abc/ABCpaso2.aspx?id_nivel1=3036&id_nivel2=3040&p=Conceptos%20b%C3%A1sicos
|
421
|
+
* - https://es.wikipedia.org/wiki/Clave_%C3%9Anica_de_Identificaci%C3%B3n_Tributaria
|
422
|
+
*/
|
423
|
+
|
424
|
+
function esArCheck(tin) {
|
425
|
+
var accum = 0;
|
426
|
+
var digits = tin.split('');
|
427
|
+
var digit = parseInt(digits.pop(), 10);
|
428
|
+
for (var i = 0; i < digits.length; i++) {
|
429
|
+
accum += digits[9 - i] * (2 + i % 6);
|
430
|
+
}
|
431
|
+
var verif = 11 - accum % 11;
|
432
|
+
if (verif === 11) {
|
433
|
+
verif = 0;
|
434
|
+
} else if (verif === 10) {
|
435
|
+
verif = 9;
|
436
|
+
}
|
437
|
+
return digit === verif;
|
438
|
+
}
|
439
|
+
|
440
|
+
/*
|
441
|
+
* es-ES validation function
|
442
|
+
* (Documento Nacional de Identidad (DNI)
|
443
|
+
* or Número de Identificación de Extranjero (NIE), persons only)
|
444
|
+
* Verify TIN validity by calculating check (last) character
|
445
|
+
*/
|
446
|
+
function esEsCheck(tin) {
|
447
|
+
// Split characters into an array for further processing
|
448
|
+
var chars = tin.toUpperCase().split('');
|
449
|
+
|
450
|
+
// Replace initial letter if needed
|
451
|
+
if (isNaN(parseInt(chars[0], 10)) && chars.length > 1) {
|
452
|
+
var lead_replace = 0;
|
453
|
+
switch (chars[0]) {
|
454
|
+
case 'Y':
|
455
|
+
lead_replace = 1;
|
456
|
+
break;
|
457
|
+
case 'Z':
|
458
|
+
lead_replace = 2;
|
459
|
+
break;
|
460
|
+
default:
|
461
|
+
}
|
462
|
+
chars.splice(0, 1, lead_replace);
|
463
|
+
// Fill with zeros if smaller than proper
|
464
|
+
} else {
|
465
|
+
while (chars.length < 9) {
|
466
|
+
chars.unshift(0);
|
467
|
+
}
|
468
|
+
}
|
469
|
+
|
470
|
+
// Calculate checksum and check according to lookup
|
471
|
+
var lookup = ['T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X', 'B', 'N', 'J', 'Z', 'S', 'Q', 'V', 'H', 'L', 'C', 'K', 'E'];
|
472
|
+
chars = chars.join('');
|
473
|
+
var checksum = parseInt(chars.slice(0, 8), 10) % 23;
|
474
|
+
return chars[8] === lookup[checksum];
|
475
|
+
}
|
476
|
+
|
477
|
+
/*
|
478
|
+
* et-EE validation function
|
479
|
+
* (Isikukood (IK), persons only)
|
480
|
+
* Checks if birth date (century digit and six following) is valid and calculates check (last) digit
|
481
|
+
* Material not in DG TAXUD document sourced from:
|
482
|
+
* - `https://www.oecd.org/tax/automatic-exchange/crs-implementation-and-assistance/tax-identification-numbers/Estonia-TIN.pdf`
|
483
|
+
*/
|
484
|
+
function etEeCheck(tin) {
|
485
|
+
// Extract year and add century
|
486
|
+
var full_year = tin.slice(1, 3);
|
487
|
+
var century_digit = tin.slice(0, 1);
|
488
|
+
switch (century_digit) {
|
489
|
+
case '1':
|
490
|
+
case '2':
|
491
|
+
full_year = "18".concat(full_year);
|
492
|
+
break;
|
493
|
+
case '3':
|
494
|
+
case '4':
|
495
|
+
full_year = "19".concat(full_year);
|
496
|
+
break;
|
497
|
+
default:
|
498
|
+
full_year = "20".concat(full_year);
|
499
|
+
break;
|
500
|
+
}
|
501
|
+
// Check date validity
|
502
|
+
var date = "".concat(full_year, "/").concat(tin.slice(3, 5), "/").concat(tin.slice(5, 7));
|
503
|
+
if (!isDate(date, 'YYYY/MM/DD')) {
|
504
|
+
return false;
|
505
|
+
}
|
506
|
+
|
507
|
+
// Split digits into an array for further processing
|
508
|
+
var digits = tin.split('').map(function (a) {
|
509
|
+
return parseInt(a, 10);
|
510
|
+
});
|
511
|
+
var checksum = 0;
|
512
|
+
var weight = 1;
|
513
|
+
// Multiply by weight and add to checksum
|
514
|
+
for (var i = 0; i < 10; i++) {
|
515
|
+
checksum += digits[i] * weight;
|
516
|
+
weight += 1;
|
517
|
+
if (weight === 10) {
|
518
|
+
weight = 1;
|
519
|
+
}
|
520
|
+
}
|
521
|
+
// Do again if modulo 11 of checksum is 10
|
522
|
+
if (checksum % 11 === 10) {
|
523
|
+
checksum = 0;
|
524
|
+
weight = 3;
|
525
|
+
for (var _i3 = 0; _i3 < 10; _i3++) {
|
526
|
+
checksum += digits[_i3] * weight;
|
527
|
+
weight += 1;
|
528
|
+
if (weight === 10) {
|
529
|
+
weight = 1;
|
530
|
+
}
|
531
|
+
}
|
532
|
+
if (checksum % 11 === 10) {
|
533
|
+
return digits[10] === 0;
|
534
|
+
}
|
535
|
+
}
|
536
|
+
return checksum % 11 === digits[10];
|
537
|
+
}
|
538
|
+
|
539
|
+
/*
|
540
|
+
* fi-FI validation function
|
541
|
+
* (Henkilötunnus (HETU), persons only)
|
542
|
+
* Checks if birth date (first six digits plus century symbol) is valid
|
543
|
+
* and calculates check (last) digit
|
544
|
+
*/
|
545
|
+
function fiFiCheck(tin) {
|
546
|
+
// Extract year and add century
|
547
|
+
var full_year = tin.slice(4, 6);
|
548
|
+
var century_symbol = tin.slice(6, 7);
|
549
|
+
switch (century_symbol) {
|
550
|
+
case '+':
|
551
|
+
full_year = "18".concat(full_year);
|
552
|
+
break;
|
553
|
+
case '-':
|
554
|
+
full_year = "19".concat(full_year);
|
555
|
+
break;
|
556
|
+
default:
|
557
|
+
full_year = "20".concat(full_year);
|
558
|
+
break;
|
559
|
+
}
|
560
|
+
// Check date validity
|
561
|
+
var date = "".concat(full_year, "/").concat(tin.slice(2, 4), "/").concat(tin.slice(0, 2));
|
562
|
+
if (!isDate(date, 'YYYY/MM/DD')) {
|
563
|
+
return false;
|
564
|
+
}
|
565
|
+
|
566
|
+
// Calculate check character
|
567
|
+
var checksum = parseInt(tin.slice(0, 6) + tin.slice(7, 10), 10) % 31;
|
568
|
+
if (checksum < 10) {
|
569
|
+
return checksum === parseInt(tin.slice(10), 10);
|
570
|
+
}
|
571
|
+
checksum -= 10;
|
572
|
+
var letters_lookup = ['A', 'B', 'C', 'D', 'E', 'F', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y'];
|
573
|
+
return letters_lookup[checksum] === tin.slice(10);
|
574
|
+
}
|
575
|
+
|
576
|
+
/*
|
577
|
+
* fr/nl-BE validation function
|
578
|
+
* (Numéro national (N.N.), persons only)
|
579
|
+
* Checks if birth date (first six digits) is valid and calculates check (last two) digits
|
580
|
+
*/
|
581
|
+
function frBeCheck(tin) {
|
582
|
+
// Zero month/day value is acceptable
|
583
|
+
if (tin.slice(2, 4) !== '00' || tin.slice(4, 6) !== '00') {
|
584
|
+
// Extract date from first six digits of TIN
|
585
|
+
var date = "".concat(tin.slice(0, 2), "/").concat(tin.slice(2, 4), "/").concat(tin.slice(4, 6));
|
586
|
+
if (!isDate(date, 'YY/MM/DD')) {
|
587
|
+
return false;
|
588
|
+
}
|
589
|
+
}
|
590
|
+
var checksum = 97 - parseInt(tin.slice(0, 9), 10) % 97;
|
591
|
+
var checkdigits = parseInt(tin.slice(9, 11), 10);
|
592
|
+
if (checksum !== checkdigits) {
|
593
|
+
checksum = 97 - parseInt("2".concat(tin.slice(0, 9)), 10) % 97;
|
594
|
+
if (checksum !== checkdigits) {
|
595
|
+
return false;
|
596
|
+
}
|
597
|
+
}
|
598
|
+
return true;
|
599
|
+
}
|
600
|
+
|
601
|
+
/*
|
602
|
+
* fr-FR validation function
|
603
|
+
* (Numéro fiscal de référence (numéro SPI), persons only)
|
604
|
+
* Verify TIN validity by calculating check (last three) digits
|
605
|
+
*/
|
606
|
+
function frFrCheck(tin) {
|
607
|
+
tin = tin.replace(/\s/g, '');
|
608
|
+
var checksum = parseInt(tin.slice(0, 10), 10) % 511;
|
609
|
+
var checkdigits = parseInt(tin.slice(10, 13), 10);
|
610
|
+
return checksum === checkdigits;
|
611
|
+
}
|
612
|
+
|
613
|
+
/*
|
614
|
+
* fr/lb-LU validation function
|
615
|
+
* (numéro d’identification personnelle, persons only)
|
616
|
+
* Verify birth date validity and run Luhn and Verhoeff checks
|
617
|
+
*/
|
618
|
+
function frLuCheck(tin) {
|
619
|
+
// Extract date and check validity
|
620
|
+
var date = "".concat(tin.slice(0, 4), "/").concat(tin.slice(4, 6), "/").concat(tin.slice(6, 8));
|
621
|
+
if (!isDate(date, 'YYYY/MM/DD')) {
|
622
|
+
return false;
|
623
|
+
}
|
624
|
+
|
625
|
+
// Run Luhn check
|
626
|
+
if (!algorithms.luhnCheck(tin.slice(0, 12))) {
|
627
|
+
return false;
|
628
|
+
}
|
629
|
+
// Remove Luhn check digit and run Verhoeff check
|
630
|
+
return algorithms.verhoeffCheck("".concat(tin.slice(0, 11)).concat(tin[12]));
|
631
|
+
}
|
632
|
+
|
633
|
+
/*
|
634
|
+
* hr-HR validation function
|
635
|
+
* (Osobni identifikacijski broj (OIB), persons/entities)
|
636
|
+
* Verify TIN validity by calling iso7064Check(digits)
|
637
|
+
*/
|
638
|
+
function hrHrCheck(tin) {
|
639
|
+
return algorithms.iso7064Check(tin);
|
640
|
+
}
|
641
|
+
|
642
|
+
/*
|
643
|
+
* hu-HU validation function
|
644
|
+
* (Adóazonosító jel, persons only)
|
645
|
+
* Verify TIN validity by calculating check (last) digit
|
646
|
+
*/
|
647
|
+
function huHuCheck(tin) {
|
648
|
+
// split digits into an array for further processing
|
649
|
+
var digits = tin.split('').map(function (a) {
|
650
|
+
return parseInt(a, 10);
|
651
|
+
});
|
652
|
+
var checksum = 8;
|
653
|
+
for (var i = 1; i < 9; i++) {
|
654
|
+
checksum += digits[i] * (i + 1);
|
655
|
+
}
|
656
|
+
return checksum % 11 === digits[9];
|
657
|
+
}
|
658
|
+
|
659
|
+
/*
|
660
|
+
* lt-LT validation function (should go here if needed)
|
661
|
+
* (Asmens kodas, persons/entities respectively)
|
662
|
+
* Current validation check is alias of etEeCheck- same format applies
|
663
|
+
*/
|
664
|
+
|
665
|
+
/*
|
666
|
+
* it-IT first/last name validity check
|
667
|
+
* Accepts it-IT TIN-encoded names as a three-element character array and checks their validity
|
668
|
+
* Due to lack of clarity between resources ("Are only Italian consonants used?
|
669
|
+
* What happens if a person has X in their name?" etc.) only two test conditions
|
670
|
+
* have been implemented:
|
671
|
+
* Vowels may only be followed by other vowels or an X character
|
672
|
+
* and X characters after vowels may only be followed by other X characters.
|
673
|
+
*/
|
674
|
+
function itItNameCheck(name) {
|
675
|
+
// true at the first occurence of a vowel
|
676
|
+
var vowelflag = false;
|
677
|
+
|
678
|
+
// true at the first occurence of an X AFTER vowel
|
679
|
+
// (to properly handle last names with X as consonant)
|
680
|
+
var xflag = false;
|
681
|
+
for (var i = 0; i < 3; i++) {
|
682
|
+
if (!vowelflag && /[AEIOU]/.test(name[i])) {
|
683
|
+
vowelflag = true;
|
684
|
+
} else if (!xflag && vowelflag && name[i] === 'X') {
|
685
|
+
xflag = true;
|
686
|
+
} else if (i > 0) {
|
687
|
+
if (vowelflag && !xflag) {
|
688
|
+
if (!/[AEIOU]/.test(name[i])) {
|
689
|
+
return false;
|
690
|
+
}
|
691
|
+
}
|
692
|
+
if (xflag) {
|
693
|
+
if (!/X/.test(name[i])) {
|
694
|
+
return false;
|
695
|
+
}
|
696
|
+
}
|
697
|
+
}
|
698
|
+
}
|
699
|
+
return true;
|
700
|
+
}
|
701
|
+
|
702
|
+
/*
|
703
|
+
* it-IT validation function
|
704
|
+
* (Codice fiscale (TIN-IT), persons only)
|
705
|
+
* Verify name, birth date and codice catastale validity
|
706
|
+
* and calculate check character.
|
707
|
+
* Material not in DG-TAXUD document sourced from:
|
708
|
+
* `https://en.wikipedia.org/wiki/Italian_fiscal_code`
|
709
|
+
*/
|
710
|
+
function itItCheck(tin) {
|
711
|
+
// Capitalize and split characters into an array for further processing
|
712
|
+
var chars = tin.toUpperCase().split('');
|
713
|
+
|
714
|
+
// Check first and last name validity calling itItNameCheck()
|
715
|
+
if (!itItNameCheck(chars.slice(0, 3))) {
|
716
|
+
return false;
|
717
|
+
}
|
718
|
+
if (!itItNameCheck(chars.slice(3, 6))) {
|
719
|
+
return false;
|
720
|
+
}
|
721
|
+
|
722
|
+
// Convert letters in number spaces back to numbers if any
|
723
|
+
var number_locations = [6, 7, 9, 10, 12, 13, 14];
|
724
|
+
var number_replace = {
|
725
|
+
L: '0',
|
726
|
+
M: '1',
|
727
|
+
N: '2',
|
728
|
+
P: '3',
|
729
|
+
Q: '4',
|
730
|
+
R: '5',
|
731
|
+
S: '6',
|
732
|
+
T: '7',
|
733
|
+
U: '8',
|
734
|
+
V: '9'
|
735
|
+
};
|
736
|
+
for (var _i4 = 0, _number_locations = number_locations; _i4 < _number_locations.length; _i4++) {
|
737
|
+
var i = _number_locations[_i4];
|
738
|
+
if (chars[i] in number_replace) {
|
739
|
+
chars.splice(i, 1, number_replace[chars[i]]);
|
740
|
+
}
|
741
|
+
}
|
742
|
+
|
743
|
+
// Extract month and day, and check date validity
|
744
|
+
var month_replace = {
|
745
|
+
A: '01',
|
746
|
+
B: '02',
|
747
|
+
C: '03',
|
748
|
+
D: '04',
|
749
|
+
E: '05',
|
750
|
+
H: '06',
|
751
|
+
L: '07',
|
752
|
+
M: '08',
|
753
|
+
P: '09',
|
754
|
+
R: '10',
|
755
|
+
S: '11',
|
756
|
+
T: '12'
|
757
|
+
};
|
758
|
+
var month = month_replace[chars[8]];
|
759
|
+
var day = parseInt(chars[9] + chars[10], 10);
|
760
|
+
if (day > 40) {
|
761
|
+
day -= 40;
|
762
|
+
}
|
763
|
+
if (day < 10) {
|
764
|
+
day = "0".concat(day);
|
765
|
+
}
|
766
|
+
var date = "".concat(chars[6]).concat(chars[7], "/").concat(month, "/").concat(day);
|
767
|
+
if (!isDate(date, 'YY/MM/DD')) {
|
768
|
+
return false;
|
769
|
+
}
|
770
|
+
|
771
|
+
// Calculate check character by adding up even and odd characters as numbers
|
772
|
+
var checksum = 0;
|
773
|
+
for (var _i5 = 1; _i5 < chars.length - 1; _i5 += 2) {
|
774
|
+
var char_to_int = parseInt(chars[_i5], 10);
|
775
|
+
if (isNaN(char_to_int)) {
|
776
|
+
char_to_int = chars[_i5].charCodeAt(0) - 65;
|
777
|
+
}
|
778
|
+
checksum += char_to_int;
|
779
|
+
}
|
780
|
+
var odd_convert = {
|
781
|
+
// Maps of characters at odd places
|
782
|
+
A: 1,
|
783
|
+
B: 0,
|
784
|
+
C: 5,
|
785
|
+
D: 7,
|
786
|
+
E: 9,
|
787
|
+
F: 13,
|
788
|
+
G: 15,
|
789
|
+
H: 17,
|
790
|
+
I: 19,
|
791
|
+
J: 21,
|
792
|
+
K: 2,
|
793
|
+
L: 4,
|
794
|
+
M: 18,
|
795
|
+
N: 20,
|
796
|
+
O: 11,
|
797
|
+
P: 3,
|
798
|
+
Q: 6,
|
799
|
+
R: 8,
|
800
|
+
S: 12,
|
801
|
+
T: 14,
|
802
|
+
U: 16,
|
803
|
+
V: 10,
|
804
|
+
W: 22,
|
805
|
+
X: 25,
|
806
|
+
Y: 24,
|
807
|
+
Z: 23,
|
808
|
+
0: 1,
|
809
|
+
1: 0
|
810
|
+
};
|
811
|
+
for (var _i6 = 0; _i6 < chars.length - 1; _i6 += 2) {
|
812
|
+
var _char_to_int = 0;
|
813
|
+
if (chars[_i6] in odd_convert) {
|
814
|
+
_char_to_int = odd_convert[chars[_i6]];
|
815
|
+
} else {
|
816
|
+
var multiplier = parseInt(chars[_i6], 10);
|
817
|
+
_char_to_int = 2 * multiplier + 1;
|
818
|
+
if (multiplier > 4) {
|
819
|
+
_char_to_int += 2;
|
820
|
+
}
|
821
|
+
}
|
822
|
+
checksum += _char_to_int;
|
823
|
+
}
|
824
|
+
if (String.fromCharCode(65 + checksum % 26) !== chars[15]) {
|
825
|
+
return false;
|
826
|
+
}
|
827
|
+
return true;
|
828
|
+
}
|
829
|
+
|
830
|
+
/*
|
831
|
+
* lv-LV validation function
|
832
|
+
* (Personas kods (PK), persons only)
|
833
|
+
* Check validity of birth date and calculate check (last) digit
|
834
|
+
* Support only for old format numbers (not starting with '32', issued before 2017/07/01)
|
835
|
+
* Material not in DG TAXUD document sourced from:
|
836
|
+
* `https://boot.ritakafija.lv/forums/index.php?/topic/88314-personas-koda-algoritms-%C4%8Deksumma/`
|
837
|
+
*/
|
838
|
+
function lvLvCheck(tin) {
|
839
|
+
tin = tin.replace(/\W/, '');
|
840
|
+
// Extract date from TIN
|
841
|
+
var day = tin.slice(0, 2);
|
842
|
+
if (day !== '32') {
|
843
|
+
// No date/checksum check if new format
|
844
|
+
var month = tin.slice(2, 4);
|
845
|
+
if (month !== '00') {
|
846
|
+
// No date check if unknown month
|
847
|
+
var full_year = tin.slice(4, 6);
|
848
|
+
switch (tin[6]) {
|
849
|
+
case '0':
|
850
|
+
full_year = "18".concat(full_year);
|
851
|
+
break;
|
852
|
+
case '1':
|
853
|
+
full_year = "19".concat(full_year);
|
854
|
+
break;
|
855
|
+
default:
|
856
|
+
full_year = "20".concat(full_year);
|
857
|
+
break;
|
858
|
+
}
|
859
|
+
// Check date validity
|
860
|
+
var date = "".concat(full_year, "/").concat(tin.slice(2, 4), "/").concat(day);
|
861
|
+
if (!isDate(date, 'YYYY/MM/DD')) {
|
862
|
+
return false;
|
863
|
+
}
|
864
|
+
}
|
865
|
+
|
866
|
+
// Calculate check digit
|
867
|
+
var checksum = 1101;
|
868
|
+
var multip_lookup = [1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
|
869
|
+
for (var i = 0; i < tin.length - 1; i++) {
|
870
|
+
checksum -= parseInt(tin[i], 10) * multip_lookup[i];
|
871
|
+
}
|
872
|
+
return parseInt(tin[10], 10) === checksum % 11;
|
873
|
+
}
|
874
|
+
return true;
|
875
|
+
}
|
876
|
+
|
877
|
+
/*
|
878
|
+
* mt-MT validation function
|
879
|
+
* (Identity Card Number or Unique Taxpayer Reference, persons/entities)
|
880
|
+
* Verify Identity Card Number structure (no other tests found)
|
881
|
+
*/
|
882
|
+
function mtMtCheck(tin) {
|
883
|
+
if (tin.length !== 9) {
|
884
|
+
// No tests for UTR
|
885
|
+
var chars = tin.toUpperCase().split('');
|
886
|
+
// Fill with zeros if smaller than proper
|
887
|
+
while (chars.length < 8) {
|
888
|
+
chars.unshift(0);
|
889
|
+
}
|
890
|
+
// Validate format according to last character
|
891
|
+
switch (tin[7]) {
|
892
|
+
case 'A':
|
893
|
+
case 'P':
|
894
|
+
if (parseInt(chars[6], 10) === 0) {
|
895
|
+
return false;
|
896
|
+
}
|
897
|
+
break;
|
898
|
+
default:
|
899
|
+
{
|
900
|
+
var first_part = parseInt(chars.join('').slice(0, 5), 10);
|
901
|
+
if (first_part > 32000) {
|
902
|
+
return false;
|
903
|
+
}
|
904
|
+
var second_part = parseInt(chars.join('').slice(5, 7), 10);
|
905
|
+
if (first_part === second_part) {
|
906
|
+
return false;
|
907
|
+
}
|
908
|
+
}
|
909
|
+
}
|
910
|
+
}
|
911
|
+
return true;
|
912
|
+
}
|
913
|
+
|
914
|
+
/*
|
915
|
+
* nl-NL validation function
|
916
|
+
* (Burgerservicenummer (BSN) or Rechtspersonen Samenwerkingsverbanden Informatie Nummer (RSIN),
|
917
|
+
* persons/entities respectively)
|
918
|
+
* Verify TIN validity by calculating check (last) digit (variant of MOD 11)
|
919
|
+
*/
|
920
|
+
function nlNlCheck(tin) {
|
921
|
+
return algorithms.reverseMultiplyAndSum(tin.split('').slice(0, 8).map(function (a) {
|
922
|
+
return parseInt(a, 10);
|
923
|
+
}), 9) % 11 === parseInt(tin[8], 10);
|
924
|
+
}
|
925
|
+
|
926
|
+
/*
|
927
|
+
* pl-PL validation function
|
928
|
+
* (Powszechny Elektroniczny System Ewidencji Ludności (PESEL)
|
929
|
+
* or Numer identyfikacji podatkowej (NIP), persons/entities)
|
930
|
+
* Verify TIN validity by validating birth date (PESEL) and calculating check (last) digit
|
931
|
+
*/
|
932
|
+
function plPlCheck(tin) {
|
933
|
+
// NIP
|
934
|
+
if (tin.length === 10) {
|
935
|
+
// Calculate last digit by multiplying with lookup
|
936
|
+
var lookup = [6, 5, 7, 2, 3, 4, 5, 6, 7];
|
937
|
+
var _checksum = 0;
|
938
|
+
for (var i = 0; i < lookup.length; i++) {
|
939
|
+
_checksum += parseInt(tin[i], 10) * lookup[i];
|
940
|
+
}
|
941
|
+
_checksum %= 11;
|
942
|
+
if (_checksum === 10) {
|
943
|
+
return false;
|
944
|
+
}
|
945
|
+
return _checksum === parseInt(tin[9], 10);
|
946
|
+
}
|
947
|
+
|
948
|
+
// PESEL
|
949
|
+
// Extract full year using month
|
950
|
+
var full_year = tin.slice(0, 2);
|
951
|
+
var month = parseInt(tin.slice(2, 4), 10);
|
952
|
+
if (month > 80) {
|
953
|
+
full_year = "18".concat(full_year);
|
954
|
+
month -= 80;
|
955
|
+
} else if (month > 60) {
|
956
|
+
full_year = "22".concat(full_year);
|
957
|
+
month -= 60;
|
958
|
+
} else if (month > 40) {
|
959
|
+
full_year = "21".concat(full_year);
|
960
|
+
month -= 40;
|
961
|
+
} else if (month > 20) {
|
962
|
+
full_year = "20".concat(full_year);
|
963
|
+
month -= 20;
|
964
|
+
} else {
|
965
|
+
full_year = "19".concat(full_year);
|
966
|
+
}
|
967
|
+
// Add leading zero to month if needed
|
968
|
+
if (month < 10) {
|
969
|
+
month = "0".concat(month);
|
970
|
+
}
|
971
|
+
// Check date validity
|
972
|
+
var date = "".concat(full_year, "/").concat(month, "/").concat(tin.slice(4, 6));
|
973
|
+
if (!isDate(date, 'YYYY/MM/DD')) {
|
974
|
+
return false;
|
975
|
+
}
|
976
|
+
|
977
|
+
// Calculate last digit by mulitplying with odd one-digit numbers except 5
|
978
|
+
var checksum = 0;
|
979
|
+
var multiplier = 1;
|
980
|
+
for (var _i7 = 0; _i7 < tin.length - 1; _i7++) {
|
981
|
+
checksum += parseInt(tin[_i7], 10) * multiplier % 10;
|
982
|
+
multiplier += 2;
|
983
|
+
if (multiplier > 10) {
|
984
|
+
multiplier = 1;
|
985
|
+
} else if (multiplier === 5) {
|
986
|
+
multiplier += 2;
|
987
|
+
}
|
988
|
+
}
|
989
|
+
checksum = 10 - checksum % 10;
|
990
|
+
return checksum === parseInt(tin[10], 10);
|
991
|
+
}
|
992
|
+
|
993
|
+
/*
|
994
|
+
* pt-BR validation function
|
995
|
+
* (Cadastro de Pessoas Físicas (CPF, persons)
|
996
|
+
* Cadastro Nacional de Pessoas Jurídicas (CNPJ, entities)
|
997
|
+
* Both inputs will be validated
|
998
|
+
*/
|
999
|
+
|
1000
|
+
function ptBrCheck(tin) {
|
1001
|
+
if (tin.length === 11) {
|
1002
|
+
var _sum;
|
1003
|
+
var remainder;
|
1004
|
+
_sum = 0;
|
1005
|
+
if (
|
1006
|
+
// Reject known invalid CPFs
|
1007
|
+
tin === '11111111111' || tin === '22222222222' || tin === '33333333333' || tin === '44444444444' || tin === '55555555555' || tin === '66666666666' || tin === '77777777777' || tin === '88888888888' || tin === '99999999999' || tin === '00000000000') return false;
|
1008
|
+
for (var i = 1; i <= 9; i++) _sum += parseInt(tin.substring(i - 1, i), 10) * (11 - i);
|
1009
|
+
remainder = _sum * 10 % 11;
|
1010
|
+
if (remainder === 10) remainder = 0;
|
1011
|
+
if (remainder !== parseInt(tin.substring(9, 10), 10)) return false;
|
1012
|
+
_sum = 0;
|
1013
|
+
for (var _i8 = 1; _i8 <= 10; _i8++) _sum += parseInt(tin.substring(_i8 - 1, _i8), 10) * (12 - _i8);
|
1014
|
+
remainder = _sum * 10 % 11;
|
1015
|
+
if (remainder === 10) remainder = 0;
|
1016
|
+
if (remainder !== parseInt(tin.substring(10, 11), 10)) return false;
|
1017
|
+
return true;
|
1018
|
+
}
|
1019
|
+
if (
|
1020
|
+
// Reject know invalid CNPJs
|
1021
|
+
tin === '00000000000000' || tin === '11111111111111' || tin === '22222222222222' || tin === '33333333333333' || tin === '44444444444444' || tin === '55555555555555' || tin === '66666666666666' || tin === '77777777777777' || tin === '88888888888888' || tin === '99999999999999') {
|
1022
|
+
return false;
|
1023
|
+
}
|
1024
|
+
var length = tin.length - 2;
|
1025
|
+
var identifiers = tin.substring(0, length);
|
1026
|
+
var verificators = tin.substring(length);
|
1027
|
+
var sum = 0;
|
1028
|
+
var pos = length - 7;
|
1029
|
+
for (var _i9 = length; _i9 >= 1; _i9--) {
|
1030
|
+
sum += identifiers.charAt(length - _i9) * pos;
|
1031
|
+
pos -= 1;
|
1032
|
+
if (pos < 2) {
|
1033
|
+
pos = 9;
|
1034
|
+
}
|
1035
|
+
}
|
1036
|
+
var result = sum % 11 < 2 ? 0 : 11 - sum % 11;
|
1037
|
+
if (result !== parseInt(verificators.charAt(0), 10)) {
|
1038
|
+
return false;
|
1039
|
+
}
|
1040
|
+
length += 1;
|
1041
|
+
identifiers = tin.substring(0, length);
|
1042
|
+
sum = 0;
|
1043
|
+
pos = length - 7;
|
1044
|
+
for (var _i10 = length; _i10 >= 1; _i10--) {
|
1045
|
+
sum += identifiers.charAt(length - _i10) * pos;
|
1046
|
+
pos -= 1;
|
1047
|
+
if (pos < 2) {
|
1048
|
+
pos = 9;
|
1049
|
+
}
|
1050
|
+
}
|
1051
|
+
result = sum % 11 < 2 ? 0 : 11 - sum % 11;
|
1052
|
+
if (result !== parseInt(verificators.charAt(1), 10)) {
|
1053
|
+
return false;
|
1054
|
+
}
|
1055
|
+
return true;
|
1056
|
+
}
|
1057
|
+
|
1058
|
+
/*
|
1059
|
+
* pt-PT validation function
|
1060
|
+
* (Número de identificação fiscal (NIF), persons/entities)
|
1061
|
+
* Verify TIN validity by calculating check (last) digit (variant of MOD 11)
|
1062
|
+
*/
|
1063
|
+
function ptPtCheck(tin) {
|
1064
|
+
var checksum = 11 - algorithms.reverseMultiplyAndSum(tin.split('').slice(0, 8).map(function (a) {
|
1065
|
+
return parseInt(a, 10);
|
1066
|
+
}), 9) % 11;
|
1067
|
+
if (checksum > 9) {
|
1068
|
+
return parseInt(tin[8], 10) === 0;
|
1069
|
+
}
|
1070
|
+
return checksum === parseInt(tin[8], 10);
|
1071
|
+
}
|
1072
|
+
|
1073
|
+
/*
|
1074
|
+
* ro-RO validation function
|
1075
|
+
* (Cod Numeric Personal (CNP) or Cod de înregistrare fiscală (CIF),
|
1076
|
+
* persons only)
|
1077
|
+
* Verify CNP validity by calculating check (last) digit (test not found for CIF)
|
1078
|
+
* Material not in DG TAXUD document sourced from:
|
1079
|
+
* `https://en.wikipedia.org/wiki/National_identification_number#Romania`
|
1080
|
+
*/
|
1081
|
+
function roRoCheck(tin) {
|
1082
|
+
if (tin.slice(0, 4) !== '9000') {
|
1083
|
+
// No test found for this format
|
1084
|
+
// Extract full year using century digit if possible
|
1085
|
+
var full_year = tin.slice(1, 3);
|
1086
|
+
switch (tin[0]) {
|
1087
|
+
case '1':
|
1088
|
+
case '2':
|
1089
|
+
full_year = "19".concat(full_year);
|
1090
|
+
break;
|
1091
|
+
case '3':
|
1092
|
+
case '4':
|
1093
|
+
full_year = "18".concat(full_year);
|
1094
|
+
break;
|
1095
|
+
case '5':
|
1096
|
+
case '6':
|
1097
|
+
full_year = "20".concat(full_year);
|
1098
|
+
break;
|
1099
|
+
default:
|
1100
|
+
}
|
1101
|
+
|
1102
|
+
// Check date validity
|
1103
|
+
var date = "".concat(full_year, "/").concat(tin.slice(3, 5), "/").concat(tin.slice(5, 7));
|
1104
|
+
if (date.length === 8) {
|
1105
|
+
if (!isDate(date, 'YY/MM/DD')) {
|
1106
|
+
return false;
|
1107
|
+
}
|
1108
|
+
} else if (!isDate(date, 'YYYY/MM/DD')) {
|
1109
|
+
return false;
|
1110
|
+
}
|
1111
|
+
|
1112
|
+
// Calculate check digit
|
1113
|
+
var digits = tin.split('').map(function (a) {
|
1114
|
+
return parseInt(a, 10);
|
1115
|
+
});
|
1116
|
+
var multipliers = [2, 7, 9, 1, 4, 6, 3, 5, 8, 2, 7, 9];
|
1117
|
+
var checksum = 0;
|
1118
|
+
for (var i = 0; i < multipliers.length; i++) {
|
1119
|
+
checksum += digits[i] * multipliers[i];
|
1120
|
+
}
|
1121
|
+
if (checksum % 11 === 10) {
|
1122
|
+
return digits[12] === 1;
|
1123
|
+
}
|
1124
|
+
return digits[12] === checksum % 11;
|
1125
|
+
}
|
1126
|
+
return true;
|
1127
|
+
}
|
1128
|
+
|
1129
|
+
/*
|
1130
|
+
* sk-SK validation function
|
1131
|
+
* (Rodné číslo (RČ) or bezvýznamové identifikačné číslo (BIČ), persons only)
|
1132
|
+
* Checks validity of pre-1954 birth numbers (rodné číslo) only
|
1133
|
+
* Due to the introduction of the pseudo-random BIČ it is not possible to test
|
1134
|
+
* post-1954 birth numbers without knowing whether they are BIČ or RČ beforehand
|
1135
|
+
*/
|
1136
|
+
function skSkCheck(tin) {
|
1137
|
+
if (tin.length === 9) {
|
1138
|
+
tin = tin.replace(/\W/, '');
|
1139
|
+
if (tin.slice(6) === '000') {
|
1140
|
+
return false;
|
1141
|
+
} // Three-zero serial not assigned before 1954
|
1142
|
+
|
1143
|
+
// Extract full year from TIN length
|
1144
|
+
var full_year = parseInt(tin.slice(0, 2), 10);
|
1145
|
+
if (full_year > 53) {
|
1146
|
+
return false;
|
1147
|
+
}
|
1148
|
+
if (full_year < 10) {
|
1149
|
+
full_year = "190".concat(full_year);
|
1150
|
+
} else {
|
1151
|
+
full_year = "19".concat(full_year);
|
1152
|
+
}
|
1153
|
+
|
1154
|
+
// Extract month from TIN and normalize
|
1155
|
+
var month = parseInt(tin.slice(2, 4), 10);
|
1156
|
+
if (month > 50) {
|
1157
|
+
month -= 50;
|
1158
|
+
}
|
1159
|
+
if (month < 10) {
|
1160
|
+
month = "0".concat(month);
|
1161
|
+
}
|
1162
|
+
|
1163
|
+
// Check date validity
|
1164
|
+
var date = "".concat(full_year, "/").concat(month, "/").concat(tin.slice(4, 6));
|
1165
|
+
if (!isDate(date, 'YYYY/MM/DD')) {
|
1166
|
+
return false;
|
1167
|
+
}
|
1168
|
+
}
|
1169
|
+
return true;
|
1170
|
+
}
|
1171
|
+
|
1172
|
+
/*
|
1173
|
+
* sl-SI validation function
|
1174
|
+
* (Davčna številka, persons/entities)
|
1175
|
+
* Verify TIN validity by calculating check (last) digit (variant of MOD 11)
|
1176
|
+
*/
|
1177
|
+
function slSiCheck(tin) {
|
1178
|
+
var checksum = 11 - algorithms.reverseMultiplyAndSum(tin.split('').slice(0, 7).map(function (a) {
|
1179
|
+
return parseInt(a, 10);
|
1180
|
+
}), 8) % 11;
|
1181
|
+
if (checksum === 10) {
|
1182
|
+
return parseInt(tin[7], 10) === 0;
|
1183
|
+
}
|
1184
|
+
return checksum === parseInt(tin[7], 10);
|
1185
|
+
}
|
1186
|
+
|
1187
|
+
/*
|
1188
|
+
* sv-SE validation function
|
1189
|
+
* (Personnummer or samordningsnummer, persons only)
|
1190
|
+
* Checks validity of birth date and calls luhnCheck() to validate check (last) digit
|
1191
|
+
*/
|
1192
|
+
function svSeCheck(tin) {
|
1193
|
+
// Make copy of TIN and normalize to two-digit year form
|
1194
|
+
var tin_copy = tin.slice(0);
|
1195
|
+
if (tin.length > 11) {
|
1196
|
+
tin_copy = tin_copy.slice(2);
|
1197
|
+
}
|
1198
|
+
|
1199
|
+
// Extract date of birth
|
1200
|
+
var full_year = '';
|
1201
|
+
var month = tin_copy.slice(2, 4);
|
1202
|
+
var day = parseInt(tin_copy.slice(4, 6), 10);
|
1203
|
+
if (tin.length > 11) {
|
1204
|
+
full_year = tin.slice(0, 4);
|
1205
|
+
} else {
|
1206
|
+
full_year = tin.slice(0, 2);
|
1207
|
+
if (tin.length === 11 && day < 60) {
|
1208
|
+
// Extract full year from centenarian symbol
|
1209
|
+
// Should work just fine until year 10000 or so
|
1210
|
+
var current_year = new Date().getFullYear().toString();
|
1211
|
+
var current_century = parseInt(current_year.slice(0, 2), 10);
|
1212
|
+
current_year = parseInt(current_year, 10);
|
1213
|
+
if (tin[6] === '-') {
|
1214
|
+
if (parseInt("".concat(current_century).concat(full_year), 10) > current_year) {
|
1215
|
+
full_year = "".concat(current_century - 1).concat(full_year);
|
1216
|
+
} else {
|
1217
|
+
full_year = "".concat(current_century).concat(full_year);
|
1218
|
+
}
|
1219
|
+
} else {
|
1220
|
+
full_year = "".concat(current_century - 1).concat(full_year);
|
1221
|
+
if (current_year - parseInt(full_year, 10) < 100) {
|
1222
|
+
return false;
|
1223
|
+
}
|
1224
|
+
}
|
1225
|
+
}
|
1226
|
+
}
|
1227
|
+
|
1228
|
+
// Normalize day and check date validity
|
1229
|
+
if (day > 60) {
|
1230
|
+
day -= 60;
|
1231
|
+
}
|
1232
|
+
if (day < 10) {
|
1233
|
+
day = "0".concat(day);
|
1234
|
+
}
|
1235
|
+
var date = "".concat(full_year, "/").concat(month, "/").concat(day);
|
1236
|
+
if (date.length === 8) {
|
1237
|
+
if (!isDate(date, 'YY/MM/DD')) {
|
1238
|
+
return false;
|
1239
|
+
}
|
1240
|
+
} else if (!isDate(date, 'YYYY/MM/DD')) {
|
1241
|
+
return false;
|
1242
|
+
}
|
1243
|
+
return algorithms.luhnCheck(tin.replace(/\W/, ''));
|
1244
|
+
}
|
1245
|
+
|
1246
|
+
/**
|
1247
|
+
* uk-UA validation function
|
1248
|
+
* Verify TIN validity by calculating check (last) digit (variant of MOD 11)
|
1249
|
+
*/
|
1250
|
+
function ukUaCheck(tin) {
|
1251
|
+
// Calculate check digit
|
1252
|
+
var digits = tin.split('').map(function (a) {
|
1253
|
+
return parseInt(a, 10);
|
1254
|
+
});
|
1255
|
+
var multipliers = [-1, 5, 7, 9, 4, 6, 10, 5, 7];
|
1256
|
+
var checksum = 0;
|
1257
|
+
for (var i = 0; i < multipliers.length; i++) {
|
1258
|
+
checksum += digits[i] * multipliers[i];
|
1259
|
+
}
|
1260
|
+
return checksum % 11 === 10 ? digits[9] === 0 : digits[9] === checksum % 11;
|
1261
|
+
}
|
1262
|
+
|
1263
|
+
// Locale lookup objects
|
1264
|
+
|
1265
|
+
/*
|
1266
|
+
* Tax id regex formats for various locales
|
1267
|
+
*
|
1268
|
+
* Where not explicitly specified in DG-TAXUD document both
|
1269
|
+
* uppercase and lowercase letters are acceptable.
|
1270
|
+
*/
|
1271
|
+
var taxIdFormat = {
|
1272
|
+
'bg-BG': /^\d{10}$/,
|
1273
|
+
'cs-CZ': /^\d{6}\/{0,1}\d{3,4}$/,
|
1274
|
+
'de-AT': /^\d{9}$/,
|
1275
|
+
'de-DE': /^[1-9]\d{10}$/,
|
1276
|
+
'dk-DK': /^\d{6}-{0,1}\d{4}$/,
|
1277
|
+
'el-CY': /^[09]\d{7}[A-Z]$/,
|
1278
|
+
'el-GR': /^([0-4]|[7-9])\d{8}$/,
|
1279
|
+
'en-CA': /^\d{9}$/,
|
1280
|
+
'en-GB': /^\d{10}$|^(?!GB|NK|TN|ZZ)(?![DFIQUV])[A-Z](?![DFIQUVO])[A-Z]\d{6}[ABCD ]$/i,
|
1281
|
+
'en-IE': /^\d{7}[A-W][A-IW]{0,1}$/i,
|
1282
|
+
'en-US': /^\d{2}[- ]{0,1}\d{7}$/,
|
1283
|
+
'es-AR': /(20|23|24|27|30|33|34)[0-9]{8}[0-9]/,
|
1284
|
+
'es-ES': /^(\d{0,8}|[XYZKLM]\d{7})[A-HJ-NP-TV-Z]$/i,
|
1285
|
+
'et-EE': /^[1-6]\d{6}(00[1-9]|0[1-9][0-9]|[1-6][0-9]{2}|70[0-9]|710)\d$/,
|
1286
|
+
'fi-FI': /^\d{6}[-+A]\d{3}[0-9A-FHJ-NPR-Y]$/i,
|
1287
|
+
'fr-BE': /^\d{11}$/,
|
1288
|
+
'fr-FR': /^[0-3]\d{12}$|^[0-3]\d\s\d{2}(\s\d{3}){3}$/,
|
1289
|
+
// Conforms both to official spec and provided example
|
1290
|
+
'fr-LU': /^\d{13}$/,
|
1291
|
+
'hr-HR': /^\d{11}$/,
|
1292
|
+
'hu-HU': /^8\d{9}$/,
|
1293
|
+
'it-IT': /^[A-Z]{6}[L-NP-V0-9]{2}[A-EHLMPRST][L-NP-V0-9]{2}[A-ILMZ][L-NP-V0-9]{3}[A-Z]$/i,
|
1294
|
+
'lv-LV': /^\d{6}-{0,1}\d{5}$/,
|
1295
|
+
// Conforms both to DG TAXUD spec and original research
|
1296
|
+
'mt-MT': /^\d{3,7}[APMGLHBZ]$|^([1-8])\1\d{7}$/i,
|
1297
|
+
'nl-NL': /^\d{9}$/,
|
1298
|
+
'pl-PL': /^\d{10,11}$/,
|
1299
|
+
'pt-BR': /(?:^\d{11}$)|(?:^\d{14}$)/,
|
1300
|
+
'pt-PT': /^\d{9}$/,
|
1301
|
+
'ro-RO': /^\d{13}$/,
|
1302
|
+
'sk-SK': /^\d{6}\/{0,1}\d{3,4}$/,
|
1303
|
+
'sl-SI': /^[1-9]\d{7}$/,
|
1304
|
+
'sv-SE': /^(\d{6}[-+]{0,1}\d{4}|(18|19|20)\d{6}[-+]{0,1}\d{4})$/,
|
1305
|
+
'uk-UA': /^\d{10}$/
|
1306
|
+
};
|
1307
|
+
// taxIdFormat locale aliases
|
1308
|
+
taxIdFormat['lb-LU'] = taxIdFormat['fr-LU'];
|
1309
|
+
taxIdFormat['lt-LT'] = taxIdFormat['et-EE'];
|
1310
|
+
taxIdFormat['nl-BE'] = taxIdFormat['fr-BE'];
|
1311
|
+
taxIdFormat['fr-CA'] = taxIdFormat['en-CA'];
|
1312
|
+
|
1313
|
+
// Algorithmic tax id check functions for various locales
|
1314
|
+
var taxIdCheck = {
|
1315
|
+
'bg-BG': bgBgCheck,
|
1316
|
+
'cs-CZ': csCzCheck,
|
1317
|
+
'de-AT': deAtCheck,
|
1318
|
+
'de-DE': deDeCheck,
|
1319
|
+
'dk-DK': dkDkCheck,
|
1320
|
+
'el-CY': elCyCheck,
|
1321
|
+
'el-GR': elGrCheck,
|
1322
|
+
'en-CA': isCanadianSIN,
|
1323
|
+
'en-IE': enIeCheck,
|
1324
|
+
'en-US': enUsCheck,
|
1325
|
+
'es-AR': esArCheck,
|
1326
|
+
'es-ES': esEsCheck,
|
1327
|
+
'et-EE': etEeCheck,
|
1328
|
+
'fi-FI': fiFiCheck,
|
1329
|
+
'fr-BE': frBeCheck,
|
1330
|
+
'fr-FR': frFrCheck,
|
1331
|
+
'fr-LU': frLuCheck,
|
1332
|
+
'hr-HR': hrHrCheck,
|
1333
|
+
'hu-HU': huHuCheck,
|
1334
|
+
'it-IT': itItCheck,
|
1335
|
+
'lv-LV': lvLvCheck,
|
1336
|
+
'mt-MT': mtMtCheck,
|
1337
|
+
'nl-NL': nlNlCheck,
|
1338
|
+
'pl-PL': plPlCheck,
|
1339
|
+
'pt-BR': ptBrCheck,
|
1340
|
+
'pt-PT': ptPtCheck,
|
1341
|
+
'ro-RO': roRoCheck,
|
1342
|
+
'sk-SK': skSkCheck,
|
1343
|
+
'sl-SI': slSiCheck,
|
1344
|
+
'sv-SE': svSeCheck,
|
1345
|
+
'uk-UA': ukUaCheck
|
1346
|
+
};
|
1347
|
+
// taxIdCheck locale aliases
|
1348
|
+
taxIdCheck['lb-LU'] = taxIdCheck['fr-LU'];
|
1349
|
+
taxIdCheck['lt-LT'] = taxIdCheck['et-EE'];
|
1350
|
+
taxIdCheck['nl-BE'] = taxIdCheck['fr-BE'];
|
1351
|
+
taxIdCheck['fr-CA'] = taxIdCheck['en-CA'];
|
1352
|
+
|
1353
|
+
// Regexes for locales where characters should be omitted before checking format
|
1354
|
+
var allsymbols = /[-\\\/!@#$%\^&\*\(\)\+\=\[\]]+/g;
|
1355
|
+
var sanitizeRegexes = {
|
1356
|
+
'de-AT': allsymbols,
|
1357
|
+
'de-DE': /[\/\\]/g,
|
1358
|
+
'fr-BE': allsymbols
|
1359
|
+
};
|
1360
|
+
// sanitizeRegexes locale aliases
|
1361
|
+
sanitizeRegexes['nl-BE'] = sanitizeRegexes['fr-BE'];
|
1362
|
+
|
1363
|
+
/*
|
1364
|
+
* Validator function
|
1365
|
+
* Return true if the passed string is a valid tax identification number
|
1366
|
+
* for the specified locale.
|
1367
|
+
* Throw an error exception if the locale is not supported.
|
1368
|
+
*/
|
1369
|
+
export default function isTaxID(str) {
|
1370
|
+
var locale = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'en-US';
|
1371
|
+
assertString(str);
|
1372
|
+
// Copy TIN to avoid replacement if sanitized
|
1373
|
+
var strcopy = str.slice(0);
|
1374
|
+
if (locale in taxIdFormat) {
|
1375
|
+
if (locale in sanitizeRegexes) {
|
1376
|
+
strcopy = strcopy.replace(sanitizeRegexes[locale], '');
|
1377
|
+
}
|
1378
|
+
if (!taxIdFormat[locale].test(strcopy)) {
|
1379
|
+
return false;
|
1380
|
+
}
|
1381
|
+
if (locale in taxIdCheck) {
|
1382
|
+
return taxIdCheck[locale](strcopy);
|
1383
|
+
}
|
1384
|
+
// Fallthrough; not all locales have algorithmic checks
|
1385
|
+
return true;
|
1386
|
+
}
|
1387
|
+
throw new Error("Invalid locale '".concat(locale, "'"));
|
1388
|
+
}
|