Skip to content

Instantly share code, notes, and snippets.

@gerardorochin
Created June 6, 2013 00:00
Show Gist options
  • Star 36 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save gerardorochin/5718313 to your computer and use it in GitHub Desktop.
Save gerardorochin/5718313 to your computer and use it in GitHub Desktop.
Expresion regular para validar RFC
/^([A-Z,Ñ,&]{3,4}([0-9]{2})(0[1-9]|1[0-2])(0[1-9]|1[0-9]|2[0-9]|3[0-1])[A-Z|\d]{3})$/
@unjordi
Copy link

unjordi commented Dec 10, 2016

^([A-ZÑ\x26]{3,4}([0-9]{2})(0[1-9]|1[0-2])(0[1-9]|1[0-9]|2[0-9]|3[0-1]))([A-Z\d]{3})?$
Cuales son las ventajas de esta regex en comparacion con la que está en xsd del sat:

Permite el ingreso del caracter ampersand (&) correctamente.
Valida desde 00 hasta 99 años
Valida meses de 01 a 12
Valida dias de 01 a 31
Opcional el ingreso de la homoclave.

Desarrollada por InvoiceOne.com.mx

encontrada en http://validacfd.com/phpbb3/viewtopic.php?t=1978

@lenriqueotero
Copy link

^([A-ZÑ\x26]{3,4}([0-9]{2})(0[1-9]|1[0-2])(0[1-9]|1[0-9]|2[0-9]|3[0-1]))((-)?([A-Z\d]{3}))?$

Basado en el que publicó @unjordi

Mucha gente escribe un guión entre el rfc y la homoclave

Valida:
ORP830422DI6
ORP830422-DI6
ORP830422

@suuperjeivier
Copy link

suuperjeivier commented Apr 25, 2018

según un documento publicado por el SAT, hay ciertas consideraciones, tanto los 2 dígitos de la homonimia, como el dígito verificador que solo tiene 3 opciones, una de ellas es que solo puede ser la letra A.
en fin, anexo el regex que actualmente utilizo en 2018
'^([A-ZÑ\x26]{3,4}([0-9]{2})(0[1-9]|1[0-2])(0[1-9]|1[0-9]|2[0-9]|3[0-1])([A-Z]|[0-9]){2}([A]|[0-9]){1})?$';

@MValenciaO
Copy link

las empresas utilizan rfc solamente 3 letras al inicio con un total de 12 caracteres, como puedo codificarla para dicho funcionamiento?
muchas gracias

@eduardelatorre
Copy link

Probad esta otra:
^(([ÑA-Z|ña-z|&]{3}|[A-Z|a-z]{4})\d{2}((0[1-9]|1[012])(0[1-9]|1\d|2[0-8])|(0[13456789]|1[012])(29|30)|(0[13578]|1[02])31)(\w{2})([A|a|0-9]{1}))$|^(([ÑA-Z|ña-z|&]{3}|[A-Z|a-z]{4})([02468][048]|[13579][26])0229)(\w{2})([A|a|0-9]{1})$

Fuente: http://www.regexlib.com/REDetails.aspx?regexp_id=3455

@fitorec
Copy link

fitorec commented Aug 19, 2021

El codigo alfanumerico de 3 letras no incluye la ñ, esta es solamente para los nombres/apellidos, por lo tanto podría quedar como:

  /^[ña-z]{3,4}[0-9]{6}[0-9a-z]{3}$/i
# | Nombre 3/4 |fecha 6| code 3  |

@jesuscovam
Copy link

El codigo alfanumerico de 3 letras no incluye la ñ, esta es solamente para los nombres/apellidos, por lo tanto podría quedar como:

  /^[ña-z]{3,4}[0-9]{6}[0-9a-z]{3}$/i
# | Nombre 3/4 |fecha 6| code 3  |

gracias!

@luisenriquech
Copy link

Hola, yo tengo varias Expresiones regulares, las explico en mi entrada de blog, pero te dejo acá los ejemplos:

Versión oficial del SAT

^[A-Z&Ñ]{3,4}[0-9]{2}(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])[A-Z0-9]{2}[0-9A]$

Versión reducida de la versión oficial del SAT

^[A-Za-zñÑ&]{3,4}\d{6}\w{3}$

Versión siguiendo al pie de la letra las instrucciones del SAT, esta versión no permite la entrada de fechas incorrectas ni de años bisiestos erróneos , de igual manera impide un RFC con palabras altisonantes, el problema es que en la práctica, existen RFC con palabras altisonantes y con fechas mal formadas.

^(((?!(([CcKk][Aa][CcKkGg][AaOo])|([Bb][Uu][Ee][YyIi])|([Kk][Oo](([Gg][Ee])|([Jj][Oo])))|([Cc][Oo](([Gg][Ee])|([Jj][AaEeIiOo])))|([QqCcKk][Uu][Ll][Oo])|((([Ff][Ee])|([Jj][Oo])|([Pp][Uu]))[Tt][Oo])|([Rr][Uu][Ii][Nn])|([Gg][Uu][Ee][Yy])|((([Pp][Uu])|([Rr][Aa]))[Tt][Aa])|([Pp][Ee](([Dd][Oo])|([Dd][Aa])|([Nn][Ee])))|([Mm](([Aa][Mm][OoEe])|([Ee][Aa][SsRr])|([Ii][Oo][Nn])|([Uu][Ll][Aa])|([Ee][Oo][Nn])|([Oo][Cc][Oo])))))[A-Za-zñÑ&][aeiouAEIOUxX]?[A-Za-zñÑ&]{2}(((([02468][048])|([13579][26]))0229)|(\d{2})((02((0[1-9])|1\d|2[0-8]))|((((0[13456789])|1[012]))((0[1-9])|((1|2)\d)|30))|(((0[13578])|(1[02]))31)))[a-zA-Z1-9]{2}[\dAa])|([Xx][AaEe][Xx]{2}010101000))$

Versión de validación caracter por caracter, esta ER es recomendable cuando se quiera validar mientras el usario tipea

^[A-Za-zñÑ&]{1,2}([A-Za-zñÑ&]([A-Za-zñÑ&](\d(\d(\d(\d(\d(\d(\w(\w(\w)?)?)?)?)?)?)?)?)?)?)?$

Fuente: https://luisenriquech.blogspot.com/2022/04/expresion-regular-de-rfc-mexico.html

@fitorec
Copy link

fitorec commented Apr 28, 2022

Fuente: https://luisenriquech.blogspot.com/2022/04/expresion-regular-de-rfc-mexico.html

Vaya de expresión regular!,

La verdad yo veo la expresión regular como un mecanismo de validar el formato del string.

Para una validación mas compleja del año/mes/día o si es bisiesto creo que hay varias librerías que te permiten hacer esto.

Meter una expresión regular que hardcodea esta lógica a un proyecto desde mi punto de vista es meter un monolito en forma de regex.

Dicho esto creo que una mejor solución es desde una regex, extraer cada parte que conforman el RFC para analizarla cada parte de estas.

  • 3 o 4 caracteres el nombre o razón social (([a-z]{3,4})).
  • 2 dígitos año de nacimiento(o conformación de la empresa) (\d{2}).
  • 2 dígitos mes de nacimiento(o conformación de la empresa)(\d{2}).
  • 2 dígitos día de nacimiento(o conformación de la empresa)(\d{2}).
  • 3 caracteres que conforman la homoclave ([0-9a-z]{3}).

Definiendo la expresión regular /^([a-z]{3,4})(\d{2})(\d{2})(\d{2})([0-9a-z]{3})$/i con el método match podemos extraer cada parte para ser analizada cada una por su parte.

De esta forma en el resultado en la posición 1 tendríamos la parte del nombre, el cual podríamos validar para ver si no es una palabra altisonante.

Un ejemplo famoso es el caso del RFC del ex-presidente Enrique Peña Nieto.
Aqui quisiera tratar el punto de:

6.- Si de las cuatro letras resulta una palabra altisonante, la segunda letra será sustituida por una "X".

Si lo pensamos este RFC debería empezar con PENE.

const rfc = "PENE660720DI6"
const reg = /^([a-z]{3,4})(\d{2})(\d{2})(\d{2})([0-9a-z]{3})$/i
rfc.match(reg)

Resultado:

[
  'PENE660720DI6',
  'PENE',
  '66',
  '07',
  '20',
  'DI6'
]

Ahora lo siguiente sería validar cada parte, como comentaba lo de las fechas es algo trivial en el sentido que hay múltiples soluciones del mismo.

Respecto a las palabras anti-sonantes se puede definir un diccionario de estos(si existe uno oficial favor de compartir) y si la parte que se conformo con el nombre/razón social pertenece a esta lista tendríamos que remplazar el segundo carácter por una X, como lo muestro a continuación:

'PENE'.replace(/^(\w)\w/, '$1X') // resultado PXNE

Dicho todo esto, hice una función denominada metaRFC que para un RFC especifico devuelve la información siguiente:

const rfc = "PENE660720DI6"
metaRFC(rfc)

Resultado

{
  rfc_input: 'PENE660720DI6',
  nombre_parte: 'PXNE',
  fecha_nacimiento_anio: '66',
  fecha_nacimiento_mes: '07',
  fecha_nacimiento_dia: '20',
  homoclave: 'DI6',
  tipo_persona: 'física',
  valido: false,
  longitud: 13,
  msg: 'Error de formato'
}

De momento metí una lista negra de malas palabras, faltaría validar las fechas y demás opciones, pensaría en agregar las demás características y como la lógica es mas compleja que la de una expresión regular, decidí crear un propio issue ojala se puedan sumar a la discusión por ahí.

👉 https://gist.github.com/fitorec/02638492300d361cd2451a8a03d99522

@luisenriquech
Copy link

luisenriquech commented Oct 11, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment