-
-
Save monikaja/65438cc397119dc0ee0b6f96f44caeea to your computer and use it in GitHub Desktop.
Spanish DNI, CIF, NIE validator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const DNI_REGEX = /^(\d{8})([A-Z])$/; | |
const CIF_REGEX = /^([ABCDEFGHJKLMNPQRSUVW])(\d{7})([0-9A-J])$/; | |
const NIE_REGEX = /^[XYZ]\d{7,8}[A-Z]$/; | |
export class ValidateSpanishID { | |
public static validateID(str:string) { | |
if(!str){ | |
return null; | |
} | |
// Ensure upcase and remove whitespace | |
str = str.toUpperCase().trim(); | |
let valid = false; | |
let type = ValidateSpanishID.spainIdType( str ); | |
switch (type) { | |
case 'dni': | |
valid = ValidateSpanishID.validDNI( str ); | |
break; | |
case 'nie': | |
valid = ValidateSpanishID.validNIE( str ); | |
break; | |
case 'cif': | |
valid = ValidateSpanishID.validCIF( str ); | |
break; | |
default://unknown | |
valid = false; | |
break; | |
} | |
return { | |
type: type, | |
valid: valid | |
}; | |
}; | |
/** | |
* return | |
* @param {string} str | |
* @return {string} | |
*/ | |
public static spainIdType(str:string) { | |
if ( str.match( DNI_REGEX ) ) { | |
return 'dni'; | |
} | |
if ( str.match( CIF_REGEX ) ) { | |
return 'cif'; | |
} | |
if ( str.match( NIE_REGEX ) ) { | |
return 'nie'; | |
} | |
return 'unknown'; | |
}; | |
/** | |
* Validate dni format | |
* @param dni | |
* @return {boolean} | |
*/ | |
static validDNI( dni ):boolean { | |
if(!dni){ | |
return false; | |
} | |
dni = dni.toUpperCase(); | |
let dniLetters = "TRWAGMYFPDXBNJZSQVHLCKE"; | |
let letter = dniLetters.charAt( parseInt( dni.toUpperCase(), 10 ) % 23 ); | |
return letter === dni.charAt(8); | |
}; | |
/** | |
* Validate nie format | |
* @param nie | |
* @return {boolean} | |
*/ | |
static validNIE( nie ):boolean { | |
if(!nie){ | |
return false; | |
} | |
nie = nie.toUpperCase(); | |
// Change the initial letter for the corresponding number and validate as DNI | |
let niePrefix = nie.charAt( 0 ); | |
switch (niePrefix) { | |
case 'X': niePrefix = 0; break; | |
case 'Y': niePrefix = 1; break; | |
case 'Z': niePrefix = 2; break; | |
} | |
return this.validDNI( niePrefix + nie.substr(1) ); | |
}; | |
/** | |
* Validate cif format | |
* @param cif | |
* @return {boolean} | |
*/ | |
static validCIF( cif ):boolean { | |
if(!cif){ | |
return false; | |
} | |
cif = cif.toUpperCase(); | |
let match = cif.match( CIF_REGEX ); | |
if(match==null){ | |
return false; | |
} | |
let letter = match[1]; | |
let numberData = match[2]; | |
let control = match[3]; | |
let evenSum = 0; | |
let oddSum = 0; | |
let n; | |
for ( let i = 0; i < numberData.length; i++) { | |
n = parseInt( numberData[i], 10 ); | |
// Odd positions (Even index equals to odd position. i=0 equals first position) | |
if ( i % 2 === 0 ) { | |
// Odd positions are multiplied first. | |
n *= 2; | |
// If the multiplication is bigger than 10 we need to adjust | |
oddSum += n < 10 ? n : n - 9; | |
// Even positions | |
// Just sum them | |
} else { | |
evenSum += n; | |
} | |
} | |
//TsLint Error: "The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type." fixed in next line | |
let controlDigit = (10 - Number((evenSum + oddSum).toString().substr(-1))); | |
let controlLetter = 'JABCDEFGHI'.substr( controlDigit, 1 ); | |
// Control must be a digit | |
if ( letter.match( /[ABEH]/ ) ) { | |
return control === controlDigit; | |
// Control must be a letter | |
} else if ( letter.match( /[KPQS]/ ) ) { | |
return control === controlLetter; | |
// Can be either | |
} else { | |
return control === controlDigit || control === controlLetter; | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment