Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
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 13 - Datum a čas v Kotlin - Parsování a porovnávání

V minulé lekci, Datum a čas v Kotlin - Úprava a intervaly, jsme se věnovali převedení, úpravě hodnoty a časovým intervalům.

V dnešním Kotlin tutoriálu dokončíme téma data a času. Podíváme se na čtení hodnoty, parsování a porovnávání.

Čtení hodnoty

Hodnotu čteme pomocí vlastností, zde nás ani nic nepřekvapí:

fun main(args: Array<String>) {

val halloween = LocalDate.of(2016, Month.OCTOBER, 31)
println("Rok: " + halloween.year + ", měsíc: " + halloween.monthValue + ", den: " + halloween.dayOfMonth)

}

Všimněte si, že když nám IntelliJ radí (pomocí Ctrl + Space), tak se po levé straně zobrazují javovské názvy metod, které jsou přegenerované do vlastností Kotlinem, pro snazší práci (to v závorce, šedým písmem).

Kotlin nám vygeneruje vlastnost z getteru z Javy - Objektově orientované programování v Kotlin

A výsledek:

Rok: 2016, měsíc: 10, den: 31

Všimněte si, že pro získání čísla měsíce jsme použili monthValue, protože month by vrátil hodnotu z výčtového typu Month.

Pokud se setkáte se starší třídou Calendar, dejte si pozor, protože tam jsou měsíce číslované od 0 místo od 1, jak je tomu v LocalDate/LocalDateTime.

Parsování data a času

Datum a čas budeme samozřejmě často dostávat v textové podobě, např. od uživatele z konzole, ze souboru nebo z databáze. Asi tušíte, že k vytvoření LocalDateTime z takovéto textové hodnoty použijeme metodu parse() přímo na datovém typu, jako to v Kotlinu děláme vždy.

Ta výchozí předpokládá datum ve formátu yyyy-mm-dd, datum a čas ve formátu yyyy-mm-ddThh:mm:ss a čas ve formátu hh:mm:ss. Všechna čísla před sebou musí mít nuly, pokud jsou menší jak 10. T není překlep, ale opravdu oddělení data a času. Zkusme si to:

fun main(args: Array<String>) {

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

}

Výsledek:

8.12.2016 10:20:30
8.12.2016
10:20:30

Vlastní formát

Mnohem častěji budeme ale samozřejmě chtít naparsovat datum a čas v českém tvaru nebo v jakémkoli jiném tvaru, výchozí oddělování data a času pomocí písmene T není zrovna user-friendly :)

fun main(args: Array<String>) {

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

}

Výsledek:

8.12.2016 10:20:30
8.12.2016
10:20:30

Porovnávání instancí

Nejjednodušší způsob jak porovnávat datumy (píší schválně češtinsky nesprávně, data je v IT zavádějící slovo) je pomocí operátorů >, <=, > a >=. Kotlin nám pomocí metody compareTo() přetěžuje tyto operátory. O metodě compareTo() si ještě povíme víc v dalších lekcích.

Pokud vám to přijde nepřehledné, můžete použít zabudované metody z Javy, které obsahuje, protože na rozdíl od Kotlin nepodporuje přetěžování operátorů. Tyto metody začínají is*(), vyjmenujme si je:

  • isAfter(datum) - Vrací zda je instance za datem/datem a časem předávané instance (zda je hodnota větší).
  • isBefore(datum) - Vrací zda je instance před datem/datem a časem předávané instance (zda je hodnota menší).
  • isEqual(datum) - Vrací, zda je instance nastavena na stejný datum a/nebo čas jako je předávaná instance (zda je hodnota stejná).

To bylo jednoduché, že? Když už jsme u is*() metod/vlastností, uveďme si i zbývající 2:

  • isLeapYear - Vrací zda je instance nastavena na přestupný rok či nikoli.
  • isSupported(ChronoUnit) - Vrací zda instance podporuje práci s danou chrono jednotkou (např. LocalDate nebude umět ChronoUnit.HOURS, protože neobsahuje informaci o čase).

isLeapYear je v Javě metoda, ale Kotlin nám jí zas přegeneroval na vlastnost.

Ukažme si příklad:

fun main(args: Array<String>) {

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

}

Výsledek:

po: false
před: true
shodný: false
shodný: true
přestupný: true
přestupný: false
podporuje hodiny: false
podporuje roky: true

Další třídy

Kromě LocalDateTime, LocalDate a LocalTime se můžete setkat také s několika dalšími třídami, které využijete spíše u aplikací, které jsou na práci s datem a časem založené. Nelekejte se jich, ve většině případů si vystačíte s LocalDateTime, ale měli byste o nich mít povědomí.

Instant

Instant je datum a čas, ale ne v pojetí kalendáře a přechodů na letní čas. Je to počet nanosekund od 1.1.1970, tedy jeden bod na časové ose UTC (univerzálního času). Když si kdekoli na Zemi napíšete aplikaci s tímto kódem:

fun main(args: Array<String>) {

val ted = Instant.now()
println(ted)

}

Vypíše vždy to samé. Instant zná jen univerzální čas a ten se bude lišit od reálného času v dané oblasti.

OffsetDateTime a ZonedDateTime

Již víme, že Instant je univerzální čas a LocalDateTime má v sobě ten čas, který je na daném území. Ze samotného LocalDateTime nedokážeme získat bod na univerzální časové ose, protože nevíme na jakém je území.

Co nám chybí je tedy kombinace těchto dvou, lokálně korektní čas, který by v sobě zároveň nesl informaci o území (časové zóně) a tím pádem mohl být univerzálně převáděn mezi různými časovými zónami. Právě k tomu slouží třída ZonedDateTime.

V Kotlinu nalezneme také třídu OffsetDateTime, která je takový mezičlánek, který umožňuje zaznamenat časový posun, ale nemá plnou podporu zón.

ZoneId

Časové zóny jsou v Kotlinu reprezentovány třídou ZoneId. Pojďme si udělat jednoduchou ukázku jak vytvoříme datum s časovou zónou:

fun main(args: Array<String>) {

val lokalniDatumCas = ZonedDateTime.now(ZoneId.of("America/New_York"))
println(lokalniDatumCas)

}

Výstup:

2017-02-02T06:37:11.026-05:00[America/New_York]

Ano, je to hodně tříd, berte to spíše jako informace, ke kterým se vrátíte, až je budete potřebovat. V Kotlinu je tříd vždy více než v ostatních jazycích, zkusme si vypěstovat trpělivost a nějakou odolnost vůči této skutečnosti :) . Příště budeme zas chvíli prakticky programovat, abychom si od teorie odpočinuli.

Epochy

Na úplný závěr si pojďme ještě představit několik posledních metod na LocalDateTime.

  • ofEpochSecond() - Statická metoda nám umožňuje vytvořit datum a čas z tzv. Linux timestamp, ve kterém se datum a čas často ukládal zejména v minulosti. Je to velké číslo označující počet vteřin od 1.1.1970 (začátek linuxové epochy), musíme uvést i nanosekundy (většinou 0) a časovou zónu, což je nejčastěji ZoneOffset.UTC. Metoda je dostupná i na LocalDate jako ofEpochDay(), kde přijímá počet dní místo sekund.
  • toEpochSecond() a toEpochDay() - Metody opačné ke dvěma předchozím, převádí hodnotu na počet sekund/dní od roku 1970.

To je k datu a času v Kotlinu opravdu vše.

V příští lekci, Diář s databází v Kotlin, si vytvoříme praktický příklad pro práci s datem a časem, půjde o elektronický diář :)


 

Předchozí článek
Datum a čas v Kotlin - Úprava a intervaly
Všechny články v sekci
Objektově orientované programování v Kotlin
Přeskočit článek
(nedoporučujeme)
Diář s databází v Kotlin
Článek pro vás napsal Samuel Kodytek
Avatar
Uživatelské hodnocení:
12 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