IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

13. diel - Dátum a čas od Javy 8 - Úprava a intervaly

V minulej lekcii, Dátum a čas v Jave 8 - Vytváranie a formátovanie, sme sa naučili vytvárať inštancie tried LocalDate, LocalTime a LocalDateTime a formátovať ich hodnotu.

V dnešnom tutoriáli sa budeme venovať úprave tejto hodnoty a zabehneme aj do časových intervalov.

Potrebné importy

Aby som zbytočne neopakoval, o aké importy v príkladoch ide, naimportujte si ich rovno všetky, ktoré použijeme:

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAmount;

Prevody

Na úvod si ukážme, ako môžeme prevádzať medzi dátumami z inštancií LocalDate, LocalTime a LocalDateTime.

Prevod z LocalDateTime

Z dátumu LocalDateTime prevádzame jednoducho pomocou jeho metód toLocalDate() a toLocalTime().

Prevod na LocalDateTime

Inštanciu LocalDateTime vytvoríme pomocou jednej z of() metód, kde uvedieme zvlášť dátum a čas, napr. takto:

LocalDateTime dateTime = LocalDateTime.of(LocalDate.of(1939, 9, 1), LocalTime.of(10, 0)); // Setting the date to 9/1/1939 10:00
System.out.println(dateTime);

Výstup:

Konzolová aplikácia
1939-09-01T10:00

Ak chceme nastaviť čas na začiatok dňa, môžeme využiť metódu atStartOfDay(). Ďalšou metódou, ktorú môžeme vziať dátum a pripojiť k nemu čas, je atTime(). Pri tejto metóde si môžeme nastaviť vlastnú hodinu a minútu. Ďalší variant príkladu vyššie by teda bol:

LocalDate start = LocalDate.of(1939, 9, 1);
LocalDateTime dayStart = start.atStartOfDay();
LocalDateTime selectedStart = start.atTime(10, 0);
System.out.println(dayStart);
System.out.println(selectedStart);

Na výstupe bude teda začiatok dňa (00:00 hodín) a ďalší čas bude o 10 hodine ako pri minulom príklade:

Konzolová aplikácia
1939-09-01T00:00
1939-09-01T10:00

Úprava hodnoty

K existujúcej inštancii môžeme pripočítať určitý počet dní, hodín a podobne. Slúžia na to metódy začínajúce na plus...() alebo minus...(), snáď netreba vysvetľovať čo robia. Dôležitá poznámka je, že vracajú novú inštanciu s upravenou hodnotou. Inštancia je vo všetkých ohľadoch nemeniteľná (immutable) a akákoľvek zmena spočíta v nahradení za novú (napr. podobne ako to je v Jave s textovými reťazcami).

Skúsme si to a pridajme aktuálnemu dátumu ďalšie 3 dni v týždni:

LocalDateTime dateTime = LocalDateTime.now();
dateTime = dateTime.plusDays(3);
System.out.println(dateTime.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)));

Ak si predstavíme, že je dnes 19.4.2023, výstupom bude:

Konzolová aplikácia
22. 4. 2023

Metódy, ktoré máme k dispozícii, sú nasledujúce:

  • minusDays()
  • minusHours()
  • minusMinutes()
  • minusMonths()
  • minusNanos() - Odoberie z času nanosekundy.
  • minusSeconds()
  • minusWeeks()
  • minusYears()
  • plusDays()
  • plusHours()
  • plusMinutes()
  • plusMonths()
  • plusNanos()
  • plusSeconds()
  • plusWeeks()
  • plusYears()

Do metód môžeme dávať aj záporné hodnoty. Pokiaľ zavoláme napríklad metódu plusDays(-3), je táto metóda rovnaká ako minusDays(3).

Triedy Period a Duration

Okrem vyššie spomenutých metód nájdeme aj 4 všeobecné verzie metód minus() a plus(), ktoré prijímajú interval na pridanie/odobratie. Využijeme ich najmä v prípade, keď dopredu nevieme, či budeme pridávať napr. dni alebo roky, ušetrí nám veľa podmienkovania. Máme k dispozícii triedy Duration a Period, na ktorých si môžeme nechať vrátiť objekt reprezentujúci takýto interval.

Až sa dostaneme k rozhraniam, môžete sa pozrieť, že obe triedy implementujúce spoločné rozhranie TemporalAmount. Zatiaľ si s nimi však nemotajme hlavu.

Upravený kód nášho príkladu by vyzeral takto:

LocalDateTime dateTime = LocalDateTime.now();
dateTime = dateTime.plus(Period.ofDays(3));
System.out.println(dateTime.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)));

Výstup bude rovnaký, ako pri príklade vyššie. of...() metódy majú rovnaké "prípony" ako mali plus/mínus metódy vymenované vyššie:

Konzolová aplikácia
22. 4. 2023

