Rexact
Cheatsheet

Regex numéro de TVA italien (partita IVA)

La partita IVA italienne compte 11 chiffres : 7 chiffres de matricule, 3 chiffres de code de l'ufficio qui a attribué le numéro, puis une clé de type Luhn définie par le décret ministériel du 23 décembre 1976. Le code de l'ufficio correspond à une province : 001 à 100, 120 et 121, plus 888 (franchise) et 999 (non-résidents identifiés en Italie). La FAQ VIES de la Commission publie seulement « IT + 11 chiffres », et les trois implémentations de TVA relues (validator.js, jsvat, valvat) ne contrôlent que cela, comme la regex unique du Regular Expressions Cookbook : « IT12345670009 » (code 000) ou « IT12345678895 » (code 889) passent. Voici un motif qui borne le code d'ufficio et refuse un matricule nul, comparé à ces tentatives.

/^IT(?!0{7})[0-9]{7}(?:00[1-9]|0[1-9][0-9]|100|12[01]|888|999)[0-9]$/
passe 29/29 cas

Comparatif des patterns existants

SourcepatternScore sur le corpusReDoS
validator.js (isVAT) — préfixe « IT » facultatif (« 07643520567 » nu passe) ; code d'ufficio non borné : « IT12345670009 » (code 000) passe^(IT)?\d{11}$20 / 29sûr
jsvat (italy.ts) — ancrée, préfixe obligatoire, mais la regex ne borne pas le code d'ufficio (le calcul de calcFn le fait à part, jusqu'à 201) : « IT12345670009 » (code 000) et un matricule nul passent^(IT)(\d{11})$21 / 29sûr
valvat (syntax.rb, A et Z remplacés par ^ et $) — ancrée, préfixe obligatoire, mais « IT12345670009 » (code 000) et un matricule nul passent^IT[0-9]{11}$21 / 29sûr
Regular Expressions Cookbook, recette 4.21 (27 pays en une regex, insensible à la casse) — préfixe facultatif, minuscules acceptées (« it07643520567 »), « FR07643520567 » passe (lu comme une TVA française) et le code d'ufficio n'est pas borné^((AT)?U[0-9]{8}|(BE)?0[0-9]{9}|(BG)?[0-9]{9,10}|(CY)?[0-9]{8}L|(CZ)?[0-9]{8,10}|(DE)?[0-9]{9}|(DK)?[0-9]{8}|(EE)?[0-9]{9}|(EL|GR)?[0-9]{9}|(ES)?[0-9A-Z][0-9]{7}[0-9A-Z]|(FI)?[0-9]{8}|(FR)?[0-9A-Z]{2}[0-9]{9}|(GB)?([0-9]{9}([0-9]{3})?|[A-Z]{2}[0-9]{3})|(HU)?[0-9]{8}|(IE)?[0-9]S[0-9]{5}L|(IT)?[0-9]{11}|(LT)?([0-9]{9}|[0-9]{12})|(LU)?[0-9]{8}|(LV)?[0-9]{11}|(MT)?[0-9]{8}|(NL)?[0-9]{9}B[0-9]{2}|(PL)?[0-9]{10}|(PT)?[0-9]{9}|(RO)?[0-9]{2,10}|(SE)?[0-9]{12}|(SI)?[0-9]{8}|(SK)?[0-9]{10})$18 / 29sûr

Implémentation

const re = new RegExp("^IT(?!0{7})[0-9]{7}(?:00[1-9]|0[1-9][0-9]|100|12[01]|888|999)[0-9]$", "");
re.test(input);

Limites

  • Valide seulement la FORME : « IT12345670018 » a un code d'ufficio valide mais une clé Luhn fausse et passe ce motif. La clé (décret du 23 décembre 1976) n'est pas recalculée par la regex.
  • La liste des codes d'ufficio (001-100, 120, 121, 888, 999) vient de it.wikipedia et de python-stdnum ; jsvat tolère jusqu'à 201. Si l'administration ajoutait un code, ce motif le refuserait : à relire régulièrement.
  • Le code fiscal d'une personne physique (16 caractères) n'est pas une partita IVA, et un code fiscal de société peut ressembler à une partita IVA : voir la fiche codice-fiscale. Aucune vérification d'existence (VIES).
  • Pas de tolérance pour les espaces ou minuscules ; normalisez avant validation. Les numéros du corpus sont des exemples de documentation ou synthétiques.

Pages liées