RegEx pre zladenie vzoru dátumu v Jave

1. Úvod

Regulárne výrazy sú mocným nástrojom na priraďovanie rôznych druhov vzorov, ak sú správne použité.

V tomto článku použijeme java.util.regex balíček na zistenie, či daný String obsahuje platný dátum alebo nie.

Úvod do regulárnych výrazov nájdete v našom Sprievodcovi rozhraním Java Regular Expressions API.

2. Prehľad formátu dátumu

Budeme definovať platný dátum vo vzťahu k medzinárodnému gregoriánskemu kalendáru. Náš formát sa bude riadiť všeobecným vzorom: RRRR-MM-DD.

Zahrňme tiež koncept a skok rok, ktorý je rokom obsahujúcim deň 29. februára. Podľa gregoriánskeho kalendára budeme volať rok skok ak možno číslo roku rozdeliť rovnomerne 4 okrem tých, ktoré sú deliteľné 100 ale vrátane tých, ktoré sú deliteľné 400.

Vo všetkých ostatných prípadoch, zavoláme rok pravidelné.

Príklady platných dátumov:

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

Príklady neplatných dátumov:

  • 2017/12/31: nesprávny oddeľovač tokenov
  • 2018-1-1: chýbajúce úvodné nuly
  • 2018-04-31: nesprávne dni sa počítajú za apríl
  • 2100-02-29: tento rok nie je skok, pretože hodnota sa vydelí 100, takže február je obmedzený na 28 dní

3. Implementácia riešenia

Pretože sa chystáme priradiť dátum pomocou regulárnych výrazov, najskôr si načrtnime rozhranie DateMatcher, ktorá poskytuje singel zápasy metóda:

verejné rozhranie DateMatcher {booleovské zhody (dátum reťazca); }

Nižšie uvedieme postupnú implementáciu, na konci ktorej bude úplné riešenie.

3.1. Zodpovedá širokému formátu

Začneme tým, že vytvoríme veľmi jednoduchý prototyp, ktorý zvládne obmedzenia formátu nášho porovnávača:

trieda FormattedDateMatcher implementuje DateMatcher {private static Pattern DATE_PATTERN = Pattern.compile ("^ \ d {4} - \ d {2} - \ d {2} $"); @ Override verejné boolean zápasy (dátum reťazca) {return DATE_PATTERN.matcher (dátum) .matches (); }}

Tu to špecifikujeme platný dátum musí pozostávať z troch skupín celých čísel oddelených pomlčkou. Prvá skupina sa skladá zo štyroch celých čísel, zvyšné dve skupiny majú vždy dve celé čísla.

Zhodné termíny: 2017-12-31, 2018-01-31, 0000-00-00, 1029-99-72

Nezhodné dátumy: 2018-01, 2018-01-XX, 2020/02/29

3.2. Zodpovedá konkrétnemu formátu dátumu

Náš druhý príklad akceptuje rozsahy dátumových tokenov, ako aj naše obmedzenie formátovania. Pre jednoduchosť sme náš záujem obmedzili na roky 1900 - 2999.

Teraz, keď sme úspešne spárovali náš všeobecný formát dátumu, musíme to ešte viac obmedziť - aby sme sa ubezpečili, že dátumy sú skutočne správne:

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

Tu sme predstavili tri skupiny z celých číselných rozsahov, ktoré sa musia zhodovať:

  • (19|2[0-9])[0-9]{2} pokrýva obmedzený rozsah rokov zhodou s číslom, ktoré začína 19 alebo 2X za ktorým nasleduje pár ľubovoľných číslic.
  • 0[1-9]|1[012] sa zhoduje s číslom mesiaca v rozmedzí od 01-12
  • 0[1-9]|[12][0-9]|3[01] sa zhoduje s číslom dňa v rozsahu od 01-31

Zhodné termíny: 1900-01-01, 2205-02-31, 2999-12-31

Nezhodné dátumy: 1899-12-31, 2018-05-35, 2018-13-05, 3000-01-01, 2018-01-XX

3.3. Zhoduje sa 29. februára

Aby sme mohli správne prispôsobiť priestupné roky, musíme najskôr zistiť, kedy sme sa stretli s priestupným rokoma potom sa uistite, že 29. február prijímame ako platný dátum pre tieto roky.

