12. diel - Dátum a čas v Kotlin - Úprava a intervaly
V minulej lekcii, Dátum a čas v Kotlin - Vytváranie a formátovanie , sme sa naučili vytvárať inštancie
LocalDate
, LocalTime
a LocalDateTime
a
formátovať ich hodnotu. V dnešnom Kotlin tutoriálu sa budeme venovať
úprave tejto hodnoty a zabehneme aj do časových intervalov.
Prevody
Na úvod si ukážme, ako môžeme prevádzať medzi LocalDate
,
LocalTime
a LocalDateTime
.
Prevod z LocalDateTime
Z LocalDateTime
prevádzame jednoducho pomocou jeho metód
toLocalDate()
a
toLocalTime()
.
Prevod na LocalDateTime
LocalDateTime
vytvoríme pomocou jednej z of*()
metód, kde uvedieme zvlášť dátum a čas, napr. Takto:
val zacatek = LocalDate.of(1939, 9, 1) val datumCas = LocalDateTime.of(zacatek, LocalTime.of(10, 0))
Ak chceme nastaviť čas na začiatok dňa, môžeme využiť metódy
atStartOfDay()
. Ďalšou metódou, ktorú môžeme vziať dátum a
pripojiť k nemu čas, je atTime()
. Ďalšie variant príkladu
vyššie by teda bola:
val zacatek = LocalDate.of(1939, 9, 1) val datumCas = zacatek.atStartOfDay() val datumCas2 = zacatek.atTime(0, 0)
Úprava hodnoty
K existujúcej inštanciu môžeme pripísať určitý počet dní, hodín a
podobne. Slúži 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 Kotlinu s textovými
reťazcami).
Skúsme si to a pridajme aktuálnemu dátumu ďalšie 3 dni v týždni:
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
{KOTLIN_CONSOLE}
var datumCas = LocalDateTime.now()
datumCas = datumCas.plusDays(3)
println(datumCas.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)))
{/KOTLIN_CONSOLE}
výsledok:
9.1.2017
Metódy, ktoré máme k dispozícii, sú nasledujúce:
minusDays()
minusHours()
minusMinutes()
minusMonths()
minusNanos()
minusSeconds()
minusWeeks()
minusYears()
plusDays()
plusHours()
plusMinutes()
plusMonths()
plusNanos()
plusSeconds()
plusWeeks()
plusYears()
Period a Duration
Okrem vyššie spomenutých metód nájdeme aj 4 všeobecnej verzie metód
minus()
a plus()
, ktoré prijímajú interval na
pridanie / odobratie. Využijeme je najmä v prípade, keď dopredu nevieme, či
budeme pridávať napr. Dni alebo roky, ušetrí nám veľa podmínkování.
Máme k dispozícii triedy Duration
a
Period
, na ktorých si môžeme nechať vrátiť
objekt reprezentujúci taký interval.
Až sa dostaneme k rozhraním, môžete sa pozrieť, že obe
triedy implementujúce spoločné rozhranie TemporalAmount
. Zatiaľ
si s nimi však nemotejme hlavu.
Upravený kód nášho príkladu by vyzeral takto:
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
import java.time.Period
{KOTLIN_CONSOLE}
var datumCas = LocalDateTime.now()
datumCas = datumCas.plus(Period.ofDays(3))
println(datumCas.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)))
{/KOTLIN_CONSOLE}
Pretože nám Kotlin umožňuje tzv. Preťažovanie operátorov, viac ďalej v kurze, môžeme kód vyššie zapísať aj týmto spôsobom:
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
import java.time.Period
{KOTLIN_CONSOLE}
var datumCas = LocalDateTime.now()
datumCas += Period.ofDays(3)
println(datumCas.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)))
{/KOTLIN_CONSOLE}
Výstup bude rovnaký, ako v príklade vyššie. Of...*()
metódy majú rovnaké "prípony" ako mali plus / mínus metódy uvedené
vyššie.
Rozdiel medzi Period
a Duration
je ten, že
Duration 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. 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 LocalDate
/ LocalDateTime
, Duration
pri práci s časom.
ChronoUnit
Pre ľahšie 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
, jedná sa teda iba o iný zápis už
predchádzajúcich úloh, ale len pre istotu, keby ste ho niekedy stretli,
ukážme si ho:
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
import java.time.temporal.ChronoUnit
{KOTLIN_CONSOLE}
var datumCas = LocalDateTime.now()
datumCas = datumCas.plus(3, ChronoUnit.DAYS)
println(datumCas.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)))
{/KOTLIN_CONSOLE}
Len pre úplnosť si dodajme, že ChronoUnit
implementuje rozhranie TemporalUnit
, keby ste sa s ním neskôr
stretli. Teraz rozhranie riešiť nebudeme.
Ako vidíte, implementácia dátumu a času je v Kotlinu pomerne zložitá, nebudeme tu zabiehať do zbytočných detailov a zameriame sa najmä na praktickú stránku použitia, ako to na ITnetwork väčšinou robíme.
Between ()
Ako posledný stojí za zmienku statická metóda between()
na
triede Period
, ktorá nám umožňuje získať interval, teda
rozdiel medzi 2 dátumy (presnejšie objekty s rozhraním Temporal
,
to je spoločný typ pre LocalDate
, LocalDateTime
a
LocalTime
). Zámerne tu nebudem písať češtinsky správne "medzi
dvoma dátumami", pretože je to v IT zavádzajúce slovo.
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
import java.time.temporal.ChronoUnit
import java.time.Period
{KOTLIN_CONSOLE}
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í")
{/KOTLIN_CONSOLE}
Tú istú metódu nájdeme aj na triede Duration
, ktorá však
pracuje s LocalDateTime
miesto s LocalDate
. Z
intervale 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.
Nastavenie hodnoty
Hodnotu nastavujeme pomocou metód with...*()
, majú opäť tie
isté "prípony" ako metódy doteraz spomínané. Ako vždy nezabudnite, že ako
všetky podobné metódy vracajú novú inštanciu.
var zacatek = LocalDate.of(1939, 9, 1) zacatek = zacatek.withYear(1945) // Nastaví rok na 1945
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 31 OCT = 25 DEC).
var zacatek = LocalDate.of(1939, 9, 1) zacatek = zacatek.withMonth(9).withDayOfMonth(31)
V budúcej lekcii, Dátum a čas v Kotlin - parsovanie a porovnávanie , budeme pokračovať a dátum a čas v Kotlinu dokončíme. Ukážeme si ako hodnoty čítať a ako dátum a čas v Kotlinu parsovať.