Ajan käsitteet haastavat ohjelmoijan
Hetket, kellonajat, aikavyöhykkeet ym. puuroutuvat ohjelmoijalla helposti yhdeksi “ajan” käsitteeksi. Monien ohjelmointikielten standardikirjastoissakin kaikki aika-asiat hoidetaan luokalla tai parilla. Lisäksi kirjastot yrittävät arvailla, mitä ohjelmoija milloinkin tarkoittaa, ja tekevät sitten piilossa kaikenlaisia “helpottavia” muunnoksia. Lopputuloksena aikaa käsittelevässä koodissa on usein tavallista enemmän virheitä. Niitä voi myös olla vaikea analysoida, sillä useampi virhe saattaa kumota toisensa tai koodi saattaa toimia hyvin melkein aina.
Tässä kirjoituksessa pyritään erottelemaan joitain aikaan liittyviä käsitteitä toisistaan. Toivottavasti tämä saa lukijan ajattelemaan käsitteitä selkeämmin ja tekemään muutaman aikabugin vähemmän.
En ole aiheen asiantuntija, vaan käytin kirjoittamista pohdiskeluun ja omienkin ajatusteni selventämiseen.
Hetkien käsittely on vielä helppoa
Hetki on piste aikasuoralla. Kuvittele, että joku käynnistää sekuntikellon. Käynnistyshetki määrää aikasuoran origon eli epokin, jonka jälkeen kaikki muut hetket voidaan ilmaista sekunteina ennen tai jälkeen epokin. Kaikkialla maailmassa samaan hetkeen viitataan samalla sekuntimäärällä. Jos Suomessa on 73 sekuntia epokin jälkeen, niin samalla hetkellä myös Japanissa on 73 sekuntia epokin jälkeen, koska kaikki viittaavat samaan sekuntikelloon.
Tunnetuimpia epokkeja on Unix-epokki. Juuri tällä hetkellä “Unix-sekuntikello” on käynyt 1 653 470 633 sekuntia. Windowseissa taas käytetään NT-epokkia ja samainen hetki on 13 297 944 233 sekuntia NT-epokin jälkeen. Sekuntien sijaan voidaan toki käyttää myös vaikkapa millisekunteja tai mikrosekunnin kymmenesosia kuten Windows tekee. Nämä ovat kuitenkin yksityiskohtia ja yleensä kannattaa pyrkiä siihen, että hetkiä pystyisi käsittelemään abstrakteina aikasuoran pisteinä.
Hetkiä on suhteellisen helppo käsitellä. Jos hetkeen lisätään 7 sekuntia, saadaan hetki, joka on 7 sekuntia ensimmäisen hetken jälkeen. Sekuntimäärien erotus kertoo, paljonko aikaa hetkien välillä on, ja sekuntimääriä vertailemalla nähdään, kumpi hetki on aikaisempi.
Tähän helpot asiat sitten oikeastaan loppuvatkin.
Kellonajat ja päivämäärät pistävät jo usealla pakan sekaisin
Tässä kirjoituksessa kellonaika tarkoittaa kellonajan ja päivämäärän yhdistelmää, esimerkiksi 2022-05-25 12:23:53. Kellonaika ei yksin viittaa mihinkään hetkeen, vaan tulkinta riippuu aina näkökulmasta. Minun näkökulmastani (Suomen aika) äskeinen kellonaika viittaa Unix-hetkeen 1 653 470 633 s, mutta vaikkapa ruotsalaisten näkökulmasta se onkin Unix-hetki 1 653 474 233 s. Kellonaika ei myöskään yksinään tarkoita “paikallista aikaa”, koska se viittaisi heti tulkintaan jossain aikavyöhykkeessä.
Kellonaika on siis vain liuta numeroita tai muita määreitä, joilla ilmaistaan vuosia, kuukausia jne., ja jotka noudattavat tiettyjä sääntöjä. Esimerkiksi päivän on oltava 1–31, missä yläraja riippuu kuukaudesta ja vuodesta.
Kuten arvata saattaa, kellonaikojen käsitteleminen on monimutkaisempaa kuin hetkien. Yllättävää on ehkä se, kuinka paljon hankalampaa se voi olla. Mitä on esimerkiksi kalenterikuukausi lisää päivämäärään 2019-02-28? Onko se 2019-03-28 vai 2019-03-31? Tai paljonko on kalenterivuosi ja yksi kalenteripäivä lisää samaan päivämäärään? 2020-03-01 vai 2020-02-29? Tällaiset pitää miettiä tapauskohtaisesti ja ensimmäinen askel on ymmärtää, minkälaisia ongelmia ylipäätään voi tulla vastaan.
Homma karkaa käsistä viimeistään siinä vaiheessa, kun hetket ja kellonajat menevät sekaisin. Sanotaan vaikka, että kellonaikaan 2022-10-30 00:00 pitäisi lisätä yksi päivä. Asiakas ajatteli yhtä kalenteripäivää (vastaus 2022-10-31 00:00), mutta ohjelmoija yhtä “sekuntikellopäivää” eli 86400 sekuntia sekuntikellolla mitattuna ja sai vastaukseksi 2022-10-30 23:00, koska satuttiin olemaan Suomessa ja siirryttiin talviaikaan.
Kellonaikojen vertailu voi myös olla ongelmallista. Jos kysytään, kumpi kahdesta kellonajasta on aikaisempi, vastaus on periaatteessa helppo. Ongelma onkin se, että oikeasti kysymys usein tarkoittaa, kumpi annetuista paikallisista kellonajoista on aikaisempi, ja siihen taas ei aina voi antaa yksikäsitteistä vastausta. Esimerkiksi talviaikaan siirryttäessä kellonaikoja toistetaan, mutta ensimmäiset niistä vastaavat aikaisempia hetkiä kuin toiset.
Aikavyöhykkeet sekä kesä- ja talviajan siirtymät tuovat omat pulmansa
Aikavyöhyke on liuta sääntöjä, joiden avulla hetki voidaan muuntaa kellonajaksi. Keskeisin aikavyöhyke on UTC, jossa on käytännössä kaksi sääntöä:
- Unix-epokki vastaa kellonaikaa 1970-01-01 00:00:00.
- Muut hetket muunnetaan kellonajoiksi laskemalla tästä sekunteja ylös tai alas kalenterilaskusääntöjen mukaan.
Periaatteessa lisähaasteita tulee karkaussekunneista, mutta ne voi yleensä aika hyvin unohtaa (kuuluisia viimeisiä sanoja?).
Muut aikavyöhykkeet ilmaistaan yleensä UTC:n avulla. Esimerkiksi Suomen kesäaika on UTC+3 (tuntia) eli hetki voidaan ilmaista Suomen kesäajassa muuntamalla se ensin UTC-aikaan ja lisäämällä tähän 3 kalenterituntia. Aikavyöhyke ei kuitenkaan ole pelkkä aikavyöhykesiirtymä kuten 3 tuntia, vaan se saattaa olla paljon monimutkaisempi. Suomen aikavyöhykkeessäkin on seuraavanlaisia sääntöjä:
- Ennen vuotta 1981 Suomen aika oli aina UTC+2, paitsi vuonna 1945, jolloin 3.4.–4.10. se oli UTC+3.
- Vuodesta 1981 tähän päivään Suomen aika on ollut UTC+2 paitsi kesäisin (maaliskuun viimeisestä sunnuntaista lokakuun viimeiseen sunnuntaihin), jolloin se on UTC+3.
Suomessa on myös välillä ollut puhetta kesä- tai talviajasta luopumisesta. Jos tämä joskus toteutuu, niin aikavyöhykesäännöt muuttuvat!
Suomen aikavyöhyke ei siis ole “UTC+2 (kesäisin UTC+3)” tai “EET/EEST”, koska se on historiallisesti ollut monimutkaisempi ja saattaa tulevaisuudessa muuttua. Sen sijaan suomen aikavyöhyke on Europe/Helsinki (zoneinfo-tunnus), joka viittaa koko dynaamiseen sääntöpakettiin.
Paikallinen aika ja sen laskeminen
Jos hetki ja aikavyöhyke tiedetään, voidaan laskea paikallinen aika. Esimerkiksi Unix-hetki 1 653 470 633 s on 2022-05-25 12:23:53 Suomen paikallista aikaa. Paikallinen aika kertoo, missä ollaan ja mitä kello siellä näyttää.
Toisin päin muunnos ei aina onnistu. Esimerkiksi “2022-03-27 03:30:00 Suomen aikaa” on virheellinen, sillä kyseinen kellonaika ohitettiin kesäaikaan siirryttäessä, eikä se siis vastaa mitään hetkeä. Toisaalta “2022-10-30 03:30:00 Suomen aikaa” ei ole yksikäsitteinen, koska tämä kellonaika tulee esiintymään kahdesti talviaikaan siirryttäessä, jos ei sitten talviajasta ennen sitä luovuta…
Sovelluksia ajan tallentamiseen
Tästä kaikesta voi ainakin johtaa pari nyrkkisääntöä ajan tallentamiseen. Sovellettava harkiten:
Menneet ajat kannattaa yleensä tallentaa hetkinä. Jos ne tallentaa pelkkinä paikallisina kellonaikoina, niin niitä ei voi enää asettaa aikajärjestykseen, ei vaikka aikavyöhykekin tunnettaisiin. Niitä ei liioin voi muuntaa hetkiksi tai toisen aikavyöhykkeen paikalliseen aikaan eikä selvittää, paljonko aikaa kahden kellonajan välillä on kulunut. Jos paikallinen aika pitää pystyä selvittämään, kannattaa luultavasti vain tallentaa sekä hetki että aikavyöhyke.
Tulevat ajat ovat vielä hankalampia. Mietitään muistutusohjelmaa. Kello on nyt 14 ja käyttäjä asettaa muistutuksen kello 17. Sitten käyttäjä lentää pikaisesti toiseen aikavyöhykkeeseen. Jos muistutus tallennettiin hetkenä, se hälyttää 3 tuntia asettamisen jälkeen kellonajasta riippumatta. Jos se tallennettiin kellonaikana, se hälyttää kello 17 riippumatta siitä, paljonko aikaa asettamisen ja hälytyksen välillä kuluu. Perussääntö voisi olla, että jos käyttäjä syöttää kellonajan, se tallennetaan kellonaikana, koska vastaavaa hetkeä ei pysty luotettavasti selvittämään. Jos taas käyttäjä syöttää ajan, joka pitää odottaa, niin tallennetaan hetki, koska vastaavaa kellonaikaa ei pysty laskemaan.
Linkkejä
Miksi .NET:in DateTime-luokka on ongelmallinen https://blog.nodatime.org/2011/08/what-wrong-with-datetime-anyway.html
Usein, tai ainakin joskus, tehtyjä vääriä olettamuksia ajasta https://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time
Blogin kirjoittaja Kristian Setälä toimii Trinerialla Senior Software Developerina.
Lisätietoja
Tagit
Erikoisosaaminen
Ohjelmistokehitys |
Toimialakokemus
IT |
Tarjonnan tyyppi
Toteutustyö |
Omat tagit
Trineria - Asiantuntijat ja yhteyshenkilöt
Trineria - Muita referenssejä
Trineria - Muita bloggauksia
It- ja ohjelmistoalan työpaikat
- Laura - Hankinta-asiantuntija, tietohallinto
- Laura - Development Manager, Operations
- Laura - ICT-asiantuntija
- Laura - IT Manager
- Nordea - Senior Fullstack Developer
- Innofactor Oyj - Business Architect
- Laura - Cloud Engineer
Premium-asiakkaiden viimeisimmät referenssit
- SD Worx - Kehitystyö SD Worxin kanssa takaa Clas Ohlsonille parhaat palkanmaksun prosessit kasvun tiellä
- Digiteam Oy - Case Esperi Care Oy: Ketterä kumppanuus vei Esperin verkkosivu-uudistuksen maaliin sujuvasti ja aikataulussa
- Kisko Labs Oy - Howspace Hub - Mukautuva oppimisen hallintajärjestelmä kasvaviin oppimisalustavaatimuksiin
- Kisko Labs Oy - Sanoma Pro: Multimediasisältöjen hallinnan uudistaminen
- Kisko Labs Oy - Svean helppokäyttöinen palvelu asiakkaan verkko-ostosten hallintaan
- Kisko Labs Oy - Yhtenäinen käyttöliittymä luovien alojen ammattilaisille
- Codemate - Digitaalisen murroksen nopeuttaminen Flutterin avulla
Tapahtumat & webinaarit
- 27.11.2024 - Green ICT -ekosysteemitapaaminen III: Ohjelmistojärjestelmien virrankulutuksen mittaaminen ja kasvihuonepäästöjen arviointi
- 27.11.2024 - Digitaalisen asiakaskokemuksen uusi aikakausi
- 28.11.2024 - Webinaari: Keskity myyntityön laatuun!
- 28.11.2024 - Copilot-webinaari – Mielekkäämpää tietotyötä turvallisesti
- 04.12.2024 - Kuinka oikea matka- ja kululaskujärjestelmä tehostaa prosesseja?
- 05.12.2024 - Green ICT VICTIS -hankkeen kick off -tilaisuus
- 15.01.2025 - Datavastuullisuuden valmennus: hanki valmiudet vastuulliseen datan ja tekoälyn hyödyntämiseen
Premium-asiakkaiden viimeisimmät bloggaukset
- Zimple Oy - Pipedrive vai Hubspot? Kumpi kannattaa valita?
- SC Software Oy - Jatkuvat palvelut – asiakaslähtöistä kumppanuutta projekteista ylläpitoon
- Timeless Technology - Ohjelmoitavat logiikat (PLC): Ratkaisevat työkalut automaatioon ControlByWebiltä.
- Kisko Labs Oy - Heroku: Ohjelmistokehittäjän ykköstyökalu skaalautuvien sovellusten rakentamiseen
- SD Worx - Näin luot vakuuttavan Business Casen palkkahallinnon ulkoistukselle
- Timeless Technology - Kyberriskien tunnistaminen Profitap IOTA verkkoanalysaattorin avulla.
- GidiUp Oy - Ai hitto -päivä: Kun sesonki pääsee taas yllättämään
Digitalisaatio & innovaatiot blogimediaBlogimediamme käsittelee tulevaisuuden liiketoimintaa, digitaalisia innovaatioita ja internet-ajan ilmiöitä |