sl-nic-utils
Version:
Sri Lanka NIC Utilities - An adaptable npm package designed to validate NIC numbers, determine the NIC format, convert between OLD and NEW formats, and extract detailed information from Sri Lanka National Identity Card (NIC) numbers.
144 lines (140 loc) • 4.97 kB
JavaScript
;
const nicPattern = /^(?:\d{9}[VvXx]|(?:\d{12}))$/;
const daysCount = [
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335,
];
const suffixLetter = 'V';
const timezone = '+05:30'; // Asia/Colombo
const getYear = (nic) => parseInt(nic.length == 10 ? '19' + nic.slice(0, 2) : nic.slice(0, 4));
const getDays = (nic) => parseInt(nic.length == 10 ? nic.slice(2, 5) : nic.slice(4, 7));
const getGender = (days) => (days > 500 ? 'Female' : 'Male');
const getModifiedDays = (days) => days > 500 ? days - 500 : days;
const getDate = (modifiedDays) => {
for (let i = 12; i > 1; i--) {
const conDays = daysCount[i - 1];
if (modifiedDays > conDays) {
return {
month: i,
day: modifiedDays - conDays,
};
}
}
return {
month: 1,
day: modifiedDays,
};
};
/**
* Represents a birthday with year, month, and date.
*/
class Birthday {
/**
* Creates a new instance of the Birthday class.
* @param year - The year of the birthday.
* @param month - The month of the birthday.
* @param date - The date of the birthday.
*/
constructor(year, month, date) {
this.year = year;
this.month = month;
this.date = date;
}
/**
* Returns a string representation of the birthday in the format "YYYY/MM/DD".
* @returns The string representation of the birthday.
*/
toString() {
return `${this.year}/${this.month}/${this.date}`;
}
/**
* Returns a Date object representing the birthday.
* @returns The Date object representing the birthday.
*/
toDate() {
return new Date(`${this.year}-${this.month.toString().padStart(2, '0')}-${this.date
.toString()
.padStart(2, '0')}T12:00:00${timezone}`);
}
}
/**
* Represents a NIC (National Identity Card) number.
*/
class NIC {
/**
* Creates a new instance of the NIC class.
* @param nic - The NIC number as a string.
* @throws {TypeError} If the provided NIC is not a string.
*/
constructor(nic) {
if (typeof nic !== 'string')
throw new TypeError('NIC must be a string');
this.nic = nic;
}
/**
* Checks if the NIC number is valid.
* @returns {boolean} True if the NIC number is valid, false otherwise.
*/
get isValid() {
if (!nicPattern.test(this.nic))
return false;
const modifiedDays = getModifiedDays(getDays(this.nic));
return !(modifiedDays < 1 || modifiedDays > 366);
}
/**
* Gets the type of the NIC number.
* @returns {NicType} The type of the NIC number.
* @throws {Error} If the NIC number is invalid.
*/
get type() {
if (!this.isValid)
throw new Error('Invalid NIC number');
return this.nic.length == 10 ? 'OLD' : 'NEW';
}
/**
* Gets the gender associated with the NIC number.
* @returns {NicGender} The gender associated with the NIC number.
* @throws {Error} If the NIC number is invalid.
*/
get gender() {
if (!this.isValid)
throw new Error('Invalid NIC number');
return getGender(getDays(this.nic));
}
/**
* Gets the birthday associated with the NIC number.
* @returns {Birthday} The birthday associated with the NIC number.
* @throws {Error} If the NIC number is invalid.
*/
get birthday() {
if (!this.isValid)
throw new Error('Invalid NIC number');
const modifiedDays = getModifiedDays(getDays(this.nic));
const { month, day } = getDate(modifiedDays);
const year = getYear(this.nic);
return new Birthday(year, month, day);
}
/**
* Formats the NIC number to the specified target type.
* @param targetType - The target type to format the NIC number to. Defaults to the current type.
* @returns {string} The formatted NIC number.
* @throws {TypeError} If the targetType is not a string or is not 'OLD' or 'NEW'.
* @throws {Error} If the targetType is 'OLD' and the NIC number is not valid for an old NIC.
*/
format(targetType = this.type) {
if (typeof targetType !== 'string' || !['OLD', 'NEW'].includes(targetType))
throw new TypeError('targetType must be a string and it must be either OLD or NEW');
if (targetType === this.type)
return this.nic.toUpperCase();
const year = getYear(this.nic);
if (targetType == 'OLD' && (year >= 2000 || this.nic[7] !== '0'))
throw new Error('Invalid request');
const days = getDays(this.nic);
const suffix = this.type == 'OLD'
? this.nic.slice(5, 9)
: this.nic.slice(8) + suffixLetter;
return targetType == 'OLD'
? `${year.toString().slice(2)}${days}${suffix}`
: `${year}${days}0${suffix}`;
}
}
module.exports = NIC;