Trieda Duration na rozdiel od triedy Period označuje nejaký časový interval, ktorý vôbec nesúvisí s kalendárom (napr. ako dlho trvá vyrobiť automobil), deň trvá vždy 24 hodín. Trieda Period počíta s prechodom na letný čas, deň teda môže niekedy trvať 23 alebo 25 hodín. Period použijeme pri práci s triedami LocalDate / LocalDateTime, triedu Duration pri práci s časom.

Trieda ChronoUnit

Pre ľahšiu prácu s rôznymi jednotkami ako sú dni, hodiny, minúty a podobne je nám k dispozícii trieda ChronoUnit. Vnútorne používa triedu Duration. Ide teda iba o iný zápis už predchádzajúcich úloh, ale len pre istotu, keby ste ho niekedy stretli, ukážme si ho:

LocalDateTime dateTime = LocalDateTime.now();
dateTime = dateTime.plus(3, ChronoUnit.DAYS);
System.out.println(dateTime.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)));

Len pre úplnosť si dodajme, že trieda ChronoUnit implementuje rozhranie TemporalUnit, keby ste sa s ním neskôr stretli. Teraz rozhranie riešiť nebudeme.

Ako môžeme vidieť, implementácia dátumu a času je v Jave pomerne zložitá, nebudeme tu zabiehať do zbytočných detailov a zameriame sa najmä na praktickú stránku použitia, ako to u nás na sieti väčšinou robíme.

Ďalšie metódy

Ukážme si ešte ďalšie užitočné metódy.

Metóda between()

Ďalšia metóda, ktorú máme k dispozícii, je statická metóda between() na triede Period, ktorá nám umožňuje získať interval, teda rozdiel medzi 2 dátumami (presnejšie objekty s rozhraním Temporal, to je spoločný typ pre triedy LocalDate, LocalDateTime a LocalTime):

LocalDate started = LocalDate.of(1939, 9, 1);
LocalDate ended = LocalDate.of(1945, 9, 2);
TemporalAmount period = Period.between(started, ended);
System.out.println("The World War II lasted for  " + period.get(ChronoUnit.YEARS) + " years and " + period.get(ChronoUnit.DAYS) + " days");

Výstup:

Konzolová aplikácia
The World War II lasted for  6 years and 1 days

Tú istú metódu nájdeme aj na triede Duration, ktorá však pracuje s triedou LocalDateTime namiesto triedy LocalDate. Z intervalu nezistíme počet rokov, pretože roky nemajú pevný počet dní a my už vieme, že Duration nie je nijako spojená s kalendárnym poňatím času.

Metóda until()

Ako posledná stojí za zmienku metóda until(). Táto metóda sa volá priamo nad inštanciami tried LocalDate, LocalDateTime a LocalTime a vracia rovnaký výsledok, ako statická metóda between().

LocalDate started = LocalDate.of(1939, 9, 1);
LocalDate ended = LocalDate.of(1945, 9, 2);
// Period between 9/1/1939 and 9/2/1945
Period period = started.until(ended);
System.out.println("The World War II lasted for  " + period.get(ChronoUnit.YEARS) + " years and " + period.get(ChronoUnit.DAYS) + " days");

Výstup je rovnaký:

Konzolová aplikácia
The World War II lasted for  6 years and 1 days

Nastavenie hodnoty

Hodnotu nastavujeme pomocou metód with...*(), majú opäť tie isté "prípony" ako metódy doposiaľ spomínané. Ako vždy nezabudnite, že ako všetky podobné metódy vracajú novú inštanciu:

LocalDateTime started = LocalDateTime.of(1939, 9, 1, 0, 0);
started = started.withHour(10); // Sets the hour to 10

Reťazenie metód

Vrátenie nových inštancií, ktoré je najmä výsledkom toho, že sú inštancie immutable, zároveň poskytuje tzv. fluent interface (slovensky niekedy prekladané ako plynulé rozhranie). Jedná sa o reťazenie metód, anglicky method chaining. Nehľadajte v tom žiadnu zložitosť, ide len o to, že môžeme väčšinu metód volať po sebe na jednom riadku.

Skúsme si nastaviť kalendár na programátorské vianoce, teda na Halloween (áno, pretože Oct 31 = Dec 25):

LocalDate started = LocalDate.of(1939, 9, 1);
started = started.withMonth(10).withDayOfMonth(31);

V budúcej lekcii, Dátum a čas v Jave 8 - Parsovanie a porovnávanie, sa pozrieme na parsovanie a porovnávanie dátumu a času.


 

Predchádzajúci článok
Dátum a čas v Jave 8 - Vytváranie a formátovanie
Všetky články v sekcii
Objektovo orientované programovanie v Jave
Preskočiť článok
(neodporúčame)
Dátum a čas v Jave 8 - Parsovanie a porovnávanie
Článok pre vás napísal David Hartinger
Avatar
Užívateľské hodnotenie:
19 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