// NibblePoker - IBAN
// Author: Herwin Bozet (@NibblePoker)
// License: Public Domain (This code, except for the data)
// Sources:
// * https://www.swift.com/standards/data-standards/iban-international-bank-account-number (Updated December 2024)
/**
* Parent class extended by all IBAN-related errors.
*/
export class IbanError extends Error {}
export class UnknownIbanCountryError extends IbanError {}
export class IncorrectIbanLengthError extends IbanError {}
export class IncorrectIbanFormatError extends IbanError {}
export class InvalidIbanChecksumError extends IbanError {}
/**
* ...
* @param countryCode {string}
* @returns {boolean} `true` if the given country code is known to have IBAN, `false` otherwise.
*/
export function doesCountryHaveIban(countryCode) {
try {
return getCountrySpec(countryCode, true) !== null;
} catch (e) {
return false;
}
}
/**
*
* @param countryCode {string}
* @param errorOnUnknown {boolean}
* @returns {IbanSpecification|null} The desired specification, or `null` if none could be found.
* @throws TypeError If the given `countryCode` is `null`, `undefined`, or not a `string`.
* @throws Error If the given `countryCode` isn't exactly 2 characters long.
* @throws UnknownIbanCountryError If `errorOnNotFound` is set to `true`, and no linked IBAN specification could be found.
*/
export function getCountrySpec(countryCode, errorOnUnknown = false) {
if (countryCode === undefined || countryCode === null) {
throw new TypeError("The given countryCode is null or undefined !");
}
if (!(typeof countryCode === 'string' || countryCode instanceof String)) {
throw new TypeError("The given countryCode is not a string !");
}
if (countryCode.length !== 2) {
throw new Error(`The given countryCode '${countryCode}' isn't exactly 2 characters long !`);
}
let desiredSpec = countriesSpecs[countryCode];
if(desiredSpec === undefined || desiredSpec === null) {
if(errorOnUnknown) {
throw new UnknownIbanCountryError(`The given countryCode '${countryCode}' isn't linked to any IBAN specification !`);
}
return null;
} else {
return desiredSpec;
}
}
/**
* Calculates the checksum for a given `countryCode` and `bban`
* @param countryCode
* @param bban
* @returns {number}
*/
export function getIbanChecksumFromParts(countryCode, bban) {
if (countryCode === undefined || countryCode === null || bban === undefined || bban === null) {
throw new TypeError("The given countryCode or bban is null or undefined !");
}
if (!(typeof countryCode === 'string' || countryCode instanceof String) ||
!(typeof bban === 'string' || bban instanceof String)) {
throw new TypeError("The given countryCode or bban is not a string !");
}
let ibanStep1 = bban + countryCode + "00";
let ibanStep2 = "";
for (let iChar = 0; iChar < ibanStep1.length; iChar++) {
let charCode = ibanStep1.charCodeAt(iChar);
if(charCode <= 57 && charCode >= 48) {
// Numbers
//console.log(`NB - ${ibanStep1[iChar]} - ${charCode} - ${(charCode - 48)}`);
ibanStep2 += (charCode - 48).toString();
} else if(charCode <= 90 && charCode >= 65) {
// Uppercase letters
//console.log(`UC - ${ibanStep1[iChar]} - ${charCode} - ${(charCode - 55)}`);
ibanStep2 += (charCode - 55).toString();
} else if(charCode <= 122 && charCode >= 97) {
// Lowercase letters
//console.log(`LC - ${ibanStep1[iChar]} - ${charCode} - ${(charCode - 87)}`);
ibanStep2 += (charCode - 87).toString();
} else {
throw new IncorrectIbanFormatError(`The character at position '${iChar}' in '${ibanStep1}' is invalid !`)
}
}
//console.log(ibanStep1);
//console.log(ibanStep2);
//console.log(BigInt(ibanStep2));
// We cannot use the regular `number` type, the lack of precision will mess with the result.
//console.log(98n - (BigInt(ibanStep2) % 97n));
return Number(98n - (BigInt(ibanStep2) % 97n));
}
/**
*
* @param iban
* @returns {StandardIban}
* @throws TypeError If the given iban is `null`, `undefined`, or not a `string`.
* @throws IncorrectIbanLengthError If the given `iban` has an invalid length.
* @throws IncorrectIbanFormatError If the given `iban` didn't pass the regex and format checks.
*/
export function parseStandardIban(iban) {
if (iban === undefined || iban === null) {
throw new TypeError("The given iban is null or undefined !");
}
if (!(typeof iban === 'string' || iban instanceof String)) {
throw new TypeError("The given countryCode is not a string !");
}
if (iban.length <= 4) {
throw new IncorrectIbanLengthError(`The given iban '${iban}' has an invalid BBAN length !`);
}
/** @type {IbanSpecification} */
let countrySpec;
try {
countrySpec = getCountrySpec(iban.substring(0, 2), true);
} catch (e) {
throw new UnknownIbanCountryError(e.message);
}
// Quickly checking the regex, and extracting some groups for later if all goes well.
let ibanRegexResult = countrySpec.ibanRegex.exec(iban);
if(ibanRegexResult === undefined || ibanRegexResult === null) {
throw new IncorrectIbanFormatError(`The given IBAN '${iban}' didn't match the '${countrySpec.ibanRegex}' regex`);
}
let actualChecksum = getIbanChecksumFromParts(ibanRegexResult.groups["prefix"], ibanRegexResult.groups["bban"]);
if(actualChecksum !== parseInt(ibanRegexResult.groups["checksum"])) {
throw new InvalidIbanChecksumError(
`The IBAN's checksum is invalid, expected '${actualChecksum}', got '${ibanRegexResult.groups["checksum"]}' !`);
}
return new StandardIban(
ibanRegexResult.groups["prefix"],
ibanRegexResult.groups["bban"],
countrySpec
);
}
/**
* Models the most basic components required for an IBAN.
* This class should either be extended or used for quick-and-dirty checksum calculations.
*/
export class SimpleIban {
/** @type {string} */
countryCode;
/** @type {string} */
bban;
constructor(countryCode, bban) {
this.countryCode = countryCode;
this.bban = bban;
}
getChecksumNumber() {
return getIbanChecksumFromParts(this.countryCode, this.bban);
}
getChecksumString() {
return this.getChecksumNumber().toString().padStart(2, "0");
}
toString() {
return `${this.countryCode}${this.getChecksumString()}${this.bban}`;
}
}
export class StandardIban extends SimpleIban {
/** @type {IbanSpecification} */
relevantSpec;
constructor(countryCode, bban, relevantSpec) {
super(countryCode, bban);
this.relevantSpec = relevantSpec;
}
}
export const charsN = "0123456789";
export const charsA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
export const charsC = charsN + charsA;
export class IbanSpecification {
/**
* ISO-3166 Country Code
* @type {string}
*/
countryCode;
/** @type {string} */
countryName;
/** @type {number} */
ibanLength;
/** @type {string} */
ibanFormat;
/** @type {number} */
bbanLength;
/** @type {string} */
bbanFormat;
/** @type {RegExp} */
ibanRegex;
/** @type {boolean} */
isSepa;
/**
* @param countryCode {string}
* @param countryName {string}
* @param ibanLength {number}
* @param ibanFormat {string}
* @param bbanLength {number}
* @param bbanFormat {string}
* @param ibanRegex {RegExp}
* @param isSepa {boolean}
*/
constructor(countryCode, countryName, ibanLength, ibanFormat,
bbanLength, bbanFormat, ibanRegex, isSepa) {
this.countryCode = countryCode;
this.countryName = countryName;
this.ibanLength = ibanLength;
this.ibanFormat = ibanFormat;
this.bbanLength = bbanLength;
this.bbanFormat = bbanFormat;
this.ibanRegex = ibanRegex;
this.isSepa = isSepa;
}
/**
* Returns the Bank Identifier from the given IBAN.
* The Bank Identifier may or may not include the Branch Identifier.
* @param iban {string}
* @returns {string}
*/
getFormattedBankId(iban) {
return "";
}
/**
* @param iban {string}
* @returns {string}
*/
getFormattedBranchId(iban) {
return "";
}
/**
* Formats the IBAN by adding spaces and other characters where necessary.
* @param iban {string}
* @returns {string}
*/
getFormattedIban(iban) {
return iban.match(/.{1,4}/g).join(' ');
}
generateRandomBban(preferNumbers = false, preferLetters = false) {
let returnedBban = "";
let patternParts = ("_" + this.bbanFormat + "0").split("!");
for(let i = 0; i < patternParts.length; i++) {
let elementCount = parseInt(patternParts[i].substring(1));
if(elementCount === 0) {
continue;
}
let elementType = patternParts[i + 1].substring(0, 1);
let elementChoices;
switch(elementType) {
case 'n':
case 'N':
elementChoices = charsN;
break;
case 'c':
case 'C':
if(preferNumbers) {
elementChoices = charsN;
} else {
if(preferLetters) {
elementChoices = charsA;
} else {
elementChoices = charsC;
}
}
break;
case 'a':
case 'A':
elementChoices = charsA;
break;
}
if(elementChoices === undefined || elementChoices === null) {
throw new IncorrectIbanFormatError(
`The format '${this.bbanFormat}' contains an unhandled element type '${elementType}' !`)
}
for (let i = 0; i < elementCount; i++) {
returnedBban += elementChoices.charAt(Math.floor(Math.random() * elementChoices.length));
}
}
return returnedBban;
}
}
export const countriesSpecs = {
AD: new IbanSpecification(
"AD", 'Andorra',
24, "AD2!n4!n4!n12!c",
20, "4!n4!n12!c",
new RegExp(
"^(?AD)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{4})" +
"(?[0-9]{4})" +
"([0-9a-zA-Z]{12})" +
")$", "g"),
true
),
AE: new IbanSpecification(
"AE", 'United Arab Emirates (The)',
23, "AE2!n3!n16!n",
19, "3!n16!n",
new RegExp(
"^(?AE)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{3})" +
"([0-9]{16})" +
")$", "g"),
false
),
AL: new IbanSpecification(
"AL", 'Albania',
28, "AL2!n8!n16!c",
24, "8!n16!c",
new RegExp(
"^(?AL)" +
"(?[0-9]{2})" +
"(?" +
"(?" +
"[0-9]{3}" +
"(?[0-9]{4})" +
"[0-9]{1}" +
")" +
"([0-9a-zA-Z]{16})" +
")$", "g"),
false
// FIXME: Has a special bank id format "212-1100-9"
),
AT: new IbanSpecification(
"AT", 'Austria',
20, "AT2!n5!n11!n",
16, "5!n11!n",
new RegExp(
"^(?AT)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{5})" +
"([0-9]{11})" +
")$", "g"),
true
),
AZ: new IbanSpecification(
"AZ", 'Azerbaijan',
28, "AZ2!n4!a20!c",
24, "4!a20!c",
new RegExp(
"^(?AZ)" +
"(?[0-9]{2})" +
"(?" +
"(?[A-Z]{4})" +
"([0-9a-zA-Z]{20})" +
")$", "g"),
false
),
BA: new IbanSpecification(
"BA", 'Bosnia and Herzegovina',
20, "BA2!n3!n3!n8!n2!n",
16, "3!n3!n8!n2!n",
new RegExp(
"^(?BA)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{3})" +
"(?[0-9]{3})" +
"([0-9]{8})" +
"([0-9]{2})" +
")$", "g"),
false
),
BE: new IbanSpecification(
"BE", 'Belgium',
16, "BE2!n3!n7!n2!n",
12, "3!n7!n2!n",
new RegExp(
"^(?BE)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{3})" +
"([0-9]{7})" +
"([0-9]{2})" +
")$", "g"),
true
),
BG: new IbanSpecification(
"BG", 'Bulgaria',
22, "BG2!n4!a4!n2!n8!c",
18, "4!a4!n2!n8!c",
new RegExp(
"^(?BG)" +
"(?[0-9]{2})" +
"(?" +
"(?[A-Z]{4})" +
"(?[0-9]{4})" +
"([0-9]{2})" +
"([0-9a-zA-Z]{8})" +
")$", "g"),
true
),
BH: new IbanSpecification(
"BH", 'Bahrain',
22, "BH2!n4!a14!c",
18, "4!a14!c",
new RegExp(
"^(?BH)" +
"(?[0-9]{2})" +
"(?" +
"(?[A-Z]{4})" +
"([0-9a-zA-Z]{14})" +
")$", "g"),
false
),
BI: Object.assign(new IbanSpecification(
"BI", 'Burundi',
27, "BI2!n5!n5!n11!n2!n",
23, "5!n5!n11!n2!n",
new RegExp(
"^(?BI)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{5})" +
"(?[0-9]{5})" +
"([0-9]{11})" +
"([0-9]{2})" +
")$", "g"),
false
), {
getFormattedIban(iban) {
return [
iban.substring(0, 4),
iban.substring(4, 9),
iban.substring(9, 14),
iban.substring(14, 25),
iban.substring(25, 27),
].join(' ');
}
}),
BR: new IbanSpecification(
"BR", 'Brazil',
29, "BR2!n8!n5!n10!n1!a1!c",
25, "8!n5!n10!n1!a1!c",
new RegExp(
"^(?BR)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{8})" +
"(?[0-9]{5})" +
"([0-9]{10})" +
"([A-Z])" +
"([0-9a-zA-Z])" +
")$", "g"),
false
),
BY: new IbanSpecification(
"BY", 'Republic of Belarus\n',
28, "BY2!n4!c4!n16!c",
24, "4!c4!n16!c",
new RegExp(
"^(?BY)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9a-zA-Z]{4})" +
"([0-9]{4})" +
"([0-9a-zA-Z]{16})" +
")$", "g"),
false
),
CH: new IbanSpecification(
"CH", 'Switzerland',
21, "CH2!n5!n12!c",
17, "5!n12!c",
new RegExp(
"^(?CH)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{5})" +
"([0-9a-zA-Z]{12})" +
")$", "g"),
true
),
CR: new IbanSpecification(
"CR", 'Costa Rica',
22, "CR2!n4!n14!n",
18, "4!n14!n",
new RegExp(
"^(?CR)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{4})" +
"([0-9]{14})" +
")$", "g"),
false
),
CY: new IbanSpecification(
"CY", 'Cyprus',
28, "CY2!n3!n5!n16!c",
24, "3!n5!n16!c",
new RegExp(
"^(?CY)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{3})" +
"(?[0-9]{5})" +
"([0-9a-zA-Z]{16})" +
")$", "g"),
true
),
CZ: new IbanSpecification(
"CZ", 'Czech Republic',
24, "CZ2!n4!n6!n10!n\n",
20, "4!n6!n10!n",
new RegExp(
"^(?CZ)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{4})" +
"([0-9]{6})" +
"([0-9]{10})" +
")$", "g"),
true
),
DE: new IbanSpecification(
"DE", 'Germany',
22, "DE2!n8!n10!n\n",
18, "8!n10!n",
new RegExp(
"^(?DE)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{8})" +
"([0-9]{10})" +
")$", "g"),
true
),
DJ: new IbanSpecification(
"DJ", 'Djibouti',
27, "DJ2!n5!n5!n11!n2!n\n",
23, "5!n5!n11!n2!n\n",
new RegExp(
"^(?DJ)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{5})" +
"(?[0-9]{5})" +
"([0-9]{11})" +
"([0-9]{2})" +
")$", "g"),
false
),
DK: new IbanSpecification(
"DK", 'Denmark',
18, "DK2!n4!n9!n1!n",
14, "4!n9!n1!n",
new RegExp(
"^(?DK)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{4})" +
"([0-9]{9})" +
"([0-9])" +
")$", "g"),
true
),
DO: new IbanSpecification(
"DO", 'Dominican Republic',
28, "DO2!n4!c20!n",
24, "4!c20!n",
new RegExp(
"^(?DO)" +
"(?[0-9]{2})" +
"(?" +
"(?[A-Z]{4})" +
"([0-9]{20})" +
")$", "g"),
false
),
EE: new IbanSpecification(
"EE", 'Estonia',
20, "EE2!n2!n14!n",
16, "2!n14!n",
new RegExp(
"^(?EE)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{2})" +
"([0-9]{14})" +
")$", "g"),
true
),
EG: Object.assign(new IbanSpecification(
"EG", 'Egypt',
29, "EG2!n4!n4!n17!n",
25, "4!n4!n17!n",
new RegExp(
"^(?EG)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{4})" +
"(?[0-9]{4})" +
"([0-9]{17})" +
")$", "g"),
false
), {
getFormattedIban(iban) {
return iban;
}
}),
ES: new IbanSpecification(
"ES", 'Spain',
24, "4!n4!n1!n1!n10!n",
20, "ES2!n4!n4!n1!n1!n10!n",
new RegExp(
"^(?ES)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{4})" +
"(?[0-9]{4})" +
"([0-9])" +
"([0-9])" +
"([0-9]{10})" +
")$", "g"),
true
),
FI: new IbanSpecification(
"FI", 'Finland',
18, "3!n11!n",
14, "FI2!n3!n11!n",
new RegExp(
"^(?FI)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{3})" +
"([0-9]{11})" +
")$", "g"),
true
// FIXME: Includes AX
),
FK: new IbanSpecification(
"FK", 'Falkland Islands',
18, "2!a12!n",
14, "FK2!n2!a12!n",
new RegExp(
"^(?FK)" +
"(?[0-9]{2})" +
"(?" +
"(?[A-Z]{1})" +
"([0-9]{12})" +
")$", "g"),
false
),
FO: new IbanSpecification(
"FO", 'Faroe Islands',
18, "FO2!n4!n9!n1!n",
14, "4!n9!n1!n",
new RegExp(
"^(?FO)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{4})" +
"([0-9]{9})" +
"([0-9])" +
")$", "g"),
false
),
FR: new IbanSpecification(
"FR", 'France',
27, "FR2!n5!n5!n11!c2!n",
23, "5!n5!n11!c2!n",
new RegExp(
"^(?FR)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{5})" +
"([0-9]{5})" +
"([0-9a-zA-Z]{11})" +
"([0-9]{2})" +
")$", "g"),
true
// FIXME: Includes a ton of extra countries
),
GB: new IbanSpecification(
"GB", 'United Kingdom',
22, "GB2!n4!a6!n8!n",
18, "4!a6!n8!n",
new RegExp(
"^(?GB)" +
"(?[0-9]{2})" +
"(?" +
"(?[A-Z]{4})" +
"(?[0-9]{6})" +
"([0-9]{8})" +
")$", "g"),
true
// FIXME: Includes extra countries
),
GE: new IbanSpecification(
"GE", 'Georgia',
22, "GE2!n2!a16!n",
18, "2!a16!n",
new RegExp(
"^(?GE)" +
"(?[0-9]{2})" +
"(?" +
"(?[A-Z]{2})" +
"([0-9]{16})" +
")$", "g"),
false
),
GI: new IbanSpecification(
"GI", 'Gibraltar',
23, "GI2!n4!a15!c",
19, "4!a15!c",
new RegExp(
"^(?GI)" +
"(?[0-9]{2})" +
"(?" +
"(?[A-Z]{4})" +
"([0-9a-zA-Z]{15})" +
")$", "g"),
true
),
GL: new IbanSpecification(
"GL", 'Greenland',
18, "GL2!n4!n9!n1!n",
14, "4!n9!n1!n",
new RegExp(
"^(?GL)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{4})" +
"([0-9]{9})" +
"([0-9])" +
")$", "g"),
false
),
GR: new IbanSpecification(
"GR", 'Greece',
27, "GR2!n3!n4!n16!c",
23, "3!n4!n16!c",
new RegExp(
"^(?GR)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{3})" +
"(?[0-9]{4})" +
"([0-9a-zA-Z]{16})" +
")$", "g"),
true
),
GT: new IbanSpecification(
"GT", 'Guatemala',
28, "GT2!n4!c20!c",
24, "4!c20!c",
new RegExp(
"^(?GT)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9a-zA-Z]{4})" +
"([0-9a-zA-Z]{20})" +
")$", "g"),
false
),
HN: new IbanSpecification(
"HN", 'Honduras',
28, "HN2!n4!a20!n",
24, "4!a20!n",
new RegExp(
"^(?HN)" +
"(?[0-9]{2})" +
"(?" +
"(?[A-Z]{4})" +
"([0-9]{20})" +
")$", "g"),
false
),
HR: new IbanSpecification(
"HR", 'Croatia',
21, "HR2!n7!n10!n",
17, "7!n10!n",
new RegExp(
"^(?HR)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{7})" +
"([0-9]{10})" +
")$", "g"),
true
),
HU: new IbanSpecification(
"HU", 'Hungary',
28, "HU2!n3!n4!n1!n15!n1!n",
24, "3!n4!n1!n15!n1!n",
new RegExp(
"^(?HU)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{3})" +
"(?[0-9]{4})" +
"([0-9])" +
"([0-9]{15})" +
"([0-9])" +
")$", "g"),
true
),
IE: new IbanSpecification(
"IE", 'Ireland',
22, "IE2!n4!a6!n8!n",
18, "4!a6!n8!n",
new RegExp(
"^(?IE)" +
"(?[0-9]{2})" +
"(?" +
"(?[A-Z]{4})" +
"(?[0-9]{6})" +
"([0-9]{8})" +
")$", "g"),
true
),
IL: new IbanSpecification(
"IL", 'Israel',
23, "IL2!n3!n3!n13!n",
19, "3!n3!n13!n",
new RegExp(
"^(?IL)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{3})" +
"(?[0-9]{3})" +
"([0-9]{13})" +
")$", "g"),
false
),
IQ: new IbanSpecification(
"IQ", 'Iraq',
23, "IQ2!n4!a3!n12!n",
19, "4!a3!n12!n",
new RegExp(
"^(?IQ)" +
"(?[0-9]{2})" +
"(?" +
"(?[A-Z]{4})" +
"(?[0-9]{3})" +
"([0-9]{12})" +
")$", "g"),
false
),
IS: new IbanSpecification(
"IS", 'Iceland',
26, "IS2!n4!n2!n6!n10!n",
22, "4!n2!n6!n10!n",
new RegExp(
"^(?IS)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{2})" +
"(?[0-9]{2})" +
"([0-9]{2})" +
"([0-9]{6})" +
"([0-9]{10})" +
")$", "g"),
true
),
IT: new IbanSpecification(
"IT", 'Italy',
27, "IT2!n1!a5!n5!n12!c",
23, "1!a5!n5!n12!c",
new RegExp(
"^(?IT)" +
"(?[0-9]{2})" +
"(?" +
"([A-Z])" +
"(?[0-9]{5})" +
"(?[0-9]{5})" +
"([0-9a-zA-Z]{12})" +
")$", "g"),
true
),
JO: new IbanSpecification(
"JO", 'Jordan',
30, "JO2!n4!a4!n18!c",
26, "4!a4!n18!c",
new RegExp(
"^(?JO)" +
"(?[0-9]{2})" +
"(?" +
"([A-Z]{4})" +
"(?[0-9]{4})" +
"([0-9a-zA-Z]{18})" +
")$", "g"),
false
),
KW: new IbanSpecification(
"KW", 'Kuwait',
30, "KW2!n4!a22!c",
26, "4!a22!c",
new RegExp(
"^(?KW)" +
"(?[0-9]{2})" +
"(?" +
"(?[A-Z]{4})" +
"([0-9a-zA-Z]{22})" +
")$", "g"),
false
),
KZ: new IbanSpecification(
"KZ", 'Kazakhstan',
20, "KZ2!n3!n13!c",
16, "3!n13!c",
new RegExp(
"^(?KZ)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{3})" +
"([0-9a-zA-Z]{13})" +
")$", "g"),
false
),
LB: new IbanSpecification(
"LB", 'Lebanon',
28, "LB2!n4!n20!c",
24, "4!n20!c",
new RegExp(
"^(?LB)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{4})" +
"([0-9a-zA-Z]{20})" +
")$", "g"),
false
),
LC: new IbanSpecification(
"LC", 'Saint Lucia',
32, "LC2!n4!a24!c",
28, "4!a24!c",
new RegExp(
"^(?LC)" +
"(?[0-9]{2})" +
"(?" +
"(?[A-Z]{4})" +
"([0-9a-zA-Z]{24})" +
")$", "g"),
false
),
LI: new IbanSpecification(
"LI", 'Liechtenstein',
21, "LI2!n5!n12!c",
17, "5!n12!c",
new RegExp(
"^(?LI)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{5})" +
"([0-9a-zA-Z]{12})" +
")$", "g"),
true
),
LT: new IbanSpecification(
"LT", 'Lithuania',
20, "LT2!n5!n11!n",
16, "5!n11!n",
new RegExp(
"^(?LT)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{5})" +
"([0-9]{11})" +
")$", "g"),
true
),
LU: new IbanSpecification(
"LU", 'Luxembourg',
20, "LU2!n3!n13!c",
16, "3!n13!c",
new RegExp(
"^(?LU)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{3})" +
"([0-9a-zA-Z]{13})" +
")$", "g"),
true
),
LV: new IbanSpecification(
"LV", 'Latvia',
21, "LV2!n4!a13!c",
17, "4!a13!c",
new RegExp(
"^(?LV)" +
"(?[0-9]{2})" +
"(?" +
"(?[A-Z]{4})" +
"([0-9a-zA-Z]{13})" +
")$", "g"),
true
),
LY: new IbanSpecification(
"LY", 'Libya',
25, "LY2!n3!n3!n15!n",
21, "3!n3!n15!n",
new RegExp(
"^(?MC)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{3})" +
"(?[0-9]{3})" +
"([0-9]{15})" +
")$", "g"),
true
// FIXME: Has special format
),
MC: new IbanSpecification(
"MC", 'Monaco',
27, "MC2!n5!n5!n11!c2!n",
23, "5!n5!n11!c2!n",
new RegExp(
"^(?MC)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{5})" +
"(?[0-9]{5})" +
"([0-9a-zA-Z]{11})" +
"([0-9]{2})" +
")$", "g"),
true
),
MD: new IbanSpecification(
"MD", 'Moldova',
24, "MD2!n2!c18!c",
20, "2!c18!c",
new RegExp(
"^(?MD)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9a-zA-Z]{2})" +
"([0-9a-zA-Z]{18})" +
")$", "g"),
false
),
ME: new IbanSpecification(
"ME", 'Montenegro',
22, "ME2!n3!n13!n2!n",
18, "3!n13!n2!n",
new RegExp(
"^(?ME)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{3})" +
"([0-9]{13})" +
"([0-9]{2})" +
")$", "g"),
false
),
MK: new IbanSpecification(
"MK", 'Macedonia',
19, "MK2!n3!n10!c2!n",
15, "3!n10!c2!n",
new RegExp(
"^(?MK)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{3})" +
"([0-9a-zA-Z]{10})" +
"([0-9]{2})" +
")$", "g"),
false
),
MN: new IbanSpecification(
"MN", 'Mongolia',
20, "MN2!n4!n12!n",
16, "4!n12!n",
new RegExp(
"^(?MN)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{4})" +
"([0-9]{12})" +
")$", "g"),
false
),
MR: new IbanSpecification(
"MR", 'Mauritania',
27, "MR2!n5!n5!n11!n2!n",
23, "5!n5!n11!n2!n",
new RegExp(
"^(?MR)" +
"(?[0-9]{2})" +
"(?" +
"(?[0-9]{5})" +
"(?[0-9]{5})" +
"([0-9]{11})" +
"([0-9]{2})" +
")$", "g"),
false
),
MT: new IbanSpecification(
"MT", 'Malta',
31, "MT2!n4!a5!n18!c",
27, "4!a5!n18!c",
new RegExp(
"^(?MT)" +
"(?[0-9]{2})" +
"(?" +
"(?[A-Z]{4})" +
"(?[0-9]{5})" +
"([0-9a-zA-Z]{18})" +
")$", "g"),
true
),
MU: new IbanSpecification(
"MU", 'Mauritius',
30, "MU2!n4!a2!n2!n12!n3!n3!a",
26, "4!a2!n2!n12!n3!n3!a",
new RegExp(
"^(?