Časové pásma vo webovej aplikácii: zmena času, termíny a reporty

Nesprávne spracované časové pásma vo webovej aplikácii sa prejavia hlavne pri zmene času: pripomienka príde o hodinu skôr, pravidelný termín sa po prechode na letný čas posunie a denný report za deň zmeny nesedí s účtovníctvom. Riešením nie je jedno nastavenie servera, ale jasné pravidlo pre každý druh časového údaja. Okamihy ukladajte v UTC, budúce termíny dohodnuté na miestny čas ako dátum, čas a názov pásma, napríklad Europe/Bratislava, dátumy bez času ako dátumy a opakovania ako pravidlo s pásmom. Potom cielene otestujte dni, keď sa mení čas.

Netýka sa to len firiem so zákazníkmi v zahraničí. Stačí rezervačný systém, plánovanie servisných výjazdov alebo nočný export do účtovníctva. Aj na Slovensku má jeden deň v roku 23 hodín a jeden 25 hodín.

Prečo sa pri zmene času hodina stratí alebo zdvojí

V pásme Europe/Bratislava sa na jar hodiny posúvajú z 2:00 na 3:00, takže miestny čas 2:30 v ten deň neexistuje. Na jeseň sa z 3:00 vracajú na 2:00 a čas 2:30 nastane dvakrát: najprv s posunom voči UTC +02:00, potom s posunom +01:00. Podľa aktuálnych pravidiel pripadne ďalšia jarná zmena na 28. marca 2027 a jesenná na 31. októbra 2027.

Tieto pravidlá nevymýšľa programátor. Udržiava ich databáza časových pásiem IANA, známa aj ako tz alebo zoneinfo. Podľa IANA sa priebežne aktualizuje podľa rozhodnutí štátnych orgánov o hraniciach pásiem, posunoch voči UTC a letnom čase a koncoví používatelia ju zvyčajne dostávajú cez aktualizácie softvéru a operačného systému. Zmena môže prísť tesne pred termínom: vydanie 2026f z 27. októbra 2026 zachytilo, že Kuba 1. novembra 2026 neprejde na zimný čas.

Pre rozhodovanie je kľúčové rozlíšiť dva druhy času. Okamih je bod na časovej osi, napríklad prijatie platby alebo odoslanie e-mailu, a dá sa jednoznačne zapísať v UTC. Miestny termín je dohoda ľudí, napríklad servis v utorok o 9:00 v Košiciach. Jeho vzťah k UTC určujú pravidlá pásma platné v deň termínu, nie v deň, keď ho niekto zapísal.

Príklad: rezervácie servisnej firmy

Ilustračný príklad, nie prípad konkrétneho klienta. Servisná firma plánuje vo webovej aplikácii výjazdy technikov, a to aj cez víkend. Zákazník si v januári objedná pravidelnú kontrolu každý utorok o 9:00. Aplikácia posiela pripomienku 24 hodín pred termínom, v noci exportuje dokončené zákazky do účtovníctva a ráno pošle vedúcemu prehľad tržieb za predchádzajúci deň.

Vývojár pri ukladaní prepočítal termín na UTC: 9:00 v januári je 8:00 UTC. Po prechode na letný čas aplikácia stále plánuje 8:00 UTC, čo je však 10:00 miestneho času. Technik príde o hodinu neskôr, než zákazník čaká.

Ďalšie chyby sú tichšie. Pripomienka „24 hodín vopred“ k termínu v nedeľu 28. marca 2027 o 9:00 odíde v sobotu o 8:00, pretože medzi rovnakými hodinami týchto dvoch dní uplynie iba 23 hodín. Nočný export naplánovaný na 2:30 sa v jarnú noc nemusí spustiť a v jesennú sa môže spustiť dvakrát, podľa toho, ako sa správa plánovač. A ak report „za včera“ počíta deň od polnoci do polnoci UTC, v zime začína o 1:00 a v lete o 2:00 slovenského času.

Náprava neznamená prepisovať celú aplikáciu. Pravidelný termín sa uloží ako pravidlo „každý utorok o 9:00, Europe/Bratislava“, firma rozhodne, či pripomienka znamená presne 24 hodín, alebo deň vopred v rovnakom čase, export sa presunie mimo nočnej hodiny zmeny a report sa bude počítať podľa slovenského kalendárneho dňa.

Ako ukladať jednotlivé druhy časových údajov

Tabuľka slúži ako zadanie pre vývojára aj ako kontrola existujúcej aplikácie. Každý stĺpec v databáze a každé pole v API by malo patriť do jedného riadku.

