Vianoce v ITnetwork sú tu! Dobí si teraz kredity a získaj až 80 % extra kreditov na e-learningové kurzy ZADARMO. Zisti viac.
Hľadáme nové posily do ITnetwork tímu. Pozri sa na voľné pozície a pridaj sa k najagilnejšej firme na trhu - Viac informácií.

14. diel - Dátum a čas v Jave 8 - Parsovanie a porovnávanie

V minulej lekcii, Dátum a čas od Javy 8 - Úprava a intervaly, sme sa venovali prevedeniu, úprave hodnoty a časovým intervalom.

V dnešnom tutoriále sa pozrieme na čítanie hodnoty, parsovanie a porovnávanie.

Čítanie hodnoty

Hodnotu čítame pomocou metód začínajúcich na get*(), tu nás ani nič neprekvapí:

LocalDate halloween = LocalDate.of(2016, Month.OCTOBER, 31);
System.out.println("Year: " + halloween.getYear() + ", month: " + halloween.getMonthValue() + ", day: " + halloween.getDayOfMonth());

Výsledok:

Konzolová aplikácia
Year: 2016, month: 10, day: 31

Všimnite si, že na získanie čísla mesiaca sme použili metódu getMonthValue(), pretože metóda getMonth() by vrátila hodnotu z vymenovaného typu Month.

Ak by sme sa stretli so staršou triedou Calendar, musíme si dať pozor. Mesiace tam sú číslované od 0 namiesto od 1, ako je to v triedach LocalDate/LocalDateTime.

Parsovanie dátumu a času

Dátum a čas budeme samozrejme často dostávať v textovej podobe, napr. od používateľa z konzoly, zo súboru alebo z databázy. Asi tušíte, že na vytvorenie LocalDateTime z takejto textovej hodnoty použijeme metódu parse() priamo na dátovom type, ako to v Jave robíme vždy.

Trieda LocalDate predpokladá dátum vo formáte yyyy-mm-dd, trieda LocalDateTime dátum a čas vo formáte yyyy-mm-ddThh:mm:ss a trieda LocalTime čas vo formáte hh:mm:ss. Všetky čísla pred sebou musia mať nuly, ak sú menšie ako 10. Písmeno T uprostred formátu nie je preklep, ale naozaj oddelenie dátumu a času. To už môžeme vedieť z predchádzajúcich lekcií. Skúsme si dátum a čas:

LocalDateTime dateTime = LocalDateTime.parse("2016-12-08T10:20:30");
LocalDate date = LocalDate.parse("2016-12-08");
LocalTime time = LocalTime.parse("10:20:30");

System.out.println(dateTime.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)));
System.out.println(date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)));
System.out.println(time.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM)));

Nezabudneme zase na importy:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;

Možný výsledok:

Konzolová aplikácia
8. 12. 2016 10:20:30
8. 12. 2016
10:20:30

Výsledok je samozrejme rôznorodý, záleží na lokalizácii systému. Preto môžete mať výstup iný.

Vlastný formát

Oveľa častejšie ale budeme chcieť naparsovať dátum a čas v slovenskom tvare alebo v akomkoľvek inom tvare, východiskové oddeľovanie dátumu a času pomocou písmena T nie je práve user-friendly :)

LocalDateTime dateTime = LocalDateTime.parse("12/08/2016 10:20:30", DateTimeFormatter.ofPattern("M/d/y HH:mm:ss"));
LocalDate date = LocalDate.parse("12/8/2016", DateTimeFormatter.ofPattern("M/d/y"));
LocalTime time = LocalTime.parse("10:20:30", DateTimeFormatter.ofPattern("H:m:ss"));

System.out.println(dateTime.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)));
System.out.println(date.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)));
System.out.println(time.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM)));

Výsledok:

Konzolová aplikácia
8. 12. 2016 10:20:30
8. 12. 2016
10:20:30

Keby sme chceli napríklad špecifikovať vlastný formát v metóde ofPattern() a formát by musel obsahovať napríklad kľúčové písmeno m (normálne by to chcelo počet minút), môžeme ho escapovať pomocou jednoduchých apostrofov '. Skúsime naparsovať napríklad 10h:20m:30s:

LocalTime time = LocalTime.parse("10h:20m:30s", DateTimeFormatter.ofPattern("H'h':m'm':ss's'"));
System.out.println(time);

Výstup:

Konzolová aplikácia
10:20:30

Porovnávanie inštancií

Pretože Java nepodporuje preťažovanie operátorov, dátumy porovnávame pomocou metód na to určených. Metódy začínajú na is*(), vymenujme si ich:

  • isAfter(datum) - Vracia, či je inštancia za dátumom/dátumom a časom odovzdávanej inštancie (či je hodnota väčšia).
  • isBefore(datum) - Vracia, či je inštancia pred dátumom/dátumom a časom odovzdávanej inštancie (či je hodnota menšia).
  • isEqual(datum) - Vracia, či je inštancia nastavená na rovnaký dátum a/alebo čas ako je odovzdávaná inštancia (či je hodnota rovnaká).

To bolo jednoduché, však? Keď už sme pri metódach is*(), spomeňme si aj zvyšné dve:

  • isLeapYear() - Vracia, či je inštancia nastavená na priestupný rok alebo nie.
  • isSupported(ChronoUnit) - Vracia, či inštancia podporuje prácu s danou chrono jednotkou (napr. LocalDate nebude vedieť ChronoUnit.HOURS, pretože neobsahuje informáciu o čase).

Ukážme si príklad:

