Hlavní navigace

Letný/zimný čas z pohľadu programátora II

24. 10. 2009 23:46 | Zdeno Sekerák

Dnes 25.10 sa zmení tzv. letný na zimný čas. Nechám teraz bokom emotívne prajavy prečo áno, prečo nie a skúsim opísať tento „problém“ z pohľadu programátora.

Úvod:

Systém prepínania letný/zimný čas vznikol z potreby šetriť elektrickou energiou a vykonáva sa nasledovne. Vždy posledný marcový (brezen) a októbrový (říjen) víkend zo soboty na nedeľu sa skoro ráno posunie hodinová ručička http://sk.wikipedia.org/wi­ki/Letný_čas. Presnejšie v marci dopredu z 2 na 3 hodinu. V októbri naspať z 3 na 2 hodinu.

Pokiaľ tento problém za vás nerieši OS a vytvárate napríklad firmware pre malé zariadenie, tak stojíte pred problémom algoritmizácie (naprogramovania) prepínania letný – zimný čas. Na dokreslenie použijem zdrojový kód v jazyku C v ktorom používam štruktúru iRTC. Tá vypadá nasledovne:

struct iRTC {    U08 Sec;    U08 Min;    U08 Hour;    enum WDAY WDay;    U08 Day;    enum MONTH Month;    U08 Year; };

Problém č.1 – Kedy to nastane.

Problém by bol v celku ľahký, keby tam nebol ten víkend. Pokiaľ to chcete naprogramovať, musíte podľa dátum zistiť na aký deň v týždni pripadá http://sk.wikipedia.org/wi­ki/Algoritmus_na_výpočet_dňa_v_týž­dni. A tak váš FW posledných 7 dní v marci a októbri o 2 (3) hodine ráno kontroluje či náhodou nieje nedeľa. Program v C bude vypadať takto.

// urcim den v tyzdni iRTC.WDay = GetWDay(iRTC);

// letny v marci if(( iRTC.Month == 3 ) && ( iRTC.Day >= 25 ) && ( iRTC.WDay == 7 ) && ( iRTC.Hour >= 2 ))    iRTC.Hour++;// posuniem hodinu pred
// zimny (normálny) v oktobri if(( iRTC.Month == 10) && ( iRTC.Day >= 25 ) && ( iRTC.WDay == 7 ) && ( iRTC.Hour >= 3 ))    iRTC.Hour--;// posuniem hodinu spat

Problém č.2 – Už sa tak stalo?

Pozorný čitatelia, prípadne skúsenejší programátori určite prišli na jednu chybu. Tou chybou je práve október. Máme postavenú podmienku, že ak je to posledná nedeľa v mesiaci október a sú 3 hodiny ráno tak potom posuň hodiny dozadu. No áno. Ale tie hodiny pobežia a za hodinu bude zase 3 hodín ráno. Algoritmus by teda posunul hodiny zase spať a tak stále dokola. Do podmienky teda musíme pridať že sa tak už stalo, a že už zimný čas je a nieje nutné znova prepínať. Tak zase krátky zdroják.

// letny uz v marci if(( iRTC.Month == 3 ) && ( iRTC.Day >= 25 ) && ( iRTC.WDay == 7 ) && ( iRTC.Hour >= 2 )) {    IsSummer=true;    iRTC.Hour++;// posuniem hodinu pred }
// zimny (normálny) v oktobri if(( iRTC.Month == 10) && ( iRTC.Day >= 25 ) && ( iRTC.WDay == 7 ) && ( iRTC.Hour >= 3 ) && (IsSummer)) {    IsSummer=false;    iRTC.Hour--;// posuniem hodinu spat }

Problém č.3 – Ešte stále nemáme vyhrané

Kto by si po vyriešení 2 vydýchol, naplnil by len Murphyho zákoník a zistil, že vyriešením problému sa vyrojili ďalšie. Tým prvým je odveké „kam s ním“. Riešenie sme totiž postavili na premennej IsSummer ktorá celý čas udržiava stav letný/zimný. Kde ju uložiť? Do registrov, do flash, do EEPROM? A naviac to musíte neustále udržiavať aj v tej globálnej premennej IsSummer (úplne zbytočné zabranie pamete). Pri zapínaní prístroja premenú včas a správne načítať a pod. Aby toho nebolo dosť. Tak pre istotu (programátori majú radi parametre) ešte pribudne premená UseSummer. Teda či má prístroj vobec prepínať čas. Kedže sa pohybujeme na zariadeniach kde každý Byte dobrý. Zožrali sme si 2B. Tí skusenejší to naperú do 1B.


Problém č.4 – Až teraz to príde

Máme teraz 2 dni z ktorých jeden má 25 hodín a ten ďalší 23 (prípadne naopak). Poviete si maličkosť. Ale čo ak vaše zariadenie počíta priemernú spotrebu? Prípadne vyvoláva alarm ak v neakom dni spotreba prekročila hranicu, prípadne bola pod minimom. Ak sa vám stratí hodina tak výpočty idú do kelu. Z toho sa potom ďažko dostať bez „straty kytičky“. Ak aj to vyriešite, tak vaši testeri to nerozchodia a všetko, opakujem všetko, budú testovať pre normálny deň a pre deň prepnutia času. To že ste si zaniesli do programu neakú chybu je samozrejmosť.


Záver

Z vlastných skúseností viem že implementácia zaberie v kóde tak 5–7%. To nemyslím tých pár riadkov čo som sem pastol, ale práve riešenie bodu 4. Poznám dokonca programátorov, ktorý niečo také neimplementujú. Proste po prepnutí času prestanú počítať kumulatívy a priemerné hodnoty v tom dni, prípadne ich označia za nekoretné. To som opísal problém len okruhu malých zariadení. Verím že veľké SW a hlavne databázy musia mať problémy komplikovanejšie. Z pohladu programátora je prepínanie času letný/zimný vyslovená nepríjemnosť, ktorá komplikuje algoritmy, zvačšuje kód a nedá sa zmysluplne vyriešiť.

Anketa

Letný čas je

PS: V pondelok pridám aj kód ako z dátumu vyveštiť deň v týždni. Teraz ho neviem nájsť.

Váš TrSek