Regex personnummer suédois
Le personnummer s'écrit « 640823-3234 » (10 chiffres, tiret, ou « + » après 100 ans) ou en 12 chiffres avec le siècle. La clé est un Luhn calculé sur les 10 derniers chiffres seulement. Piège réel que j'ai reproduit : validator.js 13.15.35 applique le Luhn sur les 12 chiffres, donc l'exemple officiel de Skatteverket « 19640823-3234 » est rejeté tandis que « 19640823-3233 », clé fausse, est accepté. Les autres tentatives réelles se trompent sur le mois (13 passe), la longueur ou le numéro de série 000. Voici un motif qui borne mois et jours (samordningsnummer compris) et exclut la série 000, comparé à ces tentatives.
/^(?:(?:18|19|20)[0-9]{2}|[0-9]{2})(?:0[1-9]|1[0-2])(?:0[1-9]|[12][0-9]|3[01]|6[1-9]|[78][0-9]|9[01])[-+]?(?!000)[0-9]{3}[0-9]$/passe 26/26 cas
Comparatif des patterns existants
| Source | pattern | Score sur le corpus | ReDoS |
|---|---|---|---|
| validator.js (sv-SE) — forme large : mois 13, jour 00 et série 000 passent ; surtout, sa clé est calculée sur 12 chiffres, donc « 19640823-3234 » (exemple officiel) est rejeté et « 19640823-3233 » accepté | ^(\d{6}[-+]{0,1}\d{4}|(18|19|20)\d{6}[-+]{0,1}\d{4})$ | 21 / 26 | sûr |
| personnummer (npm, la plus utilisée) — exclut bien la série 000 et exige la clé, mais mois 13, jour 00 et jour 92 passent la regex ; la date et le Luhn sont validés ensuite dans le code | ^(\d{2}){0,1}(\d{2})(\d{2})(\d{2})([+-]?)((?!000)\d{3}|[TRSUWXJKLMN]\d{2})(\d)$ | 22 / 26 | sûr |
| Microsoft Presidio (détecteur de données personnelles) — « \d{6,8} » accepte 6, 7 ou 8 chiffres de date, donc un numéro à 11 chiffres passe ; non ancrée avec \b ; aucune contrainte de mois ni de jour | \b(\d{6,8})([-+]?)\d{4}\b | 20 / 26 | sûr |
Implémentation
const re = new RegExp("^(?:(?:18|19|20)[0-9]{2}|[0-9]{2})(?:0[1-9]|1[0-2])(?:0[1-9]|[12][0-9]|3[01]|6[1-9]|[78][0-9]|9[01])[-+]?(?!000)[0-9]{3}[0-9]$", "");
re.test(input);Limites
- Valide seulement la FORME : ne calcule pas la clé (Luhn sur les 10 derniers chiffres). « 640823-3235 » et « 880320-0018 » ont la bonne forme mais une clé fausse et passent ce motif ; seul un calcul dans le code les rejette. Ne valide pas non plus le jour dans le mois (« 640230-3231 », 30 février, passe).
- Le séparateur « + » (personne de plus de 100 ans) dépend de la date du jour : une regex ne peut pas savoir qu'un « 640823+3234 » est incohérent. Le motif accepte « + » ou « - » avec les deux formes de siècle.
- Les jours 61 à 91 (samordningsnummer, jour + 60) sont acceptés, ainsi que les 12 chiffres avec ou sans séparateur. Si vous ne gérez que les personnes enregistrées, restreignez le jour à 01-31. La série 000 est exclue (SKV 704 : 001 à 999).
- Le comportement de validator.js sur les 12 chiffres a été testé sur la version 13.15.35 : la bibliothèque a pu être corrigée depuis. N'utilisez pas de vrais numéros dans vos tests ; les exemples viennent de SKV 704, de python-stdnum et de jeux de tests publics.