Rexact
Cheatsheet

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

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.

Related pages