Skip to content

Instantly share code, notes, and snippets.

@monikaja
Forked from afgomez/validate_spanish_id.js
Created February 24, 2018 13:43
Show Gist options
  • Save monikaja/65438cc397119dc0ee0b6f96f44caeea to your computer and use it in GitHub Desktop.
Save monikaja/65438cc397119dc0ee0b6f96f44caeea to your computer and use it in GitHub Desktop.
Spanish DNI, CIF, NIE validator
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