13. diel - Dátum a čas v Kotlin - parsovanie a porovnávanie
V minulej lekcii, Dátum a čas v Kotlin - Úprava a intervaly , sme sa venovali prevedenie, úprave hodnoty a časovým intervalom. V dnešnom Kotlin tutoriálu túto tému dokončíme, pozrieme sa na čítanie hodnoty, parsování a porovnávanie.
Čítanie hodnoty
Hodnotu čítame pomocou vlastností, tu nás ani nič neprekvapí:
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}
val halloween = LocalDate.of(2016, Month.OCTOBER, 31)
println("Rok: " + halloween.year + ", měsíc: " + halloween.monthValue + ", den: " + halloween.dayOfMonth)
{/KOTLIN_CONSOLE}
Všimnite si, že keď nám IntelliJ radia (pomocou Ctrl + Space), tak sa po ľavej strane zobrazujú javovské názvy metód, ktoré sú pregenerovanie do vlastností kotlinou, pre ľahšiu prácu (to v zátvorke, šedým písmom).
A výsledok:
Rok: 2016, měsíc: 10, den: 31
Všimnite si, že pre získanie čísla mesiaca sme použili
monthValue
, pretože month
by vrátil hodnotu z
vymenovaného typu Month
.
Ak sa stretnete so staršou triedou Calendar
,
dajte si pozor, pretože tam sú mesiace očíslované od 0
namiesto od 1
, ako je to v LocalDate
/
LocalDateTime
.
Parsovanie dátumu a času
Dátum a čas budeme samozrejme často dostávať v textovej podobe, napr. Od
užívateľa z konzoly, zo súboru alebo z databázy. Asi tušíte, že na
vytvorenie LocalDateTime
z takejto textovej hodnoty použijeme
metódu parse()
priamo na dátovom typu, ako to v Kotlinu robíme
vždy.
Tá predvolený predpokladá dátum vo formáte yyyy-mm-dd
,
dátum a čas vo formáte yyyy-mm-ddThh:mm:ss
a čas vo formáte
hh:mm:ss
. Všetky čísla pred sebou musí mať nuly, ak sú
menšie ako 10. T
nie je preklep, ale naozaj oddelenie dátumu a
času. Skúsme si to:
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}
val datumCas = LocalDateTime.parse("2016-12-08T10:20:30")
val datum = LocalDate.parse("2016-12-08")
val cas = LocalTime.parse("10:20:30")
println(datumCas.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)))
println(datum.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)))
println(cas.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM)))
{/KOTLIN_CONSOLE}
výsledok:
8.12.2016 10:20:30 8.12.2016 10:20:30
Vlastný formát
Oveľa častejšie budeme ale samozrejme chcieť naparsovat dátum a čas v
českom tvaru alebo v akomkoľvek inom tvare, predvolené oddeľovanie dátumu a
času pomocou písmena T
nie je práve user-friendly
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}
val datumCas = LocalDateTime.parse("12/08/2016 10:20:30", DateTimeFormatter.ofPattern("M/d/y HH:mm:ss"))
val datum = LocalDate.parse("12/8/2016", DateTimeFormatter.ofPattern("M/d/y"))
val cas = LocalTime.parse("10:20:30", DateTimeFormatter.ofPattern("H:m:ss"))
println(datumCas.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)))
println(datum.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)))
println(cas.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM)))
{/KOTLIN_CONSOLE}
výsledok:
8.12.2016 10:20:30 8.12.2016 10:20:30
Porovnávanie inštancií
Najjednoduchší spôsob ako porovnávať dátumy (píšu schválne
češtinsky nesprávne, dáta je v IT zavádzajúce slovo) je pomocou
operátorov >
, <=
, >
a
>=
. Kotlín nám pomocou metódy compareTo()
preťažuje týchto operátorov. O metóde compareTo()
si ešte
povieme viac v ďalších lekciách.
Pokiaľ vám to príde neprehľadné, môžete použiť zabudované metódy z
Javy, ktoré obsahuje, pretože na rozdiel od Kotlin nepodporuje preťažovania
operátorov. Tieto metódy začínajú is*()
, vymenujme si ich:
isAfter(datum)
- Vracia či je inštancia za dátumom / dátumom a časom odovzdávané inštancie (či je hodnota väčšia).isBefore(datum)
- Vracia či je inštancia pred dátumom / dátumom a časom odovzdávané inštancie (či je hodnota menšia).isEqual(datum)
- Vracia, či je inštancia nastavená na rovnaký dátum a / alebo čas ako je odovzdávaná inštancie (či je hodnota rovnaká).
To bolo jednoduché, že? Keď už sme pri is*()
metód /
vlastností, uveďme si aj zostávajúce 2:
isLeapYear
- Vracia či je inštancia nastavená na priestupný rok alebo nie.isSupported(ChronoUnit)
- Vracia či inštancia podporuje prácu s danou chrono jednotkou (napr.LocalDate
nebude vedieťChronoUnit.HOURS
, pretože neobsahuje informáciu o čase).
isLeapYear
je v Jave metóda, ale
Kotlin nám jej zas přegeneroval na vlastnosť.
Ukážme si príklad:
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}
val halloween = LocalDate.of(2016, 10, 31)
val vanoce = LocalDate.of(2016, 12, 25)
println("po: " + halloween.isAfter(vanoce))
println("před: " + halloween.isBefore(vanoce))
println("shodný: " + vanoce.isEqual(halloween))
println("shodný: " + halloween.isEqual(halloween))
println("přestupný: " + halloween.isLeapYear)
println("přestupný: " + halloween.withYear(2017).isLeapYear)
println("podporuje hodiny: " + halloween.isSupported(ChronoUnit.HOURS))
println("podporuje roky: " + halloween.isSupported(ChronoUnit.YEARS))
{/KOTLIN_CONSOLE}
výsledok:
po: false před: true shodný: false shodný: true přestupný: true přestupný: false podporuje hodiny: false podporuje roky: true
Ďalšie triedy
Okrem LocalDateTime
, LocalDate
a
LocalTime
sa môžete stretnúť aj s niekoľkými ďalšími
triedami, ktoré využijete skôr u aplikácií, ktoré sú na prácu s dátumom
a časom založené. Neľakajte sa ich, vo väčšine prípadov si vystačíte s
LocalDateTime
, ale mali by ste o nich mať povedomie.
Instant
Instant
je dátum a čas, ale nie v poňatí kalendára a
prechodov na letný čas. Je to počet nanosekúnd od 1.1.1970
,
teda jeden bod na časovej osi UTC (univerzálneho času). Keď si kdekoľvek na
Zemi napíšete aplikáciu s týmto kódom:
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.Instant
{KOTLIN_CONSOLE}
val ted = Instant.now()
println(ted)
{/KOTLIN_CONSOLE}
Vypíše vždy to isté. Instant
pozná len univerzálny čas a
ten sa bude líšiť od reálneho času v danej oblasti.
OffsetDateTime a ZonedDateTime
Už vieme, že Instant
je univerzálny čas a
LocalDateTime
má v sebe ten čas, ktorý je na danom území. Zo
samotného LocalDateTime
nedokážeme získať bod na univerzálne
časovej osi, pretože nevieme na akom je územie.
Čo nám chýba je teda kombinácia týchto dvoch, lokálne korektný čas,
ktorý by v sebe zároveň niesol informáciu o územie (časovej zóne) a tým
pádom mohol byť univerzálne prevádzaný medzi rôznymi časovými zónami.
Práve k tomu slúži trieda ZonedDateTime
.
V Kotlinu nájdeme tiež triedu OffsetDateTime
, ktorá je taký
medzičlánok, ktorý umožňuje zaznamenať časový posun, ale nemá plnú
podporu zón.
ZoneId
Časové zóny sú v Kotlinu reprezentované triedou ZoneId
.
Poďme si urobiť jednoduchú ukážku ako vytvoríme dátum s časovou
zónou:
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.Month
import java.time.format.DateTimeFormatter
import java.time.ZonedDateTime
import java.time.ZoneId
{KOTLIN_CONSOLE}
val lokalniDatumCas = ZonedDateTime.now(ZoneId.of("America/New_York"))
println(lokalniDatumCas)
{/KOTLIN_CONSOLE}
výstup:
2017-02-02T06:37:11.026-05:00[America/New_York]
Áno, je to veľa tried, berte to skôr ako informácie, ku ktorým sa vrátite, až ich budete potrebovať. V Kotlinu je tried vždy viac ako v ostatných jazykoch, skúsme si vypestovať trpezlivosť a nejakú odolnosť voči tejto skutočnosti . Nabudúce budeme zas chvíľu prakticky programovať, aby sme si od teórie oddýchli.
Epochy
Na úplný záver si poďme ešte predstaviť niekoľko posledných metód na
LocalDateTime
.
ofEpochSecond()
- Statická metóda nám umožňuje vytvoriť dátum a čas z tzv. Linux timestamp, v ktorom sa dátum a čas často ukladal najmä v minulosti. Je to veľké číslo označujúce počet sekúnd od1.1.1970
(začiatok linuxové epochy), musíme uviesť aj nanosekundy (väčšinou 0) a časovú zónu, čo je najčastejšieZoneOffset.UTC
. Metóda je dostupná aj naLocalDate
akoofEpochDay()
, kde prijíma počet dní miesto sekúnd.toEpochSecond()
atoEpochDay()
- Metódy opačnej k dvom predchádzajúcim, prevádza hodnotu na počet sekúnd / dní od roku 1970.
To je k dátumu a času v Kotlinu naozaj všetko. V budúcej lekcii, Diár s databázou v Kotlin , si vytvoríme praktický príklad, pôjde o elektronický diár