Druh údaja Ako ho uložiť Príklad
Okamih udalosti Bod v čase v UTC Prijatie platby, prihlásenie, záznam v auditnej stope
Budúci miestny termín Miestny dátum a čas plus názov pásma; UTC len ako odvodená hodnota Servis 6. apríla 2027 o 9:00, Europe/Bratislava
Opakovaný termín Pravidlo opakovania, miestny čas začiatku a pásmo Každý utorok o 9:00
Dátum bez času Iba dátum, bez času a bez pásma Splatnosť faktúry, deň dovolenky
Čas viazaný na človeka, nie na miesto Miestny čas bez pásma, výslovne označený Denné upozornenie o 8:00 tam, kde sa používateľ práve nachádza
Obchodný deň v reportoch Dátum a pásmo firmy; hranice dňa sa prepočítajú na UTC Tržby za 25. októbra 2026, deň s 25 hodinami

Pozor na to, čo robí databáza. Podľa dokumentácie PostgreSQL sa hodnota typu timestamp with time zone ukladá interne v UTC a pôvodne zadané pásmo sa neuchováva. Ak vstup pásmo neobsahuje, databáza predpokladá pásmo z nastavenia TimeZone a pri výstupe čas prevedie do aktuálne nastaveného pásma. Pre okamihy je to správne, pre budúce miestne termíny však potrebujete názov pásma v samostatnom stĺpci.

Pre čas viazaný na človeka pozná kalendárová norma iCalendar (RFC 5545) takzvaný plávajúci čas. Predstavuje rovnakú hodinu bez ohľadu na to, v akom pásme sa človek práve nachádza. Používajte ho len vtedy, keď je to zámer, nie ako náhradu za chýbajúce pásmo.

Postup zavedenia v existujúcej aplikácii

1. Spíšte všetky časové údaje

Prejdite stĺpce v databáze, polia v API, importy, exporty, plánované úlohy a reporty. Ku každému údaju zapíšte druh z tabuľky a odkiaľ pochádza. Nejasné prípady, napríklad termín bez uloženého pásma, označte na doplnenie.

2. Ukladajte názov pásma, nie pevný posun

Pri termínoch, pobočkách a používateľoch ukladajte názov pásma IANA, napríklad Europe/Bratislava. Pevný posun +01:00 platí len časť roka. Norma RFC 9557 používanie pevných posunov namiesto pásma dôrazne neodporúča: posun prevzatý z januárovej hodnoty by po pripočítaní šiestich mesiacov viedol k výsledku posunutému o hodinu.

3. Posielajte čas v API jednoznačne

V API používajte formát RFC 3339 s posunom voči UTC, napríklad 2027-04-06T09:00:00+02:00. RFC 9557 tento formát rozširuje o príponu s názvom pásma, napríklad 2027-04-06T09:00:00+02:00[Europe/Bratislava]. Pri miestnych termínoch tak druhá strana dostane okamih aj pásmo, podľa ktorého má čas ďalej prepočítavať. Ak prípone nerozumie, pošlite názov pásma v samostatnom poli. Podľa tej istej normy môžu odosielateľ a príjemca používať rôzne verzie databázy pásiem, preto musí integrácia zvládnuť aj neznámy názov pásma.

4. Zobrazujte čas v správnom pásme

Ak aplikácia formátuje čas v prehliadači cez Intl.DateTimeFormat, podľa dokumentácie MDN prijíma voľba timeZone názov pásma IANA a bez nej sa použije pásmo prostredia, v ktorom kód beží. Zákazník, ktorý má v telefóne nastavené iné pásmo, napríklad na dovolenke, by tak videl termín slovenského servisu posunutý. Rozhodnite, či sa termín zobrazuje v pásme miesta konania alebo používateľa, a pásmo pri čase uveďte.

5. Určte pravidlá pre neexistujúci a zdvojený čas

Norma iCalendar má na to jasné pravidlá: ak miestny čas nastane dvakrát, platí jeho prvý výskyt, a ak neexistuje, prepočíta sa s posunom platným pred zmenou. Termín 28. marca 2027 o 2:30 by tak pripadol na 3:30 letného času. Norma zároveň upozorňuje, že pravidlo opakovania môže vygenerovať neplatný dátum, napríklad 30. februára, alebo neexistujúci miestny čas. Zvoľte jedno správanie, zapíšte ho do zadania a v rezervačnom formulári také časy radšej vôbec neponúkajte.

6. Upravte plánované úlohy a reporty

Technické úlohy, ako zálohy či exporty, plánujte v UTC alebo mimo nočnej hodiny zmeny a navrhnite ich tak, aby opakované spustenie nevytvorilo duplicitu. Úlohy viazané na miestny čas, napríklad ranné rozosielanie, plánujte podľa pásma. Report za deň počítajte od miestnej polnoci po ďalšiu miestnu polnoc prevedené na UTC a priemer za hodinu nedeľte pevným číslom 24.

7. Aktualizujte databázu pásiem a testujte dni zmeny

Údaje o pásmach prichádzajú cez operačný systém, runtime jazyka, knižnice a databázu, preto ich aktualizáciu zaraďte do pravidelnej údržby. Po zmene pravidiel prepočítajte odvodené UTC hodnoty budúcich termínov. Automatické testy spúšťajte s pevnými dátumami, napríklad 28. marca a 31. októbra 2027, a s rôznym pásmom servera aj prehliadača.

Výhody a nevýhody jednotlivých prístupov

  • Všetko v UTC: jednoduché porovnávanie a radenie okamihov, ale pravidelné termíny sa pri zmene času posunú a budúce termíny aj pri zmene pravidiel pásma.
  • Všetko v miestnom čase servera: pohodlné pre firmu v jednej krajine, no nejednoznačné v jesennej noci a citlivé na presun servera do iného pásma.
  • Miestny čas, pásmo a odvodené UTC: správne pre termíny, ale vyžaduje viac stĺpcov, jasné pravidlá a prepočet po aktualizácii databázy pásiem.
  • Zobrazenie v pásme používateľa: prirodzené pri online stretnutiach, mätúce pri službách na konkrétnom mieste, kde dáva zmysel pásmo miesta konania.

Pre väčšinu firemných aplikácií odporúčame kombináciu: okamihy v UTC, termíny v miestnom čase s pásmom a zobrazenie v pásme miesta konania s jasne uvedeným pásmom.

Časté chyby

  • Pravidelný termín uložený ako jeden čas v UTC.
  • Pevný posun +01:00 alebo pásmo servera namiesto názvu pásma pri termíne.
  • Predpoklad, že deň má vždy 24 hodín, pri pripomienkach, lehotách a reportoch.
  • Formátovanie času v prehliadači bez určeného pásma.
  • Nočné úlohy naplánované medzi 2:00 a 3:00 miestneho času.
  • Zastaraná databáza pásiem na serveri, v kontajneri alebo v aplikácii.
  • Testy, ktoré bežia len v jednom pásme a nikdy nie v deň zmeny času.

Kontrolný zoznam pre zadanie a prevzatie

  • Každý časový údaj má určený druh: okamih, miestny termín, opakovanie, dátum alebo obchodný deň.
  • Termíny a pobočky majú uložený názov pásma IANA.
  • API posiela čas s posunom voči UTC a pri termínoch aj názov pásma.
  • Rozhranie ukazuje, v akom pásme je čas uvedený.
  • Správanie pre neexistujúci a zdvojený čas aj pre opakovania je zapísané a otestované.
  • Reporty počítajú obchodný deň v pásme firmy a zvládnu deň s 23 aj 25 hodinami.
  • Aktualizácia databázy pásiem je súčasťou údržby a po nej sa prepočítajú budúce termíny.

Časté otázky

Stačí ukladať všetky časy v UTC?

Pre okamihy áno, pre budúce termíny dohodnuté na miestny čas nie. Podľa RFC 9557 sa pravidlá pomenovaného pásma môžu meniť a platia tie, ktoré sú aktuálne v čase spracovania údaja. Ukladajte preto miestny čas s pásmom a UTC si odvoďte.

Musíme to riešiť, keď máme len domácich zákazníkov?

Áno. Zmena času sa týka aj jedného pásma a server, databáza či telefón zákazníka môžu byť nastavené na iné pásmo než firma. Chyby sa preto môžu ukázať až v noci zmeny času alebo v týždňoch po nej.

Čo s termínom v hodine, ktorá neexistuje?

Rezervačný formulár by ju nemal ponúknuť. Ak taký termín vznikne z importu alebo z opakovania, použite zapísané pravidlo, napríklad posun na 3:30 podľa iCalendar, a dotknuté rezervácie ukážte dispečerovi na kontrolu.

Ako často sa databáza časových pásiem mení?

Priebežne, keď štáty zmenia hranice pásiem, posun voči UTC alebo pravidlá letného času. Zmena môže vyjsť len pár dní pred účinnosťou, ako ukázalo vydanie 2026f. Aktualizujte ju preto spolu s bežnými aktualizáciami systému, nie až pri probléme.

Potrebujete preveriť časy vo vašej aplikácii?

Ak vaša aplikácia pracuje s rezerváciami, plánovaním, pripomienkami alebo dennými reportmi, pomôžeme s inventúrou časových údajov, úpravou dátového modelu, testami dní zmeny času aj opravou už uložených termínov. Viac o našej práci nájdete na stránke webové aplikácie na mieru.

Pošlite nám krátky popis, ktoré termíny alebo reporty sa vám posúvajú a kedy sa to stalo. Ďalšie články o vývoji a prevádzke aplikácií nájdete na blogu.

Zdroje

Vyberte si, ktoré cookies povolíte. Voľbu môžete kedykoľvek zmeniť cez odkaz v pätičke alebo tlačidlo cookies.

Ochrana súkromia a podrobnosti o cookies