verifiera
Version:
A JavaScript library to perform common operations on Personal Identification Numbers (Social Security Numbers), like: Validation, censoring the individual digits, calculating age and detecting gender.
618 lines (600 loc) • 22 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
/*!
* verifiera
* @license MIT
* Copyright (c) 2020 Milad Kawas CALE. All rights reserved.
*/
var calculateAge = function (birthday, today) {
var isLeapYear = function (year) {
var date = new Date(year, 1, 28);
date.setDate(date.getDate() + 1);
return date.getMonth() === 1;
};
var d = new Date(birthday);
var now = today ? new Date(today) : new Date();
var years = now.getFullYear() - d.getFullYear();
d.setFullYear(d.getFullYear() + years);
if (d > now) {
years -= 1;
d.setFullYear(d.getFullYear() - 1);
}
var days = (now.getTime() - d.getTime()) / (3600 * 24 * 1000);
var age = years + days / (isLeapYear(now.getFullYear()) ? 366 : 365);
return age > 0 ? Math.floor(age) : 0;
};
var validateDate = function (day, month, year) {
var date = new Date();
date.setFullYear(year, month - 1, day);
return date.getFullYear() === year &&
date.getMonth() + 1 === month &&
date.getDate() === day;
};
var clean = function (input) { return input.replace(/[^\d]/g, '')
.trim(); };
var calculateBitCheckSum = function (str, numbers) {
var cleaned = clean(str);
var sum = 0;
numbers.forEach(function (num, index) {
sum += num * parseInt(cleaned[index], 10);
});
return sum;
};
var validateBitCheckSum = function (personalNumber, numbers, mod) {
if (mod === void 0) { mod = 11; }
return calculateBitCheckSum(personalNumber, numbers) % mod === 0;
};
var reverseString = function (str) { return str.split('').reverse().join(''); };
var defaultGetAge = function () { return 0; };
var defaultGetBirthday = function () { return ''; };
var defaultGetCensored = function () { return ''; };
var defaultGetCountry = function () { return ''; };
var defaultGetGender = function () { return ''; };
var defaultGetYear = function () { return 0; };
var defaultIsCoordinationNo = function () { return false; };
var defaultIsDNumber = function () { return false; };
var defaultValidate = function () { return false; };
var getGenderFactory = function (parts) {
return function () {
return (parseInt(parts.gender, 10) % 2) === 0 ? 'f' : 'm';
};
};
var getBirthdayFactory = function (parts, getYear) {
return function () {
return getYear() + "-" + parts.month + "-" + parts.day;
};
};
var getAgeFactory = function (getBirthday) {
return function (today) {
if (today === void 0) { today = ''; }
return calculateAge(getBirthday(), today);
};
};
var validateFactory = function (personalNumber, regex, parts, getYear, localValidate) {
return function () {
return (personalNumber.length > 0 &&
regex.test(personalNumber) &&
validateDate(parseInt(parts.day, 10), parseInt(parts.month, 10), getYear()) &&
localValidate());
};
};
var defaultTools = function (extraTools) {
if (extraTools === void 0) { extraTools = {}; }
return __assign(__assign({ getAge: defaultGetAge, getBirthday: defaultGetBirthday, getCensored: defaultGetCensored, getCountry: defaultGetCountry, getGender: defaultGetGender, getYear: defaultGetYear }, extraTools), { validate: defaultValidate });
};
var czechSlovakia = function (personalNumber) {
var format = '^([0-9]{2})([0-9]{2})([0-9]{2})/([0-9]{3})([0-9])?$';
var regex = new RegExp(format);
var matches = regex.exec(personalNumber);
if (!matches) {
return defaultTools();
}
var getMonth = function () {
var month = parseInt(matches[2], 10);
if (month >= 51 && month <= 62) {
var newMonth = month - 50;
return (newMonth < 10 ? '0' : '') + newMonth.toString();
}
return matches[2];
};
var parts = {
day: matches[3],
month: getMonth(),
year: matches[1],
individualNumber: matches[4]
};
var getYear = function () {
var century = '19';
var year = parseInt(parts.year, 10);
if (personalNumber.length === 10 && year >= 54) {
century = '18';
}
else if (personalNumber.length === 11 && year < 54) {
century = '20';
}
return parseInt(century + parts.year, 10);
};
var localValidate = function () {
if (personalNumber.length === 10) {
return true;
}
var cleanedPersonalNumber = clean(personalNumber);
var oddNumbers = 0;
var evenNumbers = 0;
for (var i = 0; i < cleanedPersonalNumber.length; i++) {
var digit = parseInt(cleanedPersonalNumber[i], 10);
if ((i + 1) % 2 === 0) {
evenNumbers += digit;
}
else {
oddNumbers += digit;
}
}
return (oddNumbers - evenNumbers) % 11 === 0;
};
var validate = validateFactory(personalNumber, regex, parts, getYear, localValidate);
if (!validate()) {
return defaultTools();
}
var getBirthday = getBirthdayFactory(parts, getYear);
var getAge = getAgeFactory(getBirthday);
var getGender = function () {
var month = parseInt(matches[2], 10);
if (month >= 51 && month <= 62) {
return 'f';
}
return 'm';
};
var getCensored = function () { return "" + parts.year + matches[2] + parts.day + "/****"; };
var getCountry = function () { return 'czech_slovakia'; };
return {
getAge: getAge,
getBirthday: getBirthday,
getCensored: getCensored,
getCountry: getCountry,
getGender: getGender,
getYear: getYear,
validate: validate
};
};
var denmark = function (personalNumber, strict) {
if (strict === void 0) { strict = false; }
var format = '^([0-9]{2})([0-9]{2})([0-9]{2})-([0-9])([0-9]{2})([0-9])$';
var regex = new RegExp(format);
var matches = regex.exec(personalNumber);
if (!matches) {
return defaultTools();
}
var parts = {
day: matches[1],
month: matches[2],
year: matches[3],
centuryIndicator: matches[4],
individualNumber: matches[5],
gender: matches[6]
};
var getYear = function () {
var year = parseInt(parts.year, 10);
var inGroup1 = ['4', '9'].includes(parts.centuryIndicator);
var inGroup2 = ['5', '6', '7', '8'].includes(parts.centuryIndicator);
var century = '19';
if ((inGroup1 && year <= 36) || (inGroup2 && year <= 57)) {
century = '20';
}
else if (inGroup2 && year >= 58) {
century = '18';
}
return parseInt("" + century + parts.year, 10);
};
var localValidate = function () {
if (strict) {
return validateBitCheckSum(clean(personalNumber), [4, 3, 2, 7, 6, 5, 4, 3, 2, 1]);
}
return true;
};
var validate = validateFactory(personalNumber, regex, parts, getYear, localValidate);
if (!validate()) {
return defaultTools();
}
var getBirthday = getBirthdayFactory(parts, getYear);
var getAge = getAgeFactory(getBirthday);
var getGender = getGenderFactory(parts);
var getCensored = function () { return "" + parts.day + parts.month + parts.year + "-****"; };
var getCountry = function () { return 'denmark'; };
return {
getAge: getAge,
getBirthday: getBirthday,
getCensored: getCensored,
getCountry: getCountry,
getGender: getGender,
getYear: getYear,
validate: validate
};
};
var finland = function (personalNumber) {
var format = '^([0-9]{2})([0-9]{2})([0-9]{2})([-+A])([0-9]{3})([0-9A-Y])$';
var regex = new RegExp(format);
var matches = regex.exec(personalNumber);
if (!matches) {
return defaultTools();
}
var parts = {
day: matches[1],
month: matches[2],
year: matches[3],
centuryIndicator: matches[4],
individualNumber: matches[5],
checksum: matches[6],
gender: matches[5]
};
var getYear = function () {
var century = '19';
switch (parts.centuryIndicator) {
case '-':
century = '19';
break;
case '+':
century = '18';
break;
case 'A':
century = '20';
break;
}
return parseInt("" + century + parts.year, 10);
};
var localValidate = function () {
var controlCharacter = '0123456789ABCDEFHJKLMNPRSTUVWXY';
var num = parseInt("" + parts.day + parts.month + parts.year + parts.individualNumber, 10);
var remainder = num % 31;
return controlCharacter[remainder] === parts.checksum.toUpperCase();
};
var validate = validateFactory(personalNumber, regex, parts, getYear, localValidate);
if (!validate()) {
return defaultTools();
}
var getBirthday = getBirthdayFactory(parts, getYear);
var getAge = getAgeFactory(getBirthday);
var getGender = getGenderFactory(parts);
var getCensored = function () { return "" + parts.day + parts.month + parts.year + parts.centuryIndicator + "****"; };
var getCountry = function () { return 'finland'; };
return {
getAge: getAge,
getBirthday: getBirthday,
getCensored: getCensored,
getCountry: getCountry,
getGender: getGender,
getYear: getYear,
validate: validate
};
};
var netherlands = function (personalNumber) {
var format = '^([0-9]{9})$';
var regex = new RegExp(format);
var matches = regex.exec(personalNumber);
var validate = function () { return validateBitCheckSum(personalNumber, [9, 8, 7, 6, 5, 4, 3, 2, -1]); };
var result = defaultTools();
if (!matches || !validate()) {
return result;
}
result.validate = validate;
var getCensored = function () { return '*********'; };
var getCountry = function () { return 'netherlands'; };
result.getCensored = getCensored;
result.getCountry = getCountry;
return result;
};
var norway = function (personalNumber) {
var isDNumber = function () { return /^[4-7][0-9]{10}$/.test(personalNumber); };
var format = '^([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{3})([0-9])([0-9])$';
var regex = new RegExp(format);
var matches = regex.exec(personalNumber);
if (!matches) {
return defaultTools({ isDNumber: defaultIsDNumber });
}
var getDay = function () {
if (isDNumber()) {
var newDay = parseInt(matches[1], 10) - 40;
return (newDay < 10 ? '0' : '') + newDay.toString();
}
return matches[1];
};
var parts = {
day: getDay(),
month: matches[2],
year: matches[3],
individualNumber: matches[4],
gender: matches[4]
};
var getYear = function () {
var individualNumber = parseInt(parts.individualNumber, 10);
var year = parseInt(parts.year, 10);
var century = 19;
if (individualNumber > 499) {
if (individualNumber < 750 && year >= 54) {
century = 18;
}
else if (year < 40) {
century = 20;
}
else if (individualNumber >= 900 && year >= 40) {
century = 19;
}
}
return (century * 100) + year;
};
var localValidate = function () { return (validateBitCheckSum(personalNumber, [3, 7, 6, 1, 8, 9, 4, 5, 2, 1]) &&
validateBitCheckSum(personalNumber, [5, 4, 3, 2, 7, 6, 5, 4, 3, 2, 1])); };
var validate = validateFactory(personalNumber, regex, parts, getYear, localValidate);
if (!validate()) {
return defaultTools({ isDNumber: defaultIsDNumber });
}
var getBirthday = getBirthdayFactory(parts, getYear);
var getAge = getAgeFactory(getBirthday);
var getGender = getGenderFactory(parts);
var getCensored = function () { return "" + matches[1] + parts.month + parts.year + "*****"; };
var getCountry = function () { return 'norway'; };
return {
getAge: getAge,
getBirthday: getBirthday,
getCensored: getCensored,
getCountry: getCountry,
getGender: getGender,
getYear: getYear,
isDNumber: isDNumber,
validate: validate
};
};
var poland = function (personalNumber) {
var format = '^([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{3})([0-9])([0-9])$';
var regex = new RegExp(format);
var matches = regex.exec(personalNumber);
if (!matches) {
return defaultTools();
}
var getMonth = function () {
var month = parseInt(matches[2], 10);
var newMonth = month % 20;
return (newMonth < 10 ? '0' : '') + newMonth.toString();
};
var parts = {
day: matches[3],
month: getMonth(),
year: matches[1],
individualNumber: matches[4],
gender: matches[5],
checksum: matches[6]
};
var getYear = function () {
var month = parseInt(matches[2], 10);
var century = '19';
if (month < 20) {
century = '19';
}
else if (month > 20 && month < 33) {
century = '20';
}
else if (month > 40 && month < 53) {
century = '21';
}
else if (month > 60 && month < 73) {
century = '22';
}
return parseInt(century + parts.year, 10);
};
var localValidate = function () {
var numbers = [1, 3, 7, 9, 1, 3, 7, 9, 1, 3];
var sum = calculateBitCheckSum(personalNumber, numbers);
var modulo = sum % 10;
var tenthDigit = parseInt(personalNumber[10], 10);
return (modulo === 0 && tenthDigit === 0) || (tenthDigit === 10 - modulo);
};
var validate = validateFactory(personalNumber, regex, parts, getYear, localValidate);
if (!validate()) {
return defaultTools();
}
var getBirthday = getBirthdayFactory(parts, getYear);
var getAge = getAgeFactory(getBirthday);
var getGender = getGenderFactory(parts);
var getCensored = function () { return "" + parts.year + matches[2] + parts.day + "*****"; };
var getCountry = function () { return 'poland'; };
return {
getAge: getAge,
getBirthday: getBirthday,
getCensored: getCensored,
getCountry: getCountry,
getGender: getGender,
getYear: getYear,
validate: validate
};
};
var luhnChecksum = function (input) {
var num = reverseString(clean(input));
var total = 0;
for (var i = 0; i <= num.length - 1; i += 1) {
var val = parseInt(num[i], 10);
val = (i % 2 === 1) ? val * 2 : val;
if (val > 9) {
val -= 9;
}
total += val;
}
return total % 10;
};
var isLuhnValid = function (input) {
var num = clean(input);
return luhnChecksum(num) === 0;
};
var sweden = function (personalNumber, strict) {
if (strict === void 0) { strict = true; }
var dayLocation = strict ? 3 : 4;
var format = '^([0-9]{2})([0-9]{2})([0-9]{2})([-+])([0-9]{3})([0-9])$';
if (!strict) {
format = '^(18|19|20)?([0-9]{2})([0-9]{2})([0-9]{2})([-+])?([0-9]{3})([0-9])$';
}
var regex = new RegExp(format);
var matches = regex.exec(personalNumber);
if (!matches) {
return defaultTools({ isCoordinationNo: defaultIsCoordinationNo });
}
var getDay = function () {
var day = parseInt(matches[dayLocation], 10);
if (day >= 61) {
var newDay = day - 60;
return (newDay <= 9 ? '0' : '') + newDay.toString();
}
return matches[dayLocation];
};
var parts = {
centuryIndicator: '',
day: getDay(),
month: matches[2],
year: matches[1],
separator: matches[4],
individualNumber: matches[5],
gender: matches[5],
checksum: matches[6]
};
if (!strict) {
parts = {
centuryIndicator: matches[1] || '',
day: getDay(),
month: matches[3],
year: matches[2],
separator: matches[5] || '',
individualNumber: matches[6],
gender: matches[6],
checksum: matches[7]
};
}
var isCoordinationNo = function () { return ['6', '7', '8', '9'].includes(matches[dayLocation][0]); };
var getYear = function () {
if (!strict && parts.centuryIndicator) {
return parseInt("" + parts.centuryIndicator + parts.year, 10);
}
var birthday = parts.year + "-" + parts.month + "-" + parts.day;
var todayObj = new Date();
var century = '19';
if (todayObj < new Date("20" + birthday)) {
century = '19';
}
else if (todayObj >= new Date("20" + birthday) && parts.separator === '-') {
century = '20';
}
else if (todayObj >= new Date("19" + birthday) && parts.separator === '+') {
century = '19';
}
return parseInt("" + century + parts.year, 10);
};
var localValidate = function () { return isLuhnValid(personalNumber); };
if (!strict && parts.centuryIndicator) {
localValidate = function () { return isLuhnValid(personalNumber.replace(new RegExp("^" + parts.centuryIndicator), '')); };
}
var validate = validateFactory(personalNumber, regex, parts, getYear, localValidate);
if (!validate()) {
return defaultTools({ isCoordinationNo: defaultIsCoordinationNo });
}
var getBirthday = getBirthdayFactory(parts, getYear);
var getAge = getAgeFactory(getBirthday);
var getGender = getGenderFactory(parts);
var getCensored = function () {
if (!strict) {
return "" + parts.centuryIndicator + parts.year + parts.month + matches[4] + parts.separator + "****";
}
return "" + parts.year + parts.month + matches[3] + parts.separator + "****";
};
var getCountry = function () { return 'sweden'; };
return {
getAge: getAge,
getBirthday: getBirthday,
getCensored: getCensored,
getCountry: getCountry,
getGender: getGender,
getYear: getYear,
isCoordinationNo: isCoordinationNo,
validate: validate
};
};
var countries = [
czechSlovakia,
denmark,
finland,
netherlands,
norway,
poland,
sweden
];
var detectCountry = function (personalNumber) {
for (var _i = 0, countries_1 = countries; _i < countries_1.length; _i++) {
var country = countries_1[_i];
if (country.length === 1) {
var detector = country(personalNumber);
if (detector.validate()) {
return detector.getCountry();
}
}
else if (country.length === 2) {
var detector1 = country(personalNumber, true);
var detector2 = country(personalNumber, false);
if (detector1.validate()) {
return detector1.getCountry();
}
if (detector2.validate()) {
return detector2.getCountry();
}
}
}
return '';
};
var getCountryTools = function (personalNumber) {
for (var _i = 0, countries_2 = countries; _i < countries_2.length; _i++) {
var country = countries_2[_i];
if (country.length === 1) {
var detector = country(personalNumber);
if (detector.validate()) {
return detector;
}
}
else if (country.length === 2) {
var detector1 = country(personalNumber, true);
var detector2 = country(personalNumber, false);
if (detector1.validate()) {
return detector1;
}
if (detector2.validate()) {
return detector2;
}
}
}
return defaultTools();
};
exports.czechSlovakia = czechSlovakia;
exports.denmark = denmark;
exports.detectCountry = detectCountry;
exports.finland = finland;
exports.getCountryTools = getCountryTools;
exports.netherlands = netherlands;
exports.norway = norway;
exports.poland = poland;
exports.sweden = sweden;