Lekce 11 - Datum a čas v Kotlin - Vytváření a formátování
V dnešním tutoriálu se pustíme do dalších tříd, které Kotlin poskytuje pomocí Javy. Ukážeme si, jak se v Kotlinu pracuje s datem a časem.
Datum a čas v Kotlin
Kotlin nemá žádnou vlastní implementaci data a času. Proč by se také vývojáři Kotlinu měli soustředit na něco, co již vytvořil Oracle v Javě 8? Jak jsem zdůrazňoval v úvodní lekci základů Kotlinu, Kotlin a Java jsou "kompatibilní", běží na stejném virtuálním stroji a proto mohou sdílet své třídy. Kotlin pro datum a čas proto využívá javovské třídy.
Bohužel se v minulosti implementace data a času v Javě hned několikrát radikálně změnila a jelikož předešlé pokusy o ni nebyly příliš uspokojivé, rozšířily se dokonce i externí knihovny, které ji nahrazují. Ačkoli vy budete používat tu nejnovější, kterou Oracle představil ve verzi Javy 8, jistě se časem ve starších projektech setkáte s legacy třídami, které se k tomuto účelu využívaly v minulosti. Jsou to:
Date
- TřídaDate
z balíčkujava.util
byla prvním pokusem o uložení data a času v Javě a nalézá se v ní již jen z důvodu zpětné kompatibility. Téměř všechny její metody jsou označené jako zastaralé a proto se s ní zde nebudeme vůbec zabývat. Pokud ji někde potkáte, bude vám muset stačit oficiální dokumentace - https://docs.oracle.com/…il/Date.htmlCalendar
- TřídaCalendar
je první náhradou původníhoDate
a nově přinesla např. lokalizaci a pohodlnější manipulaci s vnitřní hodnotou. Mohli jsme jednoduše přičítat časové intervaly a podobně. V nových projektech ji nepoužívejte. Pravděpodobně na ni dříve či později narazíte a v tu chvíli se vám bude hodit článek, který je napsaný pro Javu, Datum a čas v Javě pomocí třídy Calendar.LocalDate
,LocalTime
aLocalDateTime
- Od Javy 8 se objevila třídaLocalDateTime
a její varianty jen pro samotné datum a samotný čas. Oproti tříděCalendar
je immutable (to zjednodušeně znamená, že s ní lze pracovat pomocí vláken, více dále v kurzu) a ctí tzv. fluent interface (někdy překládané do češtiny jako plynulé/tekoucí rozhraní), ale říkejme mu spíše řetězení metod. Také nemíchá získávání a nastavování hodnot v jedné metodě, ale poskytuje k tomuto účelu oddělené metody. Původní kalendář kvalitativně převyšuje a nahrazuje.- Joda-Time - Již zmíněné neúspěšné pokusy o
implementaci data a času do Javy samozřejmě způsobily potřebu kvalitní
náhrady a jako častá alternativa se uchytila knihovna Joda-Time. Nelze si
nevšimnout, že Date API Javy 8 se touto knihovnou silně inspiruje a vychází
ze stejných konceptů. Joda-Time je dost možná ještě o něco
kvalitnější, ale doporučoval bych držet se spíše již poměrně kvalitní
standardní třídy
LocalDateTime
a vyhnout se zbytečným závislostem na knihovnách třetích stran.
Velké množství tříd je, ať chceme nebo ne, každodenní chléb Java/Kotlin programátora. Čekají nás celkem 3 články na toto téma. Tak vzhůru do toho!
LocalDateTime, LocalDate a LocalTime
Již víme, že budeme používat třídy LocalDateTime
,
LocalDate
a LocalTime
a to podle toho, zda
potřebujeme ukládat datum i čas (např. odlet letadla), pouze datum (např.
datum narození) a pouze čas (např: 12:00, přesnost na nanosekundy).
Vytvoření instancí
Začněme tím, jak lze instance jednotlivých tříd vytvořit. Vytvoříme
si nový projekt s názvem DatumACas
.
Vytvoření dle zadání
Když chceme vytvořit novou instanci nějaké ze tříd, zavoláme na
třídě tovární metodu of()
a zadáme
patřičné parametry. Metoda má více přetížení, např. můžeme a
nemusíme zadat vteřiny, měsíc můžeme zadat jak číslem, tak pomocí tzv.
výčtového typu (což je asi přehlednější, více se o nich dozvíme dále
v kurzu) a podobně.
{KOTLIN_OOP}
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.Month
fun main(args: Array<String>) {
// Datum a čas
val datumCas = LocalDateTime.of(2016, Month.APRIL, 15, 3, 15)
println(datumCas)
// Pouze datum
val datum = LocalDate.of(2016, Month.APRIL, 15)
println(datum)
// Pouze čas
val cas = LocalTime.of(3, 15, 10)
println(cas)
}
{/KOTLIN_OOP}
Nezapomeňte jednotlivé třídy naimportovat:
import java.time.LocalDate import java.time.LocalDateTime import java.time.LocalTime import java.time.Month
Výstup:
2016-04-15T03:15 2016-04-15 03:15:10
Vytvoření dle aktuálního data a času
Ve svých aplikacích budeme samozřejmě potřebovat získat také
aktuální datum a čas. K tomu slouží další tovární
metoda, now()
, kterou voláme opět přímo na
příslušné třídě:
// Aktuální datum a čas val datumCas = LocalDateTime.now() println(datumCas) // Aktuální datum val datum = LocalDate.now() println(datum) // Aktuální čas val cas = LocalTime.now() println(cas)
Formátování
Jelikož výstup není úplně uživatelsky přívětivý, pojďme si
ukázat, jak jej naformátovat. Asi vás nepřekvapí, že k tomu použijeme
metodu format()
, již normálně na instanci.
Samotné formátování zajišťuje třída DateTimeFormatter
, nás
na ni budou zajímat tyto statické metody:
ofLocalizedDateTime()
- Zformátuje na lokální formát data a času. Zadáváme dva parametry - styl data a styl času. Máme na výběr plný (full) až krátký (short) formát, což platí u všech formátovacích metod kromě ofPattern().ofLocalizedDate()
- Zformátuje na lokální formát dataofLocalizedTime()
- Zformátuje na lokální formát časuofPattern()
- Oproti metodám výše, které formátovaly dle regionálního nastavení daného uživatele, zde můžeme specifikovat vlastní formát pomocí textového řetězce a zástupných znaků. Např. den, měsíc, rok, hodiny, minuty a sekundy (vše čísly) by se předalo jako "d.M.y H:m:ss". Popis významu všech symbolů by byl zbytečně vyčerpávající a najdete jej v oficiální dokumentaci Javy - https://docs.oracle.com/…rmatter.html
Udělejme si příklad:
{KOTLIN_OOP}
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.Month
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
fun main(args: Array<String>) {
val dateTime = LocalDateTime.now()
println(dateTime.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM)))
println(dateTime.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)))
println(dateTime.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG, FormatStyle.SHORT)))
println(dateTime.format(DateTimeFormatter.ofPattern("d.M.y H:m:ss")))
}
{/KOTLIN_OOP}
Nezapomeňte si dodat importy:
import java.time.format.DateTimeFormatter import java.time.format.FormatStyle
Výsledek:
20:13:04 Pátek, 9. prosince 2016 9 prosince 2016 20:13 9.12.2016 20:13:04
Datum a čas se bude zobrazovat lokalizován pro jazyk vašeho operačního systému.
Všimněte si, že metodám specifikujeme v parametrech i již zmíněný
styl (enum FormatStyle
), který udává zda chceme výpis stručný
až vyčerpávající. Máme k dispozici tyto hodnoty:
FULL
- Vrací datum jako Pátek, 6. prosince 2016, pro čas nemá význam a při použití vyvolá výjimku.LONG
- Vrací datum jako 6. prosince 2016, pro čas nemá význam a při použití vyvolá výjimku.MEDIUM
- Vrací datum jako 6. pros 2016, čas jako 3:15:10.SHORT
- Vrací datum jako 6.12.2016, čas jako 3:15.
Na třídě DateTimeFormatter
jsou také dostupné
předdefinované formáty jako konstanty, ale české formáty tam
nehledejte.
V příští lekci, Datum a čas v Kotlin - Úprava a intervaly, budeme pokračovat s datem a časem, protože je
to v Kotlin poměrně rozsáhlé téma. Ukážeme si převody mezi
LocalDate
, LocalTime
a LocalDateTime
, jak
upravovat vnitřní hodnotu a také práci s intervaly.