IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 12 - Datum a čas v Kotlin - Úprava a intervaly

V minulé lekci, Datum a čas v Kotlin - Vytváření a formátování, jsme se naučili vytvářet instance LocalDate, LocalTime a LocalDateTime a formátovat jejich hodnotu.

V dnešním Kotlin 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:

val zacatek = LocalDate.of(1939, 9, 1)
val 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:

val zacatek = LocalDate.of(1939, 9, 1)
val datumCas = zacatek.atStartOfDay()
val 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 Kotlinu s textovými řetězci).

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

fun main(args: Array<String>) {

var datumCas = LocalDateTime.now()
datumCas = datumCas.plusDays(3)
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.

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:

fun main(args: Array<String>) {

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

}

Protože nám Kotlin umožňuje tzv. přetěžování operátorů, více dále v kurzu, můžeme kód výše zapsat i tímto způsobem:

fun main(args: Array<String>) {

var datumCas = LocalDateTime.now()
datumCas += Period.ofDays(3)
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/LocalDateTime, 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:

fun main(args: Array<String>) {

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

}

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 Kotlinu 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.

fun main(args: Array<String>) {

val zacatek = LocalDate.of(1939, 9, 1)
val konec = LocalDate.of(1945, 9, 2)
val doba = Period.between(zacatek, konec)
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.

var zacatek = LocalDate.of(1939, 9, 1)
zacatek = zacatek.withYear(1945) // Nastaví rok na 1945

Ř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).

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

V příští lekci, Datum a čas v Kotlin - Parsování a porovnávání, dokončíme datum a čas v Kotlin. Ukážeme si jak hodnoty číst a jak datum a čas v Kotlinu parsovat.


 

Předchozí článek
Datum a čas v Kotlin - Vytváření a formátování
Všechny články v sekci
Objektově orientované programování v Kotlin
Přeskočit článek
(nedoporučujeme)
Datum a čas v Kotlin - Parsování a porovnávání
Článek pro vás napsal Samuel Kodytek
Avatar
Uživatelské hodnocení:
11 hlasů
Autor se věnuje všem jazykům okolo JVM. Rád pomáhá lidem, kteří se zajímají o programování. Věří, že všichni mají šanci se naučit programovat, jen je potřeba prorazit tu bariéru, který se říká lenost.
Aktivity