13. díl - Datum a čas v Javě 8 - Úprava a intervaly

Java Objektově orientované programování Datum a čas v Javě 8 - Úprava a intervaly

ONEbit hosting Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci o práci s datem a časem v Javě jsme se naučili vytvářet instance LocalDate, LocalTime a LocalDateTime a formátovat jejich hodnotu. V dnešním tutoriálu se budeme věnovat úpravě této hodnoty a zaběhneme i do časových intervalů.

Převody

Na úvod si ukažme, jak můžeme převádět mezi LocalDate, LocalTime a LocalDateTime.

Převod z LocalDateTime

Z LocalDateTime převádíme jednoduše pomocí jeho metod toLocalDate() a toLocalTime().

Převod na LocalDateTime

LocalDateTime vytvoříme pomocí jedné z of*() metod, kde uvedeme zvlášť datum a čas, např. takto:

LocalDate zacatek = LocalDate.of(1939, 9, 1);
LocalDateTime datumCas = LocalDateTime.of(zacatek, LocalTime.of(10, 0));

Pokud chceme nastavit čas na začátek dne, můžeme využít metody atStartOfDay(). Další metodou, kterou můžeme vzít datum a připojit k němu čas, je atTime(). Další varianta příkladu výše by tedy byla:

LocalDate zacatek = LocalDate.of(1939, 9, 1);
LocalDateTime datumCas = zacatek.atStartOfDay();
LocalDateTime datumCas2 = zacatek.atTime(0, 0);

Úprava hodnoty

K existující instanci můžeme přičítat určitý počet dní, hodin a podobně. Slouží k tomu metody začínající na plus...() nebo minus...(), snad netřeba vysvětlovat co dělají. Důležitá poznámka je, že vracejí novou instanci s upravenou hodnotou. Instance je ve všech ohledech neměnitelná (immutable) a jakákoli změna spočítá v nahrazení za novou (např. podobně jako to je v Javě s textovými řetězci).

Zkusme si to a přidejme aktuálnímu datu další 3 dny v týdnu:

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

Výsledek:

9.1.2017

Metody, které máme k dispozici, jsou následující:

  • minusDays()
  • minusHours()
  • minusMinutes()
  • minusMonths()
  • minusNanos()
  • minusSeconds()
  • minusWeeks()
  • minusYears()
  • plusDays()
  • plusHours()
  • plusMinutes()
  • plusMonths()
  • plusNanos()
  • plusSeconds()
  • plusWeeks()
  • plusYears()

Period a Duration

Kromě výše zmíněných metod nalezneme i 4 obecné verze metod minus() a plus(), které přijímají interval k přidání/odebrání. Využijeme je zejména v případě, kdy dopředu nevíme, zda budeme přidávat např. dny nebo roky, ušetří nám spoustu podmínkování. Máme k dispozici třídy Duration a Period, na kterých si můžeme nechat vrátit objekt reprezentující takový interval.

Pozn.: Až se dostaneme k rozhraním, můžete se podívat, že obě třídy implementující společné rozhraní TemporalAmount. Zatím si s nimi však nemotejme hlavu.

Upravený kód našeho příkladu by vypadal takto:

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

Výstup bude stejný, jako u příkladu výše. Of...*() metody mají stejné "přípony" jako měly plus/minus metody vyjmenované výše.

Rozdíl mezi Period a Duration je ten, že Duration označuje nějaký časový interval, který vůbec nesouvisí s kalendářem (např. jak dlouho trvá vyrobit automobil), den trvá vždy 24 hodin. Period počítá s přechodem na letní čas, den tedy může někdy trvat 23 nebo 25 hodin. Period použijeme při práci s LocalDate/Local­DateTime, Duration při práci s časem.

ChronoUnit

Pro snažší práci s různými jednotkami jako jsou dny, hodiny, minuty a podobně je nám k dispozici třída ChronoUnit. Vnitřně používá třídu Duration, jedná se tedy pouze o jiný zápis již předchozích úloh, ale jen pro jistotu, kdybyste jej někdy potkali, ukažme si jej:

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

Pozn.: Jen pro úplnost si dodejme, že ChronoUnit implementuje rozhraní TemporalUnit, kdybyste se s ním později setkali. Nyní rozhraní řešit nebudeme.

Jak vidíte, implementace data a času je v Javě poměrně složitá, nebudeme tu zabíhat do zbytečných detailů a zaměříme se zejména na praktickou stránku použití, jak to na ITnetwork většinou děláme.

Between()

Jako poslední stojí za zmínku statická metoda between() na třídě Period, která nám umožňuje získat interval, tedy rozdíl mezi 2 datumy (přesněji objekty s rozhraním Temporal, to je společný typ pro LocalDate, LocalDateTime a LocalTime). Záměrně zde nebudu psát češtinsky správně "mezi dvěma daty", jelikož je to v IT zavádějící slovo.

LocalDate zacatek = LocalDate.of(1939, 9, 1);
LocalDate konec = LocalDate.of(1945, 9, 2);
TemporalAmount doba = Period.between(zacatek, konec);
System.out.println("II. světová válka trvala " + doba.get(ChronoUnit.YEARS) + " let a " + doba.get(ChronoUnit.DAYS) + " dní");

Tu samou metodu nalezneme i na třídě Duration, která ovšem pracuje s LocalDateTime místo s LocalDate. Z intervalu nezjistíme počet let, protože roky nemají pevný počet dnů a my již víme, že Duration není nijak spojená s kalendářním pojetím času.

Nastavení hodnoty

Hodnotu nastavujeme pomocí metod with...*(), mají opět ty samé "přípony" jako metody doposud zmíněné. Jako vždy nezapomeňte, že jako všechny podobné metody vracejí novou instanci.

LocalDate zacatek = LocalDate.of(1939, 9, 1);
zacatek = zacatek.withHour(10); // Nastaví hodiny na 10

Řetězení metod

Vracení nových instancí, které je zejména výsledkem toho, že jsou instance immutable, zároveň poskytuje tzv. fluent interface (česky někdy překládané jako plynulé rozhraní). Jedná se o řetězení metod, anglicky "method chaining". Nehledejte v tom žádnou složitost, jde jen o to, že můžeme většinu metod volat po sobě na jednom řádku.

Zkusme si nastavit kalendář na programátorské vánoce, tedy na Halloween (ano, protože 31 OCT = 25 DEC).

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

Příště budeme pokračovat a datum a čas v Javě dokončíme. Ukážeme si jak hodnoty číst a jak datum a čas v Javě parsovat.


 

 

Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
1 hlasů
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity (3)

 

 

Komentáře

Avatar
Peter Gasparik:23. února 19:11

Nie je v texte spojenie dvoch slov ?

neměnitelná (immutable) a jakákoli změna spočítá v nahrazení za novou (např. podobně jako to je v Javě s textovými řetězci).

Odpovědět 23. února 19:11
while (noSuccess) { tryAgain(); if (Dead) break;
Avatar
Peter Gasparik:23. února 19:38

Ten kód vyhadzuje chybu, usudzujem, že tam má byť október = Month(10) ..

LocalDate zacatek = LocalDate.of(1939, 9, 1);
zacatek = zacatek.withMonth(9).withDayOfMonth(31);
Odpovědět 23. února 19:38
while (noSuccess) { tryAgain(); if (Dead) break;
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.