LocalDate halloween = LocalDate.of(2016, 10, 31);
LocalDate christmas = LocalDate.of(2016, 12, 25);
System.out.println("Halloween after Christmas: " + halloween.isAfter(christmas));
System.out.println("Halloween before Christmas: " + halloween.isBefore(christmas));
System.out.println("equal Christmas - Halloween: " + christmas.isEqual(halloween));
System.out.println("equal Halloween - Halloween: " + halloween.isEqual(halloween));
System.out.println("leap year 2016: " + halloween.isLeapYear());
System.out.println("leap year 2017: " + halloween.withYear(2017).isLeapYear());
System.out.println("supports hours: " + halloween.isSupported(ChronoUnit.HOURS));
System.out.println("supports years: " + halloween.isSupported(ChronoUnit.YEARS));

Doplníme chýbajúci import:

import java.time.temporal.ChronoUnit;

Výsledok:

Konzolová aplikácia
Halloween after Christmas: false
Halloween before Christmas: true
equal Christmas - Halloween: false
equal Halloween - Halloween: true
leap year 2016: true
leap year 2017: false
supports hours: false
supports years: true

Ďalšie triedy

Okrem tried LocalDateTime, LocalDate a LocalTime sa môžeme stretnúť aj s niekoľkými ďalšími triedami, ktoré využijeme skôr v aplikáciách, ktoré sú na práci s dátumom a časom založené. Nemusíme sa ich báť, vo väčšine prípadov si vystačíme s triedou LocalDateTime, ale mali by sme o nich mať povedomie.

Instant

Trieda Instant je pre dátum a čas, ale nie v poňatí kalendára a prechodov na letný čas. Je to počet nanosekúnd od dátumu 1.1.1970, teda jeden bod na časovej osi UTC (univerzálneho času). Keď si kdekoľvek na Zemi napíšeme aplikáciu s týmto kódom:

Instant instantNow = Instant.now();
System.out.println(instantNow);

A doplníme import:

import java.time.Instant;

Dostaneme vo výstupe vždy to isté, napríklad:

Konzolová aplikácia
2023-04-20T10:36:06.541863800Z

Trieda Instant pozná len univerzálny čas a ten sa bude líšiť od reálneho času v danej oblasti.

Triedy OffsetDateTime a ZonedDateTime

Už vieme, že Instant je univerzálny čas a LocalDateTime má v sebe ten čas, ktorý je na danom území. Zo samotného LocalDateTime nedokážeme získať bod na univerzálnej časovej osi, pretože nevieme, na akom je území.

To, čo nám chýba, je kombinácia týchto dvoch, lokálne korektný čas, ktorý by v sebe zároveň niesol informáciu o území (časovej zóne) a tým pádom by mohol byť univerzálne prevádzaný medzi rôznymi časovými zónami. Práve na to slúži trieda ZonedDateTime.

V Jave nájdeme aj triedu OffsetDateTime, ktorá je takým medzičlánkom, ktorý umožňuje zaznamenať časový posun, ale nemá plnú podporu zón.

Trieda ZoneId

Časové zóny sú v Jave reprezentované triedou ZoneId. Poďme si urobiť jednoduchú ukážku dátumu s časovou zónou.

V nasledujúcej ukážke použijeme podčiarknutie _. Na slovenskej klávesnici ho píšeme pomocou Shift a nasledujúcej klávesy:

Podčiarknutie - Objektovo orientované programovanie v Jave

Dátum s časovým pásmom vyzerá nasledovne:

ZonedDateTime localDateTime = ZonedDateTime.now(ZoneId.of("America/New_York"));
System.out.println(localDateTime);

Nezabudneme na potrebné balíčky:

import java.time.ZoneId;
import java.time.ZonedDateTime;

Výstup:

Konzolová aplikácia
2017-02-02T06:37:11.026-05:00[America/New_York]

Áno, je to veľa tried, berme to skôr ako informácie, ku ktorým sa môžeme vrátiť, až ich budeme potrebovať. Je dobré mať povedomie o tom, ako sa s dátumom pracuje. V Jave je tried vždy viac než v ostatných jazykoch. Skúsme si vypestovať trpezlivosť a odolnosť voči tejto skutočnosti, veď predsa sme kvôli tomu lepšie platení :) Nabudúce budeme zas chvíľu prakticky programovať, aby sme si oddýchli od teórie.

Epochy

Na úplný záver si poďme ešte predstaviť niekoľko posledných metód na triede LocalDateTime.

  • ofEpochSecond() - Statická metóda nám umožňuje vytvoriť dátum a čas z tzv. Unix timestamp, v ktorom sa dátum a čas často ukladal najmä v minulosti. Je to veľké číslo označujúce počet sekúnd od dátumu 1.1.1970 (začiatok unixovej epochy), musíme uviesť aj nanosekundy (väčšinou 0) a časovú zónu, čo je najčastejšie ZoneOffset.UTC. Metóda je dostupná aj na triede LocalDate ako metóda ofEpochDay(), kde prijíma počet dní namiesto sekúnd.
  • toEpochSecond() a toEpochDay() - Metódy opačné k dvom predchádzajúcim, prevádzajú hodnotu na počet sekúnd/dní od roku 1970.

To je k dátumu a času od Javy verzie 8 naozaj všetko.

V nasledujúcom cvičení, Riešené úlohy k 12. lekcii OOP v Jave, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.


 

Predchádzajúci článok
Dátum a čas od Javy 8 - Úprava a intervaly
Všetky články v sekcii
Objektovo orientované programovanie v Jave
Preskočiť článok
(neodporúčame)
Riešené úlohy k 12. lekcii OOP v Jave
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
28 hlasov
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David sa informačné technológie naučil na Unicorn University - prestížnej súkromnej vysokej škole IT a ekonómie.
Aktivity