import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'; /** * Expression validant strictement le format JJ/MM/AAAA * (2 chiffres / 2 chiffres / 4 chiffres). */ const FORMAT_JJ_MM_AAAA = /^(\d{2})\/(\d{2})\/(\d{4})$/; /** * Vérifie qu'une chaîne au format JJ/MM/AAAA correspond à une date réelle * (mois 1–12, jour cohérent avec le mois et l'année bissextile). * * @returns `true` si le format est correct ET la date existe, sinon `false`. */ export function estDateJjMmAAAAValide(valeur: string): boolean { const correspondance = FORMAT_JJ_MM_AAAA.exec(valeur); if (!correspondance) { return false; } const jour = Number(correspondance[1]); const mois = Number(correspondance[2]); const annee = Number(correspondance[3]); if (mois < 1 || mois > 12) { return false; } if (jour < 1) { return false; } // Nombre de jours du mois (tient compte des années bissextiles via Date). const joursDansMois = new Date(annee, mois, 0).getDate(); if (jour > joursDansMois) { return false; } return true; } /** * Validateur Angular pour un contrôle de date au format JJ/MM/AAAA. * * Retourne `{ dateInvalide: true }` si la valeur est présente mais mal formatée * ou correspond à une date inexistante (Exigence 1.5). Une valeur vide est * considérée valide ici : l'obligation de présence relève du validateur * `Validators.required`. */ export function dateJjMmAAAAValidator(): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { const valeur = control.value; // Champ vide : on laisse `required` gérer l'obligation. if (valeur === null || valeur === undefined || valeur === '') { return null; } if (typeof valeur !== 'string' || !estDateJjMmAAAAValide(valeur)) { return { dateInvalide: true }; } return null; }; }