Unix-aikaleimat & Epoch-aika: Vuoden 2038 ongelma selitettynä

Julkaistu: 9:00 AM , tekijältä Kelloon.com-toimitus

Unix-aikaleimat selitettynä: sekunnit vuoden 1970 epookista, UTC-muunnos, vuoden 2038 ylivuoto kello 03:14:07 UTC, 64-bittinen korjaus ja karkaussekunnit.

Digitaalinen kellonäyttö, joka pyörähtää yli 03:14:07 UTC 19. tammikuuta 2038, havainnollistaen etumerkillisen 32-bittisen Unix-ajan ylivuotoa

Mikä on Unix-aikaleima?

Unix-aikaleima on yksi luku: sekuntien määrä, joka on kulunut Unix-epookista, joka on määritelty 1. tammikuuta 1970 kello 00:00:00 UTC. Siinä kaikki. Ei aikavyöhykettä, ei päivämäärämerkkijonoa, ei kuukausien nimiä – vain kokonaisluku, joka kasvaa yhdellä yksiköllä sekunnissa.

Koska epookki on kiinteä ja universaali, aikaleima kuten 1700000000 tarkoittaa täsmälleen samaa hetkeä kaikkialla maapallolla. Tokion palvelin ja Chicagon kannettava tietokone ovat molemmat samaa mieltä siitä, että se viittaa 14. marraskuuta 2023 kello 22:13:20 UTC. Paikallinen näyttö eroaa aikavyöhykkeen mukaan, mutta taustalla oleva luku ei koskaan muutu.

Yksi tarkoituksellinen yksinkertaistus: Unix-aika jättää karkaussekunnit huomiotta. Se olettaa, että jokainen päivä on täsmälleen 86 400 sekuntia pitkä, mikä ei ole aivan totta tähtitieteellisessä todellisuudessa, mutta pitää laskutoimitukset puhtaina. Lisää tästä alla.

Miksi insinöörit rakastavat niitä

Aikaleimoja on kaikkialla ohjelmistoissa – tiedostojen muokkausajoissa, tietokantatietueissa, API-vastauksissa, JWT-voimassaolokentissä, lokiriveissä – ja hyvästä syystä:

  • Ne ovat yksittäinen arvo. Yksi kokonaisluku tallentaa täyden päivämäärän ja kellonajan. Ei jäsentämistä, ei epäselvyyttä PP/KK vs. KK/PP välillä.
  • Ne ovat aikavyöhykeriippumattomia. Luku on aina UTC. Muunnat paikalliseen aikaan vasta, kun näytät sen ihmiselle.
  • Niitä on helppo verrata ja lajitella. Kumpi tapahtuma tuli ensin? Pienempi kokonaisluku. Kahden tapahtuman välinen kesto? Vähennä ne toisistaan; vastaus on sekunteina.
  • Ne tallentuvat tiiviisti. Yksi 4- tai 8-tavuinen kokonaisluku verrattuna muotoiltuun merkkijonoon.

Tästä syystä niin moni infrastruktuuri puhuu epookkisekunteja pinnan alla, vaikka käyttöliittymä näyttäisi sinulle ystävällisen 2026-07-23. Jos haluat liikkua näiden kahden esitysmuodon välillä, Unix-aikaleiman muunnin tekee käännöksen molempiin suuntiin.

Yhden lukeminen: Työstetty esimerkki

Ota aikaleima 1000000000 – kuuluisa, koska se pyörähti yli suorassa lähetyksessä Unix-harrastajien keskuudessa.

Lukeaksesi sen käsin, jaat sekunnit suurempiin yksiköihin. Karkeasti ottaen 1 000 000 000 sekuntia on noin 31,7 vuotta (vuosi on ~31 556 952 sekuntia). Lisää se vuoden 1970 epookkiin ja päädyt vuoteen 2001. Tarkka hetki on 9. syyskuuta 2001, kello 01:46:40 UTC.

Teet tätä laskutoimitusta harvoin käsin – jokaisessa kielessä on sisäänrakennettu toiminto. Pythonissa:

```python from datetime import datetime, timezone datetime.fromtimestamp(1000000000, tz=timezone.utc)

2001-09-09 01:46:40+00:00

```

Keskeinen pointti: muunnos on aina ankkuroitu UTC:hen. Funktio muuttaa raa'an sekuntimäärän kalenteripäivämääräksi kulkemalla eteenpäin epookista. Jos haluat sen sijaan paikallisen ajan, käytät aikavyöhykkeen siirtymää UTC-muunnoksen jälkeen – itse aikaleima ei sisällä aikavyöhyketietoa.

Vuoden 2038 ongelma

Tässä kohtaa tarina muuttuu mielenkiintoiseksi – ja missä monilla muuten hyvin rakennetuilla järjestelmillä on tikittävä kello sisällään.

