RegEx za podudaranje uzorka datuma u Javi

1. Uvod

Regularni izrazi moćan su alat za podudaranje različitih vrsta obrazaca kada se koriste na odgovarajući način.

U ovom ćemo članku koristiti java.util.regex paket kako bi se utvrdilo je li zadani Niz sadrži valjani datum ili ne.

Uvod u regularne izraze potražite u našem Vodiču kroz API za Java regularne izraze.

2. Pregled formata datuma

Definirat ćemo valjani datum u odnosu na međunarodni gregorijanski kalendar. Naš format slijedit će opći obrazac: GGGG-MM-DD.

Uključimo i koncept a skok godine koja je godina koja sadrži dan 29. veljače. Prema gregorijanskom kalendaru nazvat ćemo godinu skok ako se broj godine može ravnomjerno podijeliti sa 4 osim onih koji su djeljivi sa 100 ali uključujući one koji su djeljivi sa 400.

U svim ostalim slučajevima, nazvat ćemo godinu redovito.

Primjeri valjanih datuma:

  • 2017-12-31
  • 2020-02-29
  • 2400-02-29

Primjeri nevaljanih datuma:

  • 2017/12/31: netočan graničnik tokena
  • 2018-1-1: nedostaju vodeće nule
  • 2018-04-31: pogrešni dani se računaju za travanj
  • 2100-02-29: ova godina nije skok jer se vrijednost dijeli sa 100, tako da je veljača ograničena na 28 dana

3. Primjena rješenja

Budući da ćemo datum podudarati pomoću regularnih izraza, prvo skicirajmo sučelje DateMatcher, koji pruža jedan šibice metoda:

javno sučelje DateMatcher {logička podudaranja (datum niza); }

U nastavku ćemo predstaviti implementaciju korak po korak, nadovezujući se na cjelovito rješenje na kraju.

3.1. Podudaranje sa širokim formatom

Počet ćemo s izradom vrlo jednostavnog prototipa koji obrađuje ograničenja formata našeg podudaranja:

klasa FormattedDateMatcher implementira DateMatcher {privatni statički obrazac DATE_PATTERN = Pattern.compile ("^ \ d {4} - \ d {2} - \ d {2} $"); @Preuzmi javna logička podudaranja (datum niza) {return DATE_PATTERN.matcher (date) .matches (); }}

Ovdje to preciziramo valjani datum mora se sastojati od tri skupine cijelih brojeva odvojenih crticom. Prvu skupinu čine četiri cijele brojeve, dok preostale dvije skupine imaju po dvije cijele brojeve.

Datumi podudaranja: 2017-12-31, 2018-01-31, 0000-00-00, 1029-99-72

Datumi koji se ne podudaraju: 2018-01, 2018-01-XX, 2020/02/29

3.2. Podudaranje određenog formata datuma

Naš drugi primjer prihvaća raspone tokena datuma, kao i ograničenje oblikovanja. Radi jednostavnosti, ograničili smo svoj interes na godine 1900. - 2999.

Sad kad smo uspješno uskladili naš opći format datuma, moramo to dodatno ograničiti - kako bismo bili sigurni da su datumi zapravo točni:

^((19|2[0-9])[0-9]{2})-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$

Ovdje smo predstavili tri skupine cjelobrojnih raspona koji se moraju podudarati:

  • (19|2[0-9])[0-9]{2} pokriva ograničeni raspon godina podudaranjem broja koji započinje s 19 ili 2X nakon čega slijedi nekoliko znamenki.
  • 0[1-9]|1[012] odgovara mjesečnom broju u rasponu od 01-12
  • 0[1-9]|[12][0-9]|3[01] odgovara dnevnom broju u rasponu od 01-31

Datumi podudaranja: 1900-01-01, 2205-02-31, 2999-12-31

Datumi koji se ne podudaraju: 1899-12-31, 2018-05-35, 2018-13-05, 3000-01-01, 2018-01-XX

3.3. Odgovarajući 29. veljače

Da bismo pravilno podudarali prestupne godine, prvo moramo prepoznati kada smo naišli na prijestupnu godinu, a zatim se pobrinite da 29. veljače prihvatimo kao valjani datum za te godine.

Kako je broj prijestupnih godina u našem ograničenom rasponu dovoljno velik, trebali bismo koristiti odgovarajuća pravila djeljivosti da bismo ih filtrirali:

  • Ako je broj koji čine posljednje dvije znamenke u broju djeljiv s 4, izvorni broj djeljiv je s 4
  • Ako su posljednje dvije znamenke broja 00, broj je djeljiv sa 100

Evo rješenja:

^((2000|2400|2800|(19|2[0-9](0[48]|[2468][048]|[13579][26])))-02-29)$

Uzorak se sastoji od sljedećih dijelova:

  • 2000|2400|2800 odgovara skupu prestupnih godina s razdjelnikom 400 u ograničenom rasponu od 1900-2999
  • 19|2[0-9](0[48]|[2468][048]|[13579][26])) odgovara svima bijela lista kombinacije godina koje imaju razdjelnik od 4 i nemaju razdjelnik od 100
  • -02-29 šibice 2. veljače

Datumi podudaranja: 2020-02-29, 2024-02-29, 2400-02-29

Datumi koji se ne podudaraju: 2019-02-29, 2100-02-29, 3200-02-29, 2020/02/29

3.4. Odgovarajući Generalnim danima u veljači

Kao i podudaranje 29. veljače u prijestupnoj godini, također se moramo podudarati sa svim ostalim danima veljače (1. - 28.) u svim godinama:

^(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))$

Datumi podudaranja: 2018-02-01, 2019-02-13, 2020-02-25

Datumi koji se ne podudaraju: 2000-02-30, 2400-02-62, 2018/02/28

3.5. Odgovarajući 31-dnevnim mjesecima

Mjeseci siječanj, ožujak, svibanj, srpanj, kolovoz, listopad i prosinac trebali bi se podudarati između 1 i 31 dana:

^(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))$

Datumi podudaranja: 2018-01-31, 2021-07-31, 2022-08-31

Datumi koji se ne podudaraju: 2018-01-32, 2019-03-64, 2018/01/31

3.6. Odgovarajući 30-dnevnim mjesecima

Mjeseci travanj, lipanj, rujan i studeni trebali bi se podudarati između 1 i 30 dana:

^(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30))$

Datumi podudaranja: 2018-04-30, 2019-06-30, 2020-09-30

Datumi koji se ne podudaraju: 2018-04-31, 2019-06-31, 2018/04/30

3.7. Gregorijanski meč datuma

Sad možemo kombinirajte sve gornje uzorke u jedno podudaranje kako biste dobili cjelovit GregorianDateMatcher zadovoljavajući sva ograničenja:

klasa GregorianDateMatcher implementira DateMatcher {privatni statički obrazac DATE_PATTERN = Pattern.compile ("^ ((2000 | 2400 | 2800 | (19 | 2 [0-9] (0 [48] | [2468] [048] | [13579] [ 26]))) - 02-29) $ "+" | ^ (((19 | 2 [0-9]) [0-9] {2}) - 02- (0 [1-9] | 1 [ 0-9] | 2 [0-8])) $ "+" | ^ (((19 | 2 [0-9]) [0-9] {2}) - (0 [13578] | 10 | 12 ) - (0 [1-9] | [12] [0-9] | 3 [01])) $ "+" | ^ (((19 | 2 [0-9]) [0-9] {2 }) - (0 [469] | 11) - (0 [1-9] | [12] [0-9] | 30)) $ "); @Preuzmi javna logička podudaranja (datum niza) {return DATE_PATTERN.matcher (date) .matches (); }}

Koristili smo alternacija znak "|" podudarati se barem s jednim od četiri grane. Dakle, valjani datum veljače odgovara ili prvoj grani 29. veljače prijestupne godine ili drugoj grani bilo kojeg dana od 1 do 28. Datumi preostalih mjeseci odgovaraju trećoj i četvrtoj grani.

Budući da ovaj obrazac nismo optimizirali u korist bolje čitljivosti, slobodno eksperimentirajte s njegovom dužinom.

U ovom smo trenutku zadovoljili sva ograničenja koja smo uveli na početku.

3.8. Napomena o izvedbi

Raščlanjivanje složenih regularnih izraza može značajno utjecati na izvedbu tijeka izvršavanja. Primarna svrha ovog članka nije bila naučiti učinkovit način testiranja niza za njegovo članstvo u skupu svih mogućih datuma.

Razmislite o upotrebi LocalDate.parse () pruža Java8 ako je potreban pouzdan i brz pristup provjeri valjanosti datuma.

4. Zaključak

U ovom smo članku naučili kako koristiti regularne izraze za podudaranje strogo oblikovanog datuma gregorijanskog kalendara pružajući također pravila o formatu, rasponu i duljini mjeseci.

Sav kôd predstavljen u ovom članku dostupan je na Githubu. Ovo je projekt zasnovan na Mavenu, pa bi ga trebalo lako uvesti i pokrenuti kakav jest.


$config[zx-auto] not found$config[zx-overlay] not found