Regex Chinese 18-character identity number
National standard GB 11643-1999 defines an 18-character number: a 6-digit address code (administrative division, GB/T 2260), an 8-digit birth date YYYYMMDD, a 3-digit sequence number (odd for men, even for women) and an ISO 7064:1983 MOD 11-2 check character, 0 to 9 or 'X'. The three patterns read here do not list the provinces: validator.js checks the province list in code, not in the regex; django-localflavor even accepts old 15-digit numbers; validid accepts any date. Here's a pattern bounding province, month and day, compared against those attempts.
/^(?: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]$/passes 25/25 cases
Comparison of existing patterns
| Source | pattern | Score on the 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 | safe |
| 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 | safe |
| 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 | safe |
Implementation
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);Limits
- 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.