Aika vaikuttaa yksinkertaiselta, kunnes yrität kirjoittaa ohjelmistoa, joka käsittelee sen oikein. "Kello 15:ään" sovittu tapahtuma tarkoittaa eri asiaa Tokiossa, Lontoossa ja New Yorkissa. Kesäaika siirtää kelloja eteen- tai taaksepäin — mutta ei kaikkialla, eikä samoina päivinä. Aikaleima, joka näyttää oikealta paikallisessa ympäristössäsi, epäonnistuu tuotannossa, koska palvelin on eri vyöhykkeellä.
Aikavyöhykkeet ovat yksi luotettavimmin hämmentävistä aiheista ohjelmistokehityksessä. Tämä artikkeli selittää, miten ne toimivat, mistä monimutkaisuus johtuu ja miten välttää yleisimmät virheet.
Miksi aikavyöhykkeitä on olemassa
Maapallo pyörähtää 360 astetta 24 tunnissa, mikä tarkoittaa, että aurinko on korkeimmillaan eri aikaan pituusasteesta riippuen. Ennen 1800-lukua jokainen kaupunki asetti kellonsa paikallisen aurinkoajan mukaan — keskipäivä oli kun aurinko oli korkeimmillaan. Tämä toimi hyvin, kunnes rautatiet yhdistivät kaukaisia kaupunkeja ja junien aikataulut vaativat yhtenäistä kellonaikaa.
Vuonna 1884 25 maan edustajat kokoontuivat kansainväliseen meridiaanikonferenssiin Washington D.C.:ssä ja sopivat maailman jakamisesta 24 vakioaikavyöhykkeeseen, joista kukin on siirtymä nollameridiaanista (0 pituusasteen kohdalla) Greenwichin, Englannin kautta.
Käytännössä aikavyöhykkeiden rajat seuraavat poliittisia rajoja, eivät siistejä pituusastelinjoja. Kiina ulottuu viiden maantieteellisen vyöhykkeen yli, mutta käyttää yhtä virallista aikaa (UTC+8). Intia käyttää UTC+5:30 — puolen tunnin siirtymä. Nepal käyttää UTC+5:45. Todellinen aikavyöhykekartta on sotkuinen.
UTC vs. GMT
GMT (Greenwich Mean Time) on keskimääräinen aurinkoaika Greenwichin kuninkaallisessa observatoriossa. Se oli maailman aikareferenssi yli vuosisadan ajan.
UTC (Coordinated Universal Time) korvasi GMT:n kansainvälisenä standardina vuonna 1972. UTC perustuu atomikelloihin astronomisen havainnoinnin sijaan, mikä tekee siitä paljon tarkemman. Useimmissa käytännön tarkoituksissa UTC ja GMT näyttävät saman ajan, mutta UTC on oikea tekninen referenssi.
Miksi "UTC" eikä "CUT"? Lyhenne on kompromissi englanninkielisen "Coordinated Universal Time" (CUT) ja ranskankielisen "Temps Universel Coordonné" (TUC) välillä. Kumpikaan osapuoli ei saanut suosimaansa lyhennettä, joten valittiin kielineutraali UTC.
Kesäaika: järjestäytyä kaaosta
Noin 70 maata noudattaa kesäaikaa (DST), siirtäen kelloja tunnin eteenpäin keväällä ja tunnin taaksepäin syksyllä. Tarkoituksena on sovittaa valveillaoloajat päivänvalon kanssa. Tuloksena on puolivuosittainen virheiden lähde.
Keskeisiä komplikaatioita:
- Ei universaali. Suurin osa Afrikasta, Aasiasta ja Etelä-Amerikasta ei noudata kesäaikaa. Yhdysvalloissa Arizona ja Havaiji jättäytyvät sen ulkopuolelle.
- Eri päivämäärät. EU vaihtaa maaliskuun ja lokakuun viimeisenä sunnuntaina. Yhdysvallat vaihtaa maaliskuun toisena sunnuntaina ja marraskuun ensimmäisenä sunnuntaina. Ne ovat epäsynkroonissa useita viikkoja vuosittain.
- Moniselitteiset ajat. Kun kelloja siirretään taaksepäin, tunti kello 01:00-02:00 tapahtuu kahdesti. Aikaleima "01:30" kyseisenä päivänä on moniselitteinen.
- Ohitetut ajat. Kun kelloja siirretään eteenpäin, tuntia kello 02:00-03:00 ei ole olemassa. Kello 02:30 sovittu tapaaminen ei koskaan tapahdu.
- Poliittiset muutokset. Hallitukset voivat (ja tekevätkin) muuttaa kesäaikasääntöjä lyhyellä varoitusajalla. Venäjä otti pysyvän kesäajan käyttöön vuonna 2011, vaihtoi sitten pysyvään normaaliaikaan vuonna 2014. Marokko on muuttanut kesäaikasääntöjä useita kertoja.
ISO 8601: universaali päivämäärämuoto
Moniselitteisyyden välttämiseksi kansainvälinen standardi ISO 8601 määrittelee selkeän päivämäärä- ja aikamuodon:
2026-03-29T14:30:00Z
2026-03-29T14:30:00+02:00
2026-03-29T14:30:00-05:00
Terottaa päivämäärän ajasta.Ztarkoittaa UTC:tä ("Zulu"-aikavyöhyke sotilaallisessa terminologiassa).+02:00tai-05:00on UTC-poikkeama.
Tämä muoto on yksiselitteinen, järjestettävissä pelkkänä tekstinä ja universaalisti ymmärretty päivämääräjäsennykirjastoissa. Epävarmoissa tilanteissa käytä ISO 8601:tä.
Unix-aikaleimat
Unix-aikaleima (kutsutaan myös epoch-ajaksi tai POSIX-ajaksi) on sekuntien lukumäärä, joka on kulunut 1. tammikuuta 1970, 00:00:00 UTC — hetki, joka tunnetaan nimellä Unix-epookki.
| Ihmisen luettava | Unix-aikaleima |
|---|---|
| 1970-01-01 00:00:00 UTC | 0 |
| 2000-01-01 00:00:00 UTC | 946684800 |
| 2026-03-29 12:00:00 UTC | 1774987200 |
Unix-aikaleimoilla ei ole aikavyöhykettä — ne ovat aina UTC:ssä. Tämä tekee niistä ihanteellisia aikojen tallentamiseen ja vertailuun ohjelmistossa. Muunnat paikalliseen aikavyöhykkeeseen vain esityskerroksessa.
Vuoden 2038 ongelma: Järjestelmät, jotka tallentavat Unix-aikaleimoja 32-bittisinä etumerkillisinä kokonaislukuina, ylivuotavat 19. tammikuuta 2038 kello 03:14:07 UTC. Maksimiarvo (2 147 483 647) pyörähtää negatiiviseksi luvuksi, joka tulkitaan joulukuuksi 1901. Useimmat nykyaikaiset järjestelmät käyttävät 64-bittisiä kokonaislukuja, jotka eivät ylivuoda vielä 292 miljardiin vuoteen.
IANA-aikavyöhyketietokanta
Ohjelmisto ei tarvitse pelkästään UTC-poikkeamia — se tarvitsee tietää kunkin alueen täydellisen historian ja tulevat säännöt, mukaan lukien kesäaikasiirtymät, poliittiset muutokset ja historialliset poikkeavuudet. Tämä tieto löytyy IANA Time Zone Database -tietokannasta (tunnetaan myös nimillä Olson-tietokanta tai tzdata).
Se käyttää tunnisteita kuten America/New_York, Europe/Paris, Asia/Tokyo. Jokainen merkintä koodaa kyseisen sijainnin UTC-poikkeamien ja kesäaikasääntöjen täydellisen historian.
Siksi sinun ei koskaan pitäisi tallentaa aikavyöhykettä kiinteänä poikkeamana kuten "+02:00". Poikkeama kertoo nykyisen eron UTC:hen, mutta ei sano mitään kesäaikasäännöistä. Europe/Paris on UTC+1 talvella ja UTC+2 kesällä. IANA-tunniste kattaa molemmat.
Yleisiä ohjelmistovirheitä
- Paikallisen ajan tallentaminen ilman aikavyöhykettä. Arvo kuten
2026-03-29 14:30:00on merkityksetön tietämättä mihin aikavyöhykkeeseen se viittaa. Tallenna aina UTC tai sisällytä poikkeama. - Olettaminen, että UTC-poikkeama on sama kuin aikavyöhyke. UTC+2 maaliskuussa voi olla UTC+3 heinäkuussa (jos alue noudattaa kesäaikaa). Tallenna IANA-tunniste, ei poikkeamaa.
- Kesäaikasiirtymien huomiotta jättäminen aikataulutuksessa. Päivittäinen tehtävä kello 02:30 ohitetaan kerran vuodessa ja suoritetaan kahdesti kerran vuodessa, jos et käsittele kesäaikaa.
- Olettaminen, että päivissä on 24 tuntia. Kesäaikasiirtymäpäivinä päivässä on 23 tai 25 tuntia. "Huomenna samaan aikaan" laskeminen lisäämällä 86 400 sekuntia on tunnin verran väärin.
- JavaScript
Date:n naiivi käyttö.new Date("2026-03-29")jäsennetään UTC:ksi joissakin moottoreissa ja paikalliseksi ajaksi toisissa. Ole aina eksplisiittinen aikavyöhykkeen suhteen.
Parhaat käytännöt kehittäjille
- Tallenna ajat UTC:nä. Muunna käyttäjän paikalliseen aikavyöhykkeeseen vain esityskerroksessa.
- Käytä IANA-aikavyöhyketunnisteita (
America/New_York), ei kiinteitä poikkeamia (-05:00). - Käytä ISO 8601:tä serialisointiin. Se on yksiselitteinen ja universaalisti jäsennettävissä.
- Käytä kypsää päivämääräkirjastoa. JavaScriptissa käytä
Intl.DateTimeFormat:ia tai kirjastoa kutendate-fns-tz. Pythonissa käytäzoneinfo:a (3.9+) taipytz:ia. Javassa käytäjava.time.ZonedDateTime:ia. - Pidä
tzdataajan tasalla. Hallitukset muuttavat kesäaikasääntöjä. Käyttöjärjestelmäsi ja ohjelmistoajoympäristösi tarvitsevat ajantasaiset aikavyöhyketiedot. - Testaa useilla aikavyöhykkeillä. Älä oleta, että palvelimesi ja käyttäjäsi jakavat saman vyöhykkeen.
Lue lisää
Aika on petollisen monimutkaista, mutta säännöt ovat hyvin dokumentoituja ja työkalut ovat kypsiä. Avain on kunnioittaa monimutkaisuutta sen sijaan, että olettaisi sen pois.
- Cron-lausekkeet selitettynä — tehtävien aikatauluttaminen aikavyöhykkeiden yli
- Tiivistegeneraattori ja Regex-testeri — lisää kehittäjätyökaluja ToolK:ssa
