RegEx a dátumminta illesztéséhez a Java-ban

1. Bemutatkozás

A rendszeres kifejezések hatékony eszköz a különféle minták megfelelő illesztésére, ha azokat megfelelően használják.

Ebben a cikkben felhasználjuk java.util.regex csomagot annak meghatározásához, hogy adott-e Húr érvényes dátumot tartalmaz, vagy sem.

A reguláris kifejezések bemutatásához olvassa el az Útmutató a Java rendszeres kifejezések API-hoz című útmutatónkat.

2. A dátumformátum áttekintése

Meg fogunk határozni egy érvényes dátumot a nemzetközi Gergely-naptárhoz viszonyítva. Formátumunk az általános mintát követi: ÉÉÉÉ-HH-NN.

Vegyük bele az a fogalmát is Ugrás év, azaz február 29. napját tartalmazó év. A Gergely-naptár szerint egy évet hívunk Ugrás ha az évszámot egyenletesen el lehet osztani 4 kivéve azokat, amelyek oszthatók 100 de beleértve azokat is, amelyek oszthatók 400.

Minden más esetben, egy évet hívunk szabályos.

Példák az érvényes dátumokra:

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

Példák érvénytelen dátumokra:

  • 2017/12/31: helytelen token elválasztó
  • 2018-1-1: hiányzó vezető nullák
  • 2018-04-31: rossz napok számítanak áprilisra
  • 2100-02-29: ez az év nem ugrik be, mivel az érték osztódik 100, tehát február 28 napra korlátozódik

3. Megoldás megvalósítása

Mivel a dátumot szabályos kifejezésekkel fogjuk egyeztetni, először vázoljuk fel a kezelőfelületet DateMatcher, amely egyetlen mérkőzések módszer:

nyilvános felület DateMatcher {logikai egyezések (Karakterlánc dátuma); }

Az alábbiakban lépésről lépésre bemutatjuk a megvalósítást, a végén a teljes megoldás felé építve.

3.1. A széles formátumnak megfelelő

Kezdjük egy nagyon egyszerű prototípus létrehozásával, amely kezeli a páros formátumkorlátjait:

class FormattedDateMatcher implementálja a DateMatcher {private static Pattern DATE_PATTERN = Pattern.compile ("^ \ d {4} - \ d {2} - \ d {2} $"); @ Nyilvános logikai egyezések felülírása (karakterlánc dátuma) {return DATE_PATTERN.matcher (dátum) .matches (); }}

Itt ezt meghatározzuk az érvényes dátumnak három egész számcsoportból kell állnia, amelyek elválasztva kötőjellel vannak elválasztva. Az első csoport négy egész számból áll, a fennmaradó két csoportban két-két egész szám van.

Megfelelő dátumok: 2017-12-31, 2018-01-31, 0000-00-00, 1029-99-72

Nem egyező dátumok: 2018-01, 2018-01-XX, 2020/02/29

3.2. Megfelelő dátumformátum

Második példánk elfogadja a dátumjelek tartományait, valamint a formázási kényszerünket. Az egyszerűség kedvéért érdeklődésünket az 1900–2999 évekre korlátoztuk.

Most, hogy sikeresen megfeleltünk általános dátumformátumunknak, ezt tovább kell korlátoznunk - annak érdekében, hogy megbizonyosodjunk a dátumok tényleges helyességéről:

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

Itt hármat mutattunk be csoportok egész számtartományoknak, amelyeknek meg kell egyezniük:

  • (19|2[0-9])[0-9]{2} korlátozott évekre terjed ki azzal, hogy egy számmal kezdődik 19 vagy 2X utána néhány számjegy.
  • 0[1-9]|1[012] havi számnak felel meg 01-12
  • 0[1-9]|[12][0-9]|3[01] egy napszámot megad egy tartományban 01-31

Megfelelő dátumok: 1900-01-01, 2205-02-31, 2999-12-31

Nem egyező dátumok: 1899-12-31, 2018-05-35, 2018-13-05, 3000-01-01, 2018-01-XX

3.3. Megfelel a február 29-nek

