Vánoční nadílka Vánoční nadílka
Až 80% zdarma! Předvánoční BLACK FRIDAY akce. Více informací

Lekce 13 - Datum a čas v Kotlin - Parsování a porovnávání

Kotlin Objektově orientované programování Datum a čas v Kotlin - Parsování a porovnávání

ONEbit hosting Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

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 toto téma dokončíme, 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í:

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

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:

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 často 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 :)

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:

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:

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:

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, půjde o elektronický diář :)


 

 

Článek pro vás napsal Samuel Kodytek
Avatar
Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!
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 (7)

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!