Pretože počet priestupných rokov v našom obmedzenom rozsahu je dosť veľký, mali by sme ich filtrovať pomocou príslušných pravidiel deliteľnosti:

  • Ak je číslo tvorené poslednými dvoma číslicami v čísle deliteľné 4, pôvodné číslo je deliteľné 4
  • Ak sú posledné dve číslice čísla 00, číslo je deliteľné 100

Tu je riešenie:

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

Vzor sa skladá z nasledujúcich častí:

  • 2000|2400|2800 zodpovedá množine priestupných rokov s rozdeľovačom 400 v obmedzenom rozsahu 1900-2999
  • 19|2[0-9](0[48]|[2468][048]|[13579][26])) zodpovedá všetkým biela listina kombinácie rokov, ktoré majú rozdeľovač 4 a nemáš rozdeľovač 100
  • -02-29 zápasy 2. februára

Zhodné termíny: 2020-02-29, 2024-02-29, 2400-02-29

Nezhodné dátumy: 2019-02-29, 2100-02-29, 3200-02-29, 2020/02/29

3.4. Zodpovedajúce všeobecné februárové dni

Rovnako ako zodpovedajúci 29. február v priestupných rokoch, tiež musíme zodpovedať všetkým ostatným februárovým dňom (1 - 28) vo všetkých rokoch:

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

Zhodné termíny: 2018-02-01, 2019-02-13, 2020-02-25

Nezhodné dátumy: 2000-02-30, 2400-02-62, 2018/02/28

3.5. Zodpovedajúce 31-dňové mesiace

Mesiace január, marec, máj, júl, august, október a december by sa mali zhodovať od 1 do 31 dní:

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

Zhodné termíny: 2018-01-31, 2021-07-31, 2022-08-31

Nezhodné dátumy: 2018-01-32, 2019-03-64, 2018/01/31

3.6. Zodpovedajúce 30-dňové mesiace

Mesiace apríl, jún, september a november by sa mali zhodovať od 1 do 30 dní:

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

Zhodné termíny: 2018-04-30, 2019-06-30, 2020-09-30

Nezhodné dátumy: 2018-04-31, 2019-06-31, 2018/04/30

3.7. Gregoriánsky porovnávač dátumov

Teraz môžeme skombinujte všetky vyššie uvedené vzory do jedného porovnávača, aby ste mali hotový komplet GregorianDateMatcher vyhovujúce všetkým obmedzeniam:

trieda GregorianDateMatcher implementuje DateMatcher {private static Pattern 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)) $ "); @ Verejné verejné booleovské zápasy (dátum reťazca) {return DATE_PATTERN.matcher (dátum) .matches (); }}

Použili sme striedanie znak „|“ zodpovedať aspoň jednému zo štyroch pobočiek. Platný dátum február sa teda zhoduje s prvou vetvou 29. februára priestupného roku alebo s druhou vetvou ktoréhokoľvek dňa od 1 do 28. Dátumy zostávajúcich mesiacov sa zhodujú s treťou a štvrtou pobočkou.

Pretože sme tento vzor neoptimalizovali v prospech lepšej čitateľnosti, neváhajte experimentovať s jeho dĺžkou.

V tejto chvíli sme splnili všetky obmedzenia, ktoré sme zaviedli na začiatku.

3.8. Poznámka k výkonu

Analýza zložitých regulárnych výrazov môže významne ovplyvniť výkon toku vykonávania. Primárnym účelom tohto článku nebolo naučiť sa efektívny spôsob testovania reťazca na jeho členstvo v súbore všetkých možných dátumov.

Zvážte použitie LocalDate.parse () poskytuje Java8, ak je potrebný spoľahlivý a rýchly prístup k overeniu dátumu.

4. Záver

V tomto článku sme sa naučili, ako používať regulárne výrazy na prispôsobenie sa presne formátovanému dátumu gregoriánskeho kalendára, a to poskytnutím pravidiel pre formát, rozsah a dĺžku mesiacov.

Celý kód uvedený v tomto článku je k dispozícii na stránkach Github. Toto je projekt založený na Maven, takže by malo byť ľahké ho importovať a spustiť tak, ako je.


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