A szökőévek megfelelő illesztése érdekében először is meg kell tennünk azonosítsa, amikor szökőévvel találkoztunk, majd győződjön meg arról, hogy elfogadjuk-e február 29-ét érvényes dátumként ezekre az évekre.

Mivel a szökőévek száma korlátozott tartományunkban elég nagy, a megfelelő oszthatósági szabályokat kell alkalmaznunk a szűréshez:

  • Ha a szám utolsó két számjegye által alkotott szám osztható 4-gyel, az eredeti szám osztható 4-gyel
  • Ha a szám utolsó két számjegye 00, akkor a szám osztható 100-mal

Itt van egy megoldás:

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

A minta a következő részekből áll:

  • 2000|2400|2800 szökőév halmazához illeszkedik 400 korlátozott tartományban 1900-2999
  • 19|2[0-9](0[48]|[2468][048]|[13579][26])) egyezik mindennel fehér lista évek kombinációi, amelyeknek osztója van 4 és ne legyen elválasztója 100
  • -02-29 mérkőzések Február 2-án

Megfelelő dátumok: 2020-02-29, 2024-02-29, 2400-02-29

Nem egyező dátumok: 2019-02-29, 2100-02-29, 3200-02-29, 2020/02/29

3.4. Megfelelő általános februári napok

Amellett, hogy a szökő években megegyezik február 29-én, ráadásul minden évben meg kell egyeznünk a február összes többi napját (1 - 28):

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

Megfelelő dátumok: 2018-02-01, 2019-02-13, 2020-02-25

Nem egyező dátumok: 2000-02-30, 2400-02-62, 2018/02/28

3.5. 31 napos hónapok egyeztetése

A január, március, május, július, augusztus, október és december hónapoknak 1 és 31 nap között kell lenniük:

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

Megfelelő dátumok: 2018-01-31, 2021-07-31, 2022-08-31

Nem egyező dátumok: 2018-01-32, 2019-03-64, 2018/01/31

3.6. 30 napos hónapok egyeztetése

Az április, június, szeptember és november hónapoknak 1 és 30 nap között kell lenniük:

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

Megfelelő dátumok: 2018-04-30, 2019-06-30, 2020-09-30

Nem egyező dátumok: 2018-04-31, 2019-06-31, 2018/04/30

3.7. Gergely-dátum-egyező

Most már tehetjük kombinálja a fenti mintákat egyetlen egyezőbe, hogy teljes legyen GregorianDateMatcher kielégítve az összes korlátot:

class GregorianDateMatcher implementálja a 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)) $ "); @ Nyilvános logikai egyezések felülírása (karakterlánc dátuma) {return DATE_PATTERN.matcher (dátum) .matches (); }}

Használtunk egy váltakozás karakter „|” hogy legalább egynek megfeleljen a négy ág közül. Tehát a február érvényes dátuma egybeesik a szökőév február 29. első ágával, vagy bármely nap második ágával. 1 nak nek 28. A hátralévő hónapok dátumai egyeznek a harmadik és a negyedik ággal.

Mivel nem optimalizáltuk ezt a mintát a jobb olvashatóság érdekében, nyugodtan kísérletezzen a hosszával.

Ebben a pillanatban kielégítettük az összes korlátozást, amelyeket az elején bevezettünk.

3.8. Megjegyzés a teljesítményről

Az összetett reguláris kifejezések elemzése jelentősen befolyásolhatja a végrehajtási folyamat teljesítményét. A cikk elsődleges célja nem az volt, hogy megtanuljon egy hatékony módszert tesztelni egy húr tagságát az összes lehetséges dátumban.

Fontolja meg a LocalDate.parse () a Java8 biztosítja, ha megbízható és gyors megközelítésre van szükség a dátum érvényesítéséhez.

4. Következtetés

Ebben a cikkben megtanultuk, hogyan használjuk a reguláris kifejezéseket a Gergely-naptár szigorúan formázott dátumának összehangolásához, megadva a formátum, a tartomány és a hónapok hosszának szabályait is.

Az ebben a cikkben bemutatott összes kód elérhető a Github oldalon. Ez egy Maven-alapú projekt, ezért könnyen importálhatónak és futtathatónak kell lennie.