Regex numéro d'identité chinois à 18 caractères
La norme nationale GB 11643-1999 définit un numéro de 18 caractères : un code d'adresse de 6 chiffres (division administrative, norme GB/T 2260), une date de naissance de 8 chiffres AAAAMMJJ, un numéro d'ordre de 3 chiffres (impair pour un homme, pair pour une femme) et une clé en ISO 7064:1983 MOD 11-2, qui vaut 0 à 9 ou « X ». Les trois motifs relus ici ne listent pas les provinces : validator.js teste la liste des provinces dans le code, pas dans la regex ; django-localflavor accepte même les anciens numéros à 15 chiffres ; validid accepte n'importe quelle date. Voici un motif qui borne province, mois et jour, comparé à ces tentatives.
/^(?:1[1-5]|2[1-3]|3[1-7]|4[1-6]|5[0-4]|6[1-5]|71|8[12]|91)[0-9]{4}(?:18|19|20)[0-9]{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12][0-9]|3[01])[0-9]{3}[0-9X]$/passe 25/25 cas
Comparatif des patterns existants
| Source | pattern | Score sur le corpus | ReDoS |
|---|---|---|---|
| validator.js isIdentityCard('zh-CN'), regex de 18 chiffres — la province est contrôlée hors regex : « 99… » et « 10… » passent ; accepte « x » minuscule et les années 1000-9999 | ^[1-9]\d{5}[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}(\d|x|X)$ | 21 / 25 | sûr |
| django-localflavor (cn/forms.py) — accepte les anciens numéros à 15 chiffres, n'importe quel code de province et n'importe quelle date, « x » minuscule accepté | ^\d{15}(\d{2}[0-9xX])?$ | 16 / 25 | sûr |
| validid (npm), CNID_PATTERN — 17 chiffres et X : aucune borne sur la province, le mois ou le jour (« 11010120171310193X » passe) | ^[0-9]{17}[0-9X]$ | 18 / 25 | sûr |
Implémentation
const re = new RegExp("^(?:1[1-5]|2[1-3]|3[1-7]|4[1-6]|5[0-4]|6[1-5]|71|8[12]|91)[0-9]{4}(?:18|19|20)[0-9]{2}(?:0[1-9]|1[0-2])(?:0[1-9]|[12][0-9]|3[01])[0-9]{3}[0-9X]$", "");
re.test(input);Limites
- Valide seulement la FORME : ne calcule pas la clé MOD 11-2. La clé d'un exemple du corpus est volontairement fausse (… « 0 » à la place de la bonne) et passe quand même ; calculez la somme pondérée dans le code.
- Une date impossible mais de la bonne forme (30 février, jour 31 d'un mois de 30 jours) passe, et l'année est bornée à 1800-2099 seulement : le motif ne connaît pas le calendrier. Les 15 chiffres des anciens numéros (avant GB 11643-1999) sont refusés.
- Les codes de province viennent de la liste de validator.js, non vérifiée ici contre GB/T 2260 ; le code d'adresse complet à 6 chiffres n'est pas contrôlé (division administrative existante ou non). « X » doit être majuscule, comme dans la norme.
- Un numéro d'identité chinois porte la date de naissance et le sexe de son titulaire : donnée personnelle. N'utilisez que des numéros synthétiques, comme ceux du corpus.