Regex de data brasileira (dd/mm/aaaa)
Regex para data no formato dd/mm/aaaa, com dia de 01 a 31 e mês de 01 a 12. Valida o intervalo, mas não os dias de cada mês nem ano bissexto.
O padrão
(?:0[1-9]|[12]\d|3[01])/(?:0[1-9]|1[0-2])/\d{4}
Flags: nenhuma. Sem âncoras: para validar um campo inteiro use ^(?:padrão)$.
Teste na hora
| Linha | Resultado |
|---|
Tudo roda no seu navegador; nada do que você digita é enviado.
Exemplos
Casam
31/12/202601/01/190029/02/202415/08/2030
Não casam
32/01/202600/10/202615/13/20261/1/20262026-12-31
Como funciona, por partes
(?:0[1-9]|[12]\d|3[01]): Dia: de 01 a 09 pela primeira alternativa, de 10 a 29 pela segunda e 30 ou 31 pela terceira. Sempre com dois dígitos./: A barra separadora é literal. Dentro de uma regex literal em JavaScript ela precisa ser escapada (\/); em RegExp montada por texto, não.(?:0[1-9]|1[0-2]): Mês: de 01 a 09 ou de 10 a 12. Isso recusa mês 00 e mês 13.\d{4}: Ano com quatro dígitos. Qualquer ano casa, de 0000 a 9999; limites de ano razoáveis ficam por conta de uma validação posterior.Intervalo, não calendário: O padrão confere que dia e mês estão em faixas possíveis, mas não cruza as duas informações. Por isso 31/02/2026 passa pelo regex.
Armadilhas
- O regex aceita datas que não existem, como 31/02, 31/04 e 29/02 de ano comum. Depois do regex, converta para uma data de verdade e confira se o dia continua o mesmo; é o jeito confiável de rejeitar essas datas.
- Em JavaScript, new Date("05/03/2026") lê a data no padrão americano (mês primeiro). Nunca passe uma data brasileira direto ao construtor; separe dia, mês e ano com os grupos do regex e monte a data com eles.
- O padrão exige zero à esquerda. Quem digita 5/3/2026 é recusado. Se isso não for desejado, troque 0[1-9] por 0?[1-9] e ajuste o mês do mesmo modo.
- Datas com hora, como 05/03/2026 14:30, não casam quando o padrão está ancorado. Combine com o padrão de hora numa expressão maior, se precisar dos dois juntos.
Código pronto
JavaScript
const re = new RegExp("^(?:(?:0[1-9]|[12]\\d|3[01])/(?:0[1-9]|1[0-2])/\\d{4})$");
console.log(re.test(texto.trim()));
Python
import re
re_data_brasileira = re.compile(r"(?:0[1-9]|[12][0-9]|3[01])/(?:0[1-9]|1[0-2])/[0-9]{4}")
print(bool(re_data_brasileira.fullmatch(texto.strip())))
C#
using System.Text.RegularExpressions;
var re = new Regex(@"^(?:(?:0[1-9]|[12][0-9]|3[01])/(?:0[1-9]|1[0-2])/[0-9]{4})\z");
bool ok = re.IsMatch(texto.Trim());
Perguntas frequentes
Como validar também o ano bissexto?
Depois que o regex aprovar o formato, monte a data com Date.UTC (ano, mês menos um, dia) e compare se o dia e o mês da data resultante são os mesmos informados. Se mudaram, a data não existe, como 29/02 em ano que não é bissexto.
Dá para aceitar também o formato com hífen?
Dá. Troque a barra por [/-] nas duas posições. Se quiser forçar que o separador seja o mesmo nas duas, use um grupo de captura e a referência \1.
Por que não usar só o campo de data do HTML?
O campo date entrega o valor em AAAA-MM-DD e cuida do calendário, mas nem toda entrada vem de um formulário: planilhas, arquivos e textos colados chegam em dd/mm/aaaa, e é aí que este regex ajuda.