Dopasowanie wyrażenia regularnego, aby sprawdzić prawidłowy rok

89

Biorąc pod uwagę wartość, chcę ją zweryfikować, aby sprawdzić, czy jest to ważny rok. Moje kryteria są proste, gdzie wartość powinna być liczbą całkowitą ze 4znakami. Wiem, że to nie jest najlepsze rozwiązanie, ponieważ nie pozwoli na to lata wcześniej 1000i pozwoli na takie lata 5000. To kryterium jest adekwatne do mojego obecnego scenariusza.

To, co wymyśliłem, to

\d{4}$

Chociaż to działa, pozwala również na wartości ujemne.

Jak się upewnić, że dozwolone są tylko dodatnie liczby całkowite?

Ranhiru Jude Cooray
źródło
fwiw Stworzyłem projekt node.js, to-regex-range, aby automatycznie utworzyć te zakresy. Jest to trudniejsze niż mogłoby się wydawać, jeśli musisz wygenerować wyrażenie regularne do testowania przez kilka lat.
jonschlinkert
Po co ograniczać walidację do 4-cyfrowych lat? longnow.org
Dan Temple,

Odpowiedzi:

76

Musisz dodać kotwicę początkową ^jako:

^\d{4}$

Twoje wyrażenie regularne \d{4}$dopasuje ciągi kończące się 4 cyframi . Tak więc wejście takie jak -1234zostanie zaakceptowane.

Dodając kotwicę początkową, dopasowujesz tylko te ciągi, które zaczynają się i kończą 4 cyframi, co w praktyce oznacza, że ​​muszą zawierać tylko 4 cyfry.

codaddict
źródło
2
Cholera! Mój był tak wadliwy, że nawet by to zaakceptował whateverblahblah2323. Teraz rozumiem, dlaczego odrobina nauki jest niebezpieczna: O
Ranhiru Jude Cooray,
62
Nastąpi to w 10.000 roku.
sferik
16
@sferik: Nie ma znaczenia. Oryginalny plakat wyraźnie stwierdzał, że chce sprawdzić cztery postacie. Nie oświadczył, że chce, aby rok 10.000 był prawidłowym wejściem, więc akceptacja 10000byłaby błędem.
markusk
4
@sferik: Do tego czasu program zniknie na wieki. Jeśli nie, najlepiej martwić się o 9000 lat w przyszłości. Zgodnie z zasadą YAGNI, podejście to jest poprawne.
Phil
182

Lata od 1000 do 2999

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

Na lata 1900-2099

^(19|20)\d{2}$
r92
źródło
14
To znacznie lepsze rozwiązanie
mk_89
10
Lepiej użyć grupy bez przechwytywania:^(?:19|20)\d{2}$
Eldar Agalarov
Jak zweryfikować czterocyfrowy rok między 2011 a 2099?
mcquaim
Jak mogę dodać (19|20)\d{2}do mojego wyrażenia regularnego, aby sprawdzić poprawność formatu daty urodzenia? To jest moje wyrażenie regularne. /^[0-9]{1,2}\/(0[1-9])|(1[0-2])\/[0-9]{4}$/Chcę się upewnić, że rok ma zawsze 4 cyfry i zaczyna się od 19 ** lub 20 **
ltdev
Użyj ^ (19 | 2 [0-9]) \ d {2} $ dla lat 1900 - 2999
MarcoZen
22

„Zaakceptowana” odpowiedź na to pytanie jest zarówno niepoprawna, jak i krótkowzroczna.

Niepoprawne jest to, że dopasowuje ciągi, takie jak 0001, który nie jest prawidłowym rokiem.

Jest krótkowzroczny, ponieważ nie będzie pasował do żadnych wartości powyżej 9999. Czy już zapomnieliśmy o lekcjach z roku 2000 ? Zamiast tego użyj wyrażenia regularnego:

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

Jeśli chcesz dopasować lata z przeszłości, a nie tylko lata w przyszłości, możesz użyć tego wyrażenia regularnego do dopasowania dowolnej dodatniej liczby całkowitej:

^[1-9]\d*$

Nawet jeśli nie spodziewasz się dat z przeszłości, i tak możesz chcieć użyć tego wyrażenia regularnego, na wypadek gdyby ktoś wynalazł wehikuł czasu i chciał zabrać ze sobą twoje oprogramowanie.

Uwaga: to wyrażenie regularne będzie pasowało do wszystkich lat, w tym przed rokiem 1, ponieważ są one zwykle przedstawiane jako BC zamiast ujemnej liczby całkowitej. Oczywiście ta konwencja może się zmienić w ciągu następnych kilku tysiącleci, więc najlepszym rozwiązaniem jest dopasowanie dowolnej liczby całkowitej - dodatniej lub ujemnej - za pomocą następującego wyrażenia regularnego:

^-?[1-9]\d*$
sferik
źródło
3
Nie, prawdopodobnie nie będzie. Ale ktoś (archeolog? Historyk?) Może potrzebować dopasowania lat 8000 lat temu. : D A Doc Brown może tego potrzebować ...
Jaime
1
użyłem tego do ograniczenia zakresu od 1000-9999 ^ [1-9] \\ d {3} $ to dlatego, że aplikacja, do której musimy dostarczyć dane, akceptuje tylko 4
cyfrowe
Świetna odpowiedź. Zrobiłbym następująco, aby zaakceptować rok 0: ^ (-? [1-9] \ d * | 0) $
Kosta Kontos,
10

Działa to od 1900 do 2099:

/(?:(?:19|20)[0-9]{2})/
jonschlinkert
źródło
wygląda mi na to, że poszedłby tylko do 2099. BTW OP pyta, jak zezwolić tylko na dodatnią liczbę 4-cyfrową.
DeanOC
bah, mam na myśli 2099. dzięki. a teraz widzę część dodatnich liczb całkowitych.
jonschlinkert
Stworzyłem projekt, to-regex-range, aby automatycznie utworzyć te zakresy
jonschlinkert
5

Opierając się na odpowiedzi @ r92, dla lat 1970-2019:

(19[789]\d|20[01]\d)
Renaud
źródło
Twoja odpowiedź pozwala197999
lawina1
Myślę, że tak nie jest ... Pierwsza część wyrażenia regularnego odpowiada numerowi zaczynającemu się od 19, następnie dowolnemu z 7,8 lub 9, po którym następuje POJEDYNCZA liczba. Wyrażenie regularne 19[789]\d\d\dpozwoli197999
Renaud
1
/(19[789]\d|20[01]\d)/.test(1970324) >> true
lawina 1
tak, dopasuje pierwsze 4 cyfry ( 1970), a nie ostatnie 3. A co z (19[789]\d|20[01]\d)[^0-9]? To pasowałoby, 1970 324ale nie1970324
Renaud
1
Ten okazał się przydatny do znalezienia roku filmowego na podstawie nazwy pliku ... w tym przypadku chcemy rzeczy z lat trzydziestych XX wieku ... ale następnie wykluczamy 1024, który jest dodawany na końcu ze względu na jakość wideo
Adrian Hum
2

Teoretycznie opcja 4-cyfrowa jest właściwa. Ale w praktyce lepiej byłoby mieć zakres 1900-2099.

Dodatkowo musi to być grupa bez przechwytywania. Wiele komentarzy i odpowiedzi proponuje grupowanie przechwytywania, które nie jest właściwym IMHO. Ponieważ dopasowanie może zadziałać, ale przy wyodrębnianiu dopasowań za pomocą wyrażenia regularnego wyodrębni 4-cyfrowe liczby i dwucyfrowe (19 i 20) liczby również ze względu na parantezę.

To zadziała w przypadku dokładnego dopasowania przy użyciu grup nieprzechwytywanych:

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

Adil Aliyev
źródło
1

możesz iść z czymś takim jak [ ^-]\d{4}$: zapobiegasz umieszczaniu znaku minus -przed twoimi 4 cyframi.
możesz także użyć ^\d{4}$with, ^aby złapać początek łańcucha. To zależy od twojego scenariusza ...

PierrOz
źródło
1

Aby przetestować rok w ciągu zawierającym inne słowa wraz z rokiem, możesz użyć następującego wyrażenia regularnego: \ b \ d {4} \ b

Dhyey
źródło
To było dokładnie to, czego potrzebowałem, zaakceptowana odpowiedź nie wydaje się być poprawną PCRE.
Prometeusz
0

Możesz zamienić swoją liczbę całkowitą na łańcuch. Ponieważ znak minus nie będzie pasował do cyfr, nie będziesz mieć lat ujemnych.

Comradin
źródło
0

Używam tego wyrażenia regularnego w Javie ^(0[1-9]|1[012])[/](0[1-9]|[12][0-9]|3[01])[/](19|[2-9][0-9])[0-9]{2}$

Działa od 1900 do 9999

R2Rivs
źródło
0

/ ^ \ d {4} $ / Sprawdzi, czy ciąg składa się tylko z 4 liczb. W tym scenariuszu, aby wprowadzić rok 989, można zamiast tego podać 0989.

Dayz
źródło
0

Jeśli chcesz dopasować RRRR lub RRRRMMDD, możesz użyć:

^((?:(?:(?:(?:(?:[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
źródło
0

Możesz również użyć tego.

([0-2][0-9]|3[0-1])\/([0-1][0-2])\/(19[789]\d|20[01]\d)
Ranjeet Chouhan
źródło
Chcą pasować tylko rok. Ponadto Twoje wyrażenie regularne pasuje 00/00/2000lub 31/02/1999i wiele innych fałszywych dat.
Toto
To może ci pomóc ([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])jest znacznie lepszym określeniem na miesiąc
EZ-C