Hvad er et Unix-tidsstempel? Sådan virker epoketid
Et Unix-tidsstempel er antallet af sekunder, der er gået siden 1. januar 1970 kl. 00:00:00 UTC. Det tidspunkt kaldes Unix-epoken, og alt efter det tælles som et positivt tal, mens alt før tælles som negativt. Når du ser et tal som 1700000000 i en database eller en API-respons, er det præcis, hvad det er: et øjeblik i tiden udtrykt som ét enkelt heltal.
Hvad et Unix-tidsstempel egentlig er
I stedet for at gemme en dato som en tekststreng, gemmer et Unix-tidsstempel den som et antal sekunder fra et fast nulpunkt. Det virker måske omstændeligt ved første øjekast, men det løser en række problemer, som formaterede datostrenge skaber.
For det første er et tidsstempel kompakt. “1700000000” fylder mindre end “2023-11-14T22:13:20Z” og kræver ingen parsing af måneds- eller ugedagsnavne. For det andet er det entydigt: der er kun én måde at fortolke tallet på, uanset hvilket sprog eller hvilken lokal indstilling systemet kører med. En dato skrevet som “01-02-2023” kan betyde 1. februar eller 2. januar afhængigt af hvor du er, men 1675209600 betyder præcis ét bestemt øjeblik, uanset hvem der læser det.
Den tredje og måske vigtigste grund er, at et tidsstempel er timezone-uafhængigt og nemt at regne på. To tidsstempler kan sammenlignes med en simpel større-end eller mindre-end, sorteres numerisk, eller trækkes fra hinanden for at få forskellen i sekunder. Prøv at gøre det samme pålideligt med to strenge i forskellige datoformater, og du ender hurtigt i en bunke af edge cases. Det er derfor felter som en databases created_at-kolonne, et JWT-tokens exp-claim eller en linje i en logfil ofte gemmer tid som et rent tal frem for en formateret dato.
Regneeksempel: sådan læser du rigtige tidsstempelværdier
Her er fem tidsstempler og de præcise UTC-tidspunkter, de svarer til:
| Unix-tidsstempel (sekunder) | Dato og klokkeslæt (UTC) |
|---|---|
| 0 | 1. januar 1970 kl. 00:00:00 UTC (selve epoken) |
| 1000000000 | 9. september 2001 kl. 01:46:40 UTC |
| 1700000000 | 14. november 2023 kl. 22:13:20 UTC |
| 2000000000 | 18. maj 2033 kl. 03:33:20 UTC |
| 2147483647 | 19. januar 2038 kl. 03:14:07 UTC |
Tag 1700000000 som eksempel. Der er cirka 31 556 952 sekunder på et almindeligt år, så 1700000000 sekunder svarer til lidt under 54 år fra epoken i 1970. Tæl 54 år frem fra 1. januar 1970, og du lander midt i 2023, hvilket stemmer med tabellen: 14. november 2023 kl. 22:13:20 UTC. Du behøver ikke regne det ud i hovedet hver gang, men det er nyttigt at have en grov fornemmelse af skalaen, når du sidder og kigger på et tal og skal vurdere, om det virker rigtigt.
Læg også mærke til 2147483647. Det tal er ikke tilfældigt, det er det største heltal, der kan rummes i et 32-bit signed heltal, og det kommer vi tilbage til under Year 2038-problemet.
Sekunder eller millisekunder? Sådan kender du forskel
Den klassiske faldgrube med Unix-tidsstempler er at blande sekunder og millisekunder sammen. Et tidsstempel i sekunder har i dag 10 cifre, for eksempel 1700000000. Det samme øjeblik udtrykt i millisekunder har 13 cifre: 1700000000000, som stadig svarer til 14. november 2023.
JavaScripts Date.now() og en lang række web-API’er returnerer millisekunder som standard, mens Unix-systemkald, cron og det meste Unix/Linux-værktøj arbejder i sekunder. Forskellen lyder triviel, men den slår hårdt, hvis du blander dem sammen. Indsætter du en millisekund-værdi som 1700000000000 i et felt, der forventer sekunder, tolkes den som 1700000000000 sekunder efter epoken, altså et tidspunkt tusind gange længere ude i fremtiden end tiltænkt, hvilket typisk lander et sted mellem år 55000 og år 56000. Omvendt vil en sekund-værdi tolket som millisekunder pege tilbage til få minutter efter selve epoken i 1970. Begge fejl er nemme at få øje på, hvis du kender genkendelsestegnet: tæl cifrene.
Konverter et tidsstempel til en dato
Har du et rent tal fra en logfil, en API-respons eller en databaserække og vil vide, hvilken dato og klokkeslæt det egentlig svarer til, kan du sætte det direkte ind herunder.
Konverter en dato til et tidsstempel
Den anden vej rundt har du typisk brug for, når du skal planlægge noget til et bestemt tidspunkt, for eksempel en cron-jobkørsel eller en scheduled_at-værdi, der skal sendes til en API som et tal frem for en datostreng. Vælg dato og klokkeslæt herunder for at få det tilsvarende Unix-tidsstempel.
Almindelige fejl og særtilfælde
At blande sekunder og millisekunder sammen. Som beskrevet ovenfor er dette den hyppigste fejl. Et tal med 10 cifre er sandsynligvis sekunder, et med 13 cifre er sandsynligvis millisekunder. Tjek altid, hvilken enhed den API eller det bibliotek, du arbejder med, forventer, før du sender tallet videre.
Year 2038-problemet. Systemer, der gemmer tidsstemplet som et 32-bit signed heltal, kan maksimalt repræsentere 2147483647, hvilket svarer til 19. januar 2038 kl. 03:14:07 UTC. Ét sekund senere vipper tallet om til en negativ værdi, fordi det øverste bit, der bruges til fortegn, vælter over. Resultatet er, at systemets ur pludselig springer tilbage til 1901 i stedet for at gå videre til 2038, hvilket kan ødelægge alt fra sessionshåndtering til planlagte jobs. 64-bit systemer, som de fleste moderne servere og databaser i dag kører på, har et langt større talområde og rammer ikke dette loft.
Timezone-forvirring. Et Unix-tidsstempel har ingen tidszone. Det er et absolut øjeblik, tælt fra epoken i UTC, og har ingen mening af “lokal tid” indbygget i sig selv. Forvirringen opstår først, når tallet skal vises for et menneske: en bruger i København og en i Tokyo, der begge kigger på tidsstemplet 1700000000, ser to forskellige klokkeslæt på deres skærm, fordi hver af dem konverterer det samme øjeblik til sin egen lokale tidszone. Selve tallet ændrer sig ikke, kun fremvisningen af det.
Negative tidsstempler. Datoer før 1. januar 1970 repræsenteres som negative tal. -86400 svarer til præcis ét døgn før epoken, altså 31. december 1969 kl. 00:00:00 UTC. Ikke alle systemer og biblioteker understøtter negative tidsstempler korrekt, så hvis du arbejder med historiske data fra før 1970, for eksempel et fødselsår eller et arkivdatosæt, bør du teste specifikt, om det værktøj, du bruger, håndterer negative værdier.
Ofte stillede spørgsmål
Hvad er et Unix-tidsstempel? Det er antallet af sekunder, der er gået siden 1. januar 1970 kl. 00:00:00 UTC, kaldet Unix-epoken. Det bruges til at repræsentere et bestemt tidspunkt som et enkelt heltal frem for en formateret datostreng, hvilket gør det kompakt, entydigt og nemt at regne og sammenligne på tværs af systemer.
Hvordan ved jeg, om mit tidsstempel er i sekunder eller millisekunder? Tæl cifrene. I dag har et tidsstempel i sekunder 10 cifre, for eksempel 1700000000, mens det samme øjeblik i millisekunder har 13 cifre, 1700000000000. Hvis tallet virker urimeligt langt ude i fremtiden, når du konverterer det som sekunder, prøv i stedet at behandle det som millisekunder.
Hvad er Year 2038-problemet? Det er en overløbsfejl, der rammer systemer, som gemmer Unix-tidsstemplet i et 32-bit signed heltal. Det største tal, sådan et felt kan rumme, er 2147483647, som svarer til 19. januar 2038 kl. 03:14:07 UTC. Lige efter det tidspunkt vipper værdien om til negativ, hvilket kan få systemets ur til at springe tilbage til 1901. 64-bit systemer er ikke berørt, fordi deres talområde er langt større.
Kan jeg konvertere en dato fra før 1970? Ja. Datoer før epoken repræsenteres som negative tidsstempler. -86400 svarer for eksempel til 31. december 1969. De fleste moderne værktøjer, inklusive konverterne herover, håndterer negative værdier uden problemer, men det er værd at teste specifikt, hvis du arbejder med ældre eller historiske systemer.
Hvorfor gemmer databaser datoer som Unix-tidsstempler i stedet for en datostreng?
Fordi et tidsstempel er langt billigere at sammenligne, sortere og regne på end en tekststreng. At finde alle rækker mellem to tidspunkter bliver en simpel numerisk sammenligning i stedet for streng-parsing, og tidsstemplet fylder mindre plads og er uafhængigt af, hvilken tidszone eller hvilket sprog serveren kører med. Det er derfor felter som created_at og updated_at ofte gemmes som tal internt, selv når de vises formateret for brugeren.