IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

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í:

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

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

Kotlín nám vygeneruje vlastnosť z Getter z Javy - Objektovo orientované programovanie v Kotlin

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:

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

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ý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:

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ý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:

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

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:

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

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 od 1.1.1970 (začiatok linuxové epochy), musíme uviesť aj nanosekundy (väčšinou 0) a časovú zónu, čo je najčastejšie ZoneOffset.UTC. Metóda je dostupná aj na LocalDate ako ofEpochDay(), kde prijíma počet dní miesto sekúnd.
  • toEpochSecond() a toEpochDay() - 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 :)


 

Predchádzajúci článok
Dátum a čas v Kotlin - Úprava a intervaly
Všetky články v sekcii
Objektovo orientované programovanie v Kotlin
Preskočiť článok
(neodporúčame)
Diár s databázou v Kotlin
Článok pre vás napísal Samuel Kodytek
Avatar
Užívateľské hodnotenie:
1 hlasov
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