Correspondência de expressão regular para testar um ano válido

92

Dado um valor, quero validá-lo para verificar se é um ano válido. Meus critérios são simples, onde o valor deve ser um número inteiro com 4caracteres. Sei que essa não é a melhor solução, pois não permitirá anos antes 1000e permitirá anos como 5000. Este critério é adequado para meu cenário atual.

O que eu inventei é

\d{4}$

Embora funcione, também permite valores negativos.

Como posso garantir que apenas números inteiros positivos sejam permitidos?

Ranhiru Jude Cooray
fonte
fwiw Eu criei um projeto node.js, to-regex-range para criar automaticamente esses intervalos. É mais difícil do que pode parecer se você precisar gerar a regex para testar por um intervalo de anos.
jonschlinkert
Por que limitar sua validação a anos de 4 dígitos? longnow.org
Dan Temple

Respostas:

78

Você precisa adicionar uma âncora inicial ^como:

^\d{4}$

Seu regex \d{4}$corresponderá a strings que terminam com 4 dígitos . Portanto, entradas como -1234serão aceitas.

Ao adicionar a âncora de início, você associa apenas as strings que começam e terminam com 4 dígitos, o que efetivamente significa que devem conter apenas 4 dígitos.

codadicto
fonte
2
Droga! O meu era tão defeituoso que teria até aceitado whateverblahblah2323. Agora eu entendo porque um pouco de aprendizado é perigoso: O
Ranhiru Jude Cooray
62
Isso acontecerá no ano 10.000.
sferik
16
@sferik: Não importa. O pôster original afirmou especificamente que queria verificar se havia quatro personagens. Ele não afirmou que queria que o ano 10.000 fosse uma entrada válida, então aceitar 10000seria um bug.
markusk
4
@sferik: O programa terá desaparecido por séculos. Do contrário, é melhor se preocupar com 9.000 anos no futuro. Seguindo o princípio de YAGNI, a abordagem é válida.
Phil
183

Anos de 1000 a 2999

^[12][0-9]{3}$

Para 1900-2099

^(19|20)\d{2}$
r92
fonte
14
Esta é uma solução muito melhor
mk_89
10
É melhor usar o grupo sem captura:^(?:19|20)\d{2}$
Eldar Agalarov
Como eu validaria um ano de 4 dígitos entre 2011 e 2099?
Mcquaim
Como posso adicionar (19|20)\d{2}ao meu regex para validar um formato de data de nascimento? Esta é a minha regex /^[0-9]{1,2}\/(0[1-9])|(1[0-2])\/[0-9]{4}$/. Quero garantir que o ano sempre tenha 4 dígitos e comece a murchar 19 ** ou 20 **
ltdev
Use ^ (19 | 2 [0-9]) \ d {2} $ para os anos 1900 - 2999
MarcoZen
22

A resposta "aceita" a esta pergunta é incorreta e míope.

É incorreto porque corresponderá a strings como 0001, que não é um ano válido.

É míope porque não corresponderá a nenhum valor acima de 9999. Já esquecemos as lições do Y2K ? Em vez disso, use a expressão regular:

^[1-9]\d{3,}$

Se você precisar corresponder anos no passado, além de anos no futuro, poderá usar esta expressão regular para corresponder a qualquer número inteiro positivo:

^[1-9]\d*$

Mesmo que você não espere datas do passado, você pode querer usar esta expressão regular de qualquer maneira, apenas no caso de alguém inventar uma máquina do tempo e quiser levar seu software de volta com eles.

Nota: Esta expressão regular corresponderá a todos os anos, incluindo aqueles anteriores ao ano 1, uma vez que eles são normalmente representados com uma designação BC em vez de um número inteiro negativo. Claro, essa convenção pode mudar nos próximos milênios, então sua melhor opção é combinar qualquer número inteiro - positivo ou negativo - com a seguinte expressão regular:

^-?[1-9]\d*$
sferik
fonte
3
Não, provavelmente não vai. Mas alguém (arqueólogo? Historiador?) Pode precisar comparar anos com 8.000 anos atrás. : D E Doc Brown pode precisar ...
Jaime
1
Eu usei isso para limitar o intervalo de 1000-9999 ^ [1-9] \\ d {3} $ isso porque o aplicativo para o qual temos que fornecer dados, aceita apenas números de 4 dígitos :(
MatPag
Resposta incrível. Eu faria o seguinte para aceitar o ano 0 também: ^ (-? [1-9] \ d * | 0) $
Kosta Kontos
10

Isso funciona de 1900 a 2099:

/(?:(?:19|20)[0-9]{2})/
jonschlinkert
fonte
me parece que só iria para 2099. BTW, o OP está perguntando como permitir apenas números positivos de 4 dígitos.
DeanOC 01 de
bah, 2099 é o que eu quis dizer. obrigado. e agora vejo a parte dos inteiros positivos.
jonschlinkert 01 de
Eu criei um projeto, to-regex-range para criar automaticamente esses intervalos
jonschlinkert
5

Com base na resposta @ r92, para os anos 1970-2019:

(19[789]\d|20[01]\d)
Renaud
fonte
Sua resposta permite197999
avalanche1
Acho que não ... A primeira parte da regex corresponde a um número começando com 19, depois qualquer um de 7,8 ou 9, seguido por um ÚNICO número. A regex 19[789]\d\d\dpermitiria197999
Renaud,
1
/(19[789]\d|20[01]\d)/.test(1970324) >> true
avalanche1 de
sim, corresponderá aos 4 primeiros números ( 1970), não aos 3 últimos (19[789]\d|20[01]\d)[^0-9]. Isso combinaria, 1970 324mas não1970324
Renaud
1
Achei este útil para encontrar o ano do filme a partir de um nome de arquivo ... neste caso, queremos coisas de 1930 em diante ... mas, em seguida, excluímos o 1024 que foi adicionado ao final para qualidade de vídeo
Adrian Hum
2

Para testar um ano em uma string que contém outras palavras junto com o ano, você pode usar o seguinte regex: \ b \ d {4} \ b

Dhyey
fonte
Isso era exatamente o que eu precisava, a resposta aceita não parece ser PCRE válida.
Prometheus
2

Em teoria, a opção de 4 dígitos está certa. Mas, na prática, pode ser melhor ter uma faixa de 1900-2099.

Além disso, ele precisa ser um grupo sem captura. Muitos comentários e respostas propõem capturar o agrupamento que não é IMHO adequado. Porque para correspondência pode funcionar, mas para extrair correspondências usando regex, ele extrairá números de 4 dígitos e números de dois dígitos (19 e 20) também por causa do parêntese.

Isso funcionará para correspondência exata usando grupos de não captura:

(?:19|20)\d{2}

Adil Aliyev
fonte
1

você pode ir com sth como [ ^-]\d{4}$: você evita que o sinal de menos -fique antes de seus 4 dígitos.
você também pode usar ^\d{4}$com ^para pegar o início da string. Na verdade, depende do seu cenário ...

PierrOz
fonte
0

Você pode converter seu inteiro em uma string. Como o sinal de menos não coincide com os dígitos, você não terá anos negativos.

Comradin
fonte
0

Eu uso este regex em Java ^(0[1-9]|1[012])[/](0[1-9]|[12][0-9]|3[01])[/](19|[2-9][0-9])[0-9]{2}$

Funciona de 1900 a 9999

R2Rivs
fonte
0

/ ^ \ d {4} $ / Isto irá verificar se uma string consiste em apenas 4 números. Neste cenário, para inserir o ano 989, você pode fornecer 0989.

Dayz
fonte
0

Se precisar corresponder YYYY ou YYYYMMDD, você pode usar:

^((?:(?:(?:(?:(?:[1-9]\d)(?:0[48]|[2468][048]|[13579][26])|(?:(?:[2468][048]|[13579][26])00))(?:0?2(?:29)))|(?:(?:[1-9]\d{3})(?:(?:(?:0?[13578]|1[02])(?:31))|(?:(?:0?[13-9]|1[0-2])(?:29|30))|(?:(?:0?[1-9])|(?:1[0-2]))(?:0?[1-9]|1\d|2[0-8])))))|(?:19|20)\d{2})$
Benjamin Goodacre
fonte
0

Você também pode usar este.

([0-2][0-9]|3[0-1])\/([0-1][0-2])\/(19[789]\d|20[01]\d)
Ranjeet Chouhan
fonte
Eles querem combinar apenas o ano. Além disso, suas correspondências de regex 00/00/2000ou 31/02/1999e muitas outras datas falsas.
Toto de
Isso pode ajudá-lo ([0-2] [0-9] | 3 [0-1]) \ / ([0-1] [0-2]) \ / (19 [789] \ d | 20 [01 ] \ d)
Ranjeet Chouhan
(0[1-9]|1[0-2])é uma expressão muito melhor para o mês
EZ-C
0

No meu caso, eu queria combinar uma string que terminasse com um ano (4 dígitos) como este, por exemplo:

Oct 2020
Nov 2020
Dec 2020
Jan 2021

Ele vai voltar truecom este:

var sheetName = 'Jan 2021';
var yearRegex = new RegExp("\\d{4}$");
var isMonthSheet = yearRegex.test(sheetName);
Logger.log('isMonthSheet = ' + isMonthSheet);

O código acima é usado no Apps Script .

Leniel Maccaferri
fonte
Isso, não só vai combinar, Oct 2020mas também Oct 20202, Oct20202
Ranhiru Jude Cooray