Vuosikymmenten ajan C-standardin tyyppiä, jota käytettiin Unix-ajan tallentamiseen, time_t, käytettiin yleisesti allekirjoitettuna 32-bittisenä kokonaislukuna. Allekirjoitettu 32-bittinen kokonaisluku voi edustaa arvoja −2 147 483 648:sta 2 147 483 647:ään. Tämä yläraja on ongelma.

Laskettaessa sekunteja vuoden 1970 epookista, arvo 2 147 483 647 saavutetaan 19. tammikuuta 2038 kello 03:14:07 UTC. Yksi sekunti myöhemmin laskurin pitäisi olla 2 147 483 648 – mutta tämä luku ei mahdu allekirjoitettuun 32-bittiseen kokonaislukuun. Sen sijaan, että se jatkaisi ylöspäin, bitit ylivuotavat ja kiertyvät takaisin negatiivisimpaan arvoon, −2 147 483 648.

Negatiivinen aikaleima tulkitaan ajaksi ennen epookkia. Joten kello ei vain pysähdy – se hyppää taaksepäin 13. joulukuuta 1901. Mikä tahansa järjestelmä, joka luotti 32-bittiseen time_t-arvoonsa, uskoo yhtäkkiä olevansa 1900-luvun alussa.

Tätä kutsutaan usein Y2K38-bugiksi tai Unixin vuosituhatbugiksi, ja rakenteellisesti se on samanlainen kiinteän leveyden ylivuoto, joka aiheutti vuoden 2000 pelon – vain kauempana tulevaisuudessa ja juurtunut binäärikokonaislukujen rajoituksiin kahden numeron vuosien sijaan.

Missä se todella puree

Modernit 64-bittiset työpöytäkoneet ja palvelimet korjattiin suurelta osin vuosia sitten. Riski keskittyy paikkoihin, joita on vaikea päivittää:

  • Sulautetut ja teolliset järjestelmät. Reitittimet, ohjaimet, lääkinnälliset laitteet, autojen ECU:t ja IoT-laitteisto, joka toimitettiin 32-bittisellä time_t:llä ja saattaa toimia koskemattomana 20+ vuotta. Monet tänään käyttöönotetut laitteet ovat edelleen käytössä vuonna 2038.
  • Vanha C-koodi. Sovellukset, jotka on käännetty vanhaa time_t-määritelmää vastaan, erityisesti missä tyyppi on päätynyt levyformaattiin tai verkkoprotokolliin.
  • Vanhat tietokannat ja tiedostojärjestelmät. Tallennusformaatit, jotka pakkasivat aikaleimat 32-bittisiin kenttiin. Jotkut vanhemmat järjestelmät osoittavat jo oireita käsitellessään kaukaisia tulevaisuuden päivämääriä – ajattele 20 vuoden asuntolainaa tai sertifikaatin voimassaoloa, joka ulottuu yli vuoden 2038.

Vikatila ei ole aina dramaattinen kaatuminen. Joskus se on hienovarainen väärin laskettu päivämäärä: vanhentunut token, joka luetaan voimassa olevaksi, lajittelujärjestys, joka kääntyy, ajastettu työ, joka käynnistyy vuonna 1901.

Korjaus: 64-bittinen aika

Korjaus on periaatteessa suoraviivainen – laajenna time_t 64 bittiin. Allekirjoitettu 64-bittinen kokonaisluku voi laskea sekunteja kauas minkään käytännöllisen horisontin yli: ylivuotopiste on noin 292 miljardia vuotta tulevaisuudessa, mukavasti Auringon odotetun eliniän jälkeen.

Useimmat nykyiset käyttöjärjestelmät ovat jo tehneet tämän siirron. 64-bittinen Linux käyttää 64-bittistä time_t:tä; jopa 32-bittinen Linux sai 64-bittisen ajan tuen ytimeen ja glibc:hen viime vuosina. Vaikea osa ei ole itse korjaus – se on jokaisen viimeisenkin laiteohjelmiston, jokaisen tallennusformaatin ja jokaisen kolmannen osapuolen binäärin löytäminen ja uudelleenkääntäminen, joka edelleen olettaa 32 bittiä. Tämä auditointityö on todellinen vuoden 2038 projekti.

Miten karkaussekunnit sopivat kuvaan

Tähtitieteellinen aika ja atomiaika erkanevat hieman toisistaan, joten virallinen UTC lisää ajoittain karkaussekunnin pitääkseen kellot linjassa Maan pyörimisen kanssa. Unix-aika teeskentelee, ettei näitä ole olemassa – se koodaa kovaksi 86 400 sekuntia päivässä.

Kun karkaussekunti tapahtuu, järjestelmät tyypillisesti "hämärtävät" sen – levittäen ylimääräisen sekunnin ikkunan yli (Google suositteli 24 tunnin hämärrystä) niin, ettei minkään kellon tarvitse koskaan näyttää mahdotonta 23:59:60. Lopputulos: Unix-aikaleimat pysyvät tasaisina ja monotonisina, kustannuksena olla pienen murto-osan sekunnista poissa tarkasta UTC:stä hämärryksen aikana. Käytännössä kaikille ohjelmistoille tämä on juuri se kompromissi, jonka haluat. Vuoden 2038 ylivuoto on kokonaislukuleveysongelma; karkaussekunnit ovat erillinen, paljon pienempi määritelmän omituisuus – älä sekoita niitä.

Keskeiset opit

  • Unix-aikaleima on sekunteja 1. tammikuuta 1970 kello 00:00:00 UTC jälkeen, karkaussekunnit huomiotta jättäen.
  • Se on yksittäinen, aikavyöhykeriippumaton kokonaisluku – helppo tallentaa, verrata ja lajitella.
  • Muunnos on aina suhteessa UTC:hen; paikallinen aika lisätään jälkikäteen.
  • Allekirjoitettu 32-bittinen time_t ylivuotaa 19. tammikuuta 2038 kello 03:14:07 UTC, kiertyen negatiiviseksi arvoksi ja hypäten vuoteen 1901.
  • Korjaus on 64-bittinen time_t; työ on sulautettujen ja vanhojen järjestelmien auditointi.

Haluatko nähdä sen toiminnassa? Liitä mikä tahansa epookkiarvo Unix-aikaleiman muunnin:een lukeaksesi sen ihmisen päivämääränä – tai mene toiseen suuntaan ja muuta päivämäärä sen aikaleimaksi.

Usein kysytyt kysymykset

Onko Unix-aikaleima sekunneissa vai millisekunneissa?

Klassinen Unix-aika on sekunneissa. JavaScript ja monet verkkosovellusliittymät käyttävät kuitenkin millisekunteja epookista, joten arvo kuten 1700000000000 on 1 000× suurempi. Nopea vinkki: sekuntipohjaisessa aikaleimassa on 10 numeroa tuoreelle päivämäärälle; millisekuntipohjaisessa on 13. Jos olet epävarma, tarkista suuruusluokka ennen muuntamista.

Kaatuuko puhelimeni tai kannettavani vuoden 2038 ongelmaan?

Melkein varmasti ei. Modernit 64-bittiset käyttöjärjestelmät käyttävät jo 64-bittistä time_t:tä, mikä työntää ylivuodon miljardien vuosien päähän. Todellinen altistus on pitkäikäisissä sulautetuissa laitteissa ja vanhoissa ohjelmistoissa, jotka edelleen luottavat 32-bittiseen aikaan ja joita ei välttämättä päivitetä ennen vuotta 2038.

Voiko Unix-aikaleima olla negatiivinen?

Kyllä. Negatiiviset arvot edustavat hetkiä ennen vuoden 1970 epookkia – esimerkiksi -1 on 31. joulukuuta 1969, kello 23:59:59 UTC. Tämä on täsmälleen se, mitä 32-bittinen ylivuoto tuottaa vuonna 2038, minkä vuoksi kello näyttää hyppäävän takaisin vuoteen 1901.

Miksi Unix-aika jättää karkaussekunnit huomiotta?

Pitääkseen matematiikan yksinkertaisena ja ennustettavana. Kohtelemalla jokaista päivää täsmälleen 86 400 sekuntina kestot ovat vain vähennyslaskua, ja aikaleimat pysyvät monotonisina. Pieni epäsuhta tähtitieteellisen UTC:n kanssa käsitellään "hämärtämällä" karkaussekunti, minkä lähes kaikki sovellukset suosivat sen sijaan, että joutuisivat käsittelemään 23:59:60-reunatapausta.

Miten muunnan aikaleiman kirjoittamatta koodia?

Käytä verkkotyökalua. Unix-aikaleiman muunnin hyväksyy epookkiarvon ja näyttää vastaavan UTC- ja paikallisen päivämäärän ja kellonajan välittömästi, ja se muuntaa myös kalenteripäivämäärät takaisin aikaleimoiksi.

Kello nyt sisällä näissä kaupungeissa:

New York · Lontoo · Tokio · Pariisi · Hongkong · Singapore · Dubai · Los Angeles · Shanghai · Peking · Sydney · Mumbai

Kello nyt maissa:

🇺🇸 USA | 🇨🇳 Kiina | 🇮🇳 Intia | 🇬🇧 Iso-Britannia | 🇩🇪 Saksa | 🇯🇵 Japani | 🇫🇷 Ranska | 🇨🇦 Kanada | 🇦🇺 Australia | 🇧🇷 Brasilia |

Kello nyt aikavyöhykkeet:

UTC | GMT | CET | PST | MST | CST | EST | EET | IST | Kiina (CST) | JST | AEST | SAST | MSK | NZST |

Ilmainen widgetit verkkovastaaville:

Ilmainen analoginen kello-widget | Ilmainen digitaalinen kello-widget | Ilmainen tekstikellon-widget | Ilmainen sanakellon-widget