ci-validation
Version:
šŗš¾ Complete TypeScript/JavaScript library for validating Uruguayan CI (CĆ©dula de Identidad) with official algorithm and government service integration
172 lines ⢠7.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DateUtils = void 0;
/**
* Utilidades para el manejo de fechas de nacimiento
*/
class DateUtils {
/**
* Convierte string de fecha de nacimiento a objeto Date
* @param fechaString - Fecha en formato string (ej: "DD/MM/YYYY", "YYYY-MM-DD", etc.)
* @returns Date object o null si no se puede parsear
*/
static parseFechaNacimiento(fechaString) {
if (!fechaString || typeof fechaString !== "string") {
return null;
}
try {
// Limpiar la fecha de espacios y caracteres extraƱos
const fechaLimpia = fechaString.trim();
// Intentar diferentes formatos comunes
const formatosComunes = [
/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/, // DD/MM/YYYY o D/M/YYYY
/^(\d{4})-(\d{1,2})-(\d{1,2})$/, // YYYY-MM-DD
/^(\d{1,2})-(\d{1,2})-(\d{4})$/, // DD-MM-YYYY
];
// Formato DD/MM/YYYY
const matchDDMMYYYY = fechaLimpia.match(formatosComunes[0]);
if (matchDDMMYYYY) {
const [, dia, mes, aƱo] = matchDDMMYYYY;
const diaNum = parseInt(dia);
const mesNum = parseInt(mes);
const aƱoNum = parseInt(aƱo);
// Validar rangos antes de crear la fecha
if (!this.validarRangosFecha(diaNum, mesNum, aƱoNum)) {
return null;
}
const fecha = new Date(aƱoNum, mesNum - 1, diaNum);
return this.validarFecha(fecha, diaNum, mesNum, aƱoNum) ? fecha : null;
}
// Formato YYYY-MM-DD
const matchYYYYMMDD = fechaLimpia.match(formatosComunes[1]);
if (matchYYYYMMDD) {
const [, aƱo, mes, dia] = matchYYYYMMDD;
const diaNum = parseInt(dia);
const mesNum = parseInt(mes);
const aƱoNum = parseInt(aƱo);
// Validar rangos antes de crear la fecha
if (!this.validarRangosFecha(diaNum, mesNum, aƱoNum)) {
return null;
}
const fecha = new Date(aƱoNum, mesNum - 1, diaNum);
return this.validarFecha(fecha, diaNum, mesNum, aƱoNum) ? fecha : null;
}
// Formato DD-MM-YYYY
const matchDDMMYYYYGuion = fechaLimpia.match(formatosComunes[2]);
if (matchDDMMYYYYGuion) {
const [, dia, mes, aƱo] = matchDDMMYYYYGuion;
const diaNum = parseInt(dia);
const mesNum = parseInt(mes);
const aƱoNum = parseInt(aƱo);
// Validar rangos antes de crear la fecha
if (!this.validarRangosFecha(diaNum, mesNum, aƱoNum)) {
return null;
}
const fecha = new Date(aƱoNum, mesNum - 1, diaNum);
return this.validarFecha(fecha, diaNum, mesNum, aƱoNum) ? fecha : null;
}
// Intentar parseo directo como Ćŗltimo recurso
const fechaDirecta = new Date(fechaLimpia);
return this.validarFecha(fechaDirecta) ? fechaDirecta : null;
}
catch (error) {
console.warn("Error parseando fecha de nacimiento:", error);
return null;
}
}
/**
* Valida rangos bĆ”sicos de dĆa, mes y aƱo antes de crear la fecha
* @param dia - DĆa del mes (1-31)
* @param mes - Mes (1-12)
* @param aƱo - AƱo (1900-actual)
* @returns true si los rangos son vƔlidos
*/
static validarRangosFecha(dia, mes, aƱo) {
// Validar rangos bƔsicos
if (dia < 1 || dia > 31)
return false;
if (mes < 1 || mes > 12)
return false;
const aƱoActual = new Date().getFullYear();
if (aƱo < 1900 || aƱo > aƱoActual)
return false;
return true;
}
/**
* Valida que una fecha sea vƔlida y razonable para fecha de nacimiento
* Verifica que la fecha creada corresponda exactamente a los valores originales
* @param fecha - Fecha a validar
* @param diaOriginal - DĆa original ingresado (opcional)
* @param mesOriginal - Mes original ingresado (opcional)
* @param aƱoOriginal - AƱo original ingresado (opcional)
* @returns true si la fecha es vƔlida
*/
static validarFecha(fecha, diaOriginal, mesOriginal, aƱoOriginal) {
// Verificar que es una fecha vƔlida
if (isNaN(fecha.getTime())) {
return false;
}
// Si se proporcionan valores originales, verificar que la fecha creada sea exactamente igual
if (diaOriginal !== undefined && mesOriginal !== undefined && aƱoOriginal !== undefined) {
if (fecha.getDate() !== diaOriginal || fecha.getMonth() !== mesOriginal - 1 || fecha.getFullYear() !== aƱoOriginal) {
return false; // La fecha fue normalizada por JavaScript, lo que indica valores invƔlidos
}
}
const aƱo = fecha.getFullYear();
const aƱoActual = new Date().getFullYear();
// Validar rango razonable (entre 1900 y aƱo actual)
if (aƱo < 1900 || aƱo > aƱoActual) {
return false;
}
// Verificar que no sea fecha futura
if (fecha > new Date()) {
return false;
}
return true;
}
/**
* Calcula la edad en aƱos basada en la fecha de nacimiento
* @param fechaNacimiento - Fecha de nacimiento
* @returns Edad en aƱos
*/
static calcularEdad(fechaNacimiento) {
const hoy = new Date();
let edad = hoy.getFullYear() - fechaNacimiento.getFullYear();
// Ajustar si el cumpleaños aún no ha ocurrido este año
const mesActual = hoy.getMonth();
const diaActual = hoy.getDate();
const mesNacimiento = fechaNacimiento.getMonth();
const diaNacimiento = fechaNacimiento.getDate();
if (mesActual < mesNacimiento || (mesActual === mesNacimiento && diaActual < diaNacimiento)) {
edad--;
}
return edad;
}
/**
* Procesa una fecha de nacimiento string y retorna la fecha Date y la edad
* @param fechaString - Fecha en formato string
* @returns Objeto con fecha Date y edad, o null si no se puede procesar
*/
static procesarFechaNacimiento(fechaString) {
if (!fechaString) {
return null;
}
try {
const fechaDate = this.parseFechaNacimiento(fechaString);
if (!fechaDate) {
return null;
}
const edad = this.calcularEdad(fechaDate);
return {
fechaDate,
edad,
};
}
catch (error) {
console.warn("Error procesando fecha de nacimiento:", error);
return null;
}
}
}
exports.DateUtils = DateUtils;
//# sourceMappingURL=dateUtils.js.map