Unix-tid

Två lager av kodning utgör Unix-tid. Det första lagret kodar en tidpunkt som ett skalärt reellt tal som representerar antalet sekunder som har gått sedan 00:00:00 UTC torsdagen den 1 januari 1970. Det andra lagret kodar det talet som en sekvens av bitar eller decimalsiffror.

Som standard med UTC märker den här artikeln dagar med hjälp av den gregorianska kalendern och räknar tider inom varje dag i timmar, minuter och sekunder. Några av exemplen visar också International Atomic Time (TAI), ett annat tidssystem som använder samma sekunder och visas i samma format som UTC, men där varje dag är exakt 86400 sekunder lång och gradvis förlorar synkroniseringen med jordens rotation med en hastighet av ungefär en sekund per år.

Kodning av tid som ett talRedigera

Unix-tid är ett enkelt signerat tal som ökas varje sekund, vilket gör det lättare för datorer att lagra och hantera än konventionella datumsystem. Tolkningsprogram kan sedan konvertera det till ett människoläsbart format.

Unix epok är tiden 00:00:00:00 UTC den 1 januari 1970. Det finns ett problem med denna definition, eftersom UTC inte fanns i sin nuvarande form förrän 1972; denna fråga diskuteras nedan. För korthetens skull används i resten av det här avsnittet ISO 8601 datum- och tidsformat, där Unix epok är 1970-01-01T00:00:00:00Z.

Unix tidsnummer är noll vid Unix epok, och ökar med exakt 86400 per dag sedan epoken. Således representeras 2004-09-16T00:00:00:00Z, 12677 dagar efter epoken, av Unix-tidstalet 12677 × 86400 = 1095292800. Detta kan också utvidgas bakåt från epoken med hjälp av negativa tal. 1957-10-04T00:00:00Z, 4472 dagar före epoken, representeras alltså av Unix-tidstalet -4472 × 86400 = -386380800. Detta gäller även inom dagar; tidstalet vid en given tidpunkt på en dag är det antal sekunder som har gått sedan midnatt som börjar den dagen adderat till tidstalet vid den midnatt.

På grund av att Unix-tiden är baserad på en epok, och på grund av ett vanligt missförstånd om att Unix-epoken är den enda epoken (ofta kallad ”epoken” ), kallas Unix-tid ibland för epoktid.

SkedsekunderRedigera

Ovanstående schema innebär att på en normal UTC-dag, som har en varaktighet på 86400 sekunder, ändras Unix-tidstalet på ett kontinuerligt sätt över midnatt. I slutet av den dag som används i exemplen ovan utvecklas tidsrepresentationerna till exempel på följande sätt:

När en skottsekund inträffar är UTC-dagen inte exakt 86400 sekunder lång och Unix-tidstalet (som alltid ökar med exakt 86400 varje dag) upplever en diskontinuitet. Skedsekunder kan vara positiva eller negativa. Ingen negativ skottsekund har någonsin deklarerats, men om en sådan skulle uppstå skulle Unix-tidstalet i slutet av en dag med en negativ skottsekund hoppa upp med 1 till början av nästa dag. Under en positiv skottsekund i slutet av en dag, som i genomsnitt inträffar ungefär vart och ett och ett halvt år, ökar Unix-tidstalet kontinuerligt till nästa dag under skottsekunden och hoppar sedan i slutet av skottsekunden tillbaka med 1 (och återgår till början av nästa dag). Detta är till exempel vad som hände på strikt överensstämmande POSIX.1-system i slutet av 1998:

Unix tidstal upprepas under den sekund som följer omedelbart efter en positiv skottsekund. Unix-tidstalet 1483142400 är därför tvetydigt: det kan hänvisa antingen till början av skottsekunden (2016-12-31 23:59:60) eller till slutet av den, en sekund senare (2017-01-01 00:00:00). I det teoretiska fallet när en negativ skottsekund inträffar uppstår ingen tvetydighet, utan det finns istället en rad Unix-tidstal som inte hänvisar till någon punkt i UTC-tiden alls.

En Unix-klocka implementeras ofta med en annan typ av hantering av positiva skottsekunder i samband med Network Time Protocol (NTP). Detta ger ett system som inte överensstämmer med POSIX-standarden. Se avsnittet nedan om NTP för mer information.

När det gäller perioder som inte omfattar en UTC-skottsekund är skillnaden mellan två Unix-tidstal lika med varaktigheten i sekunder av perioden mellan de motsvarande tidpunkterna. Detta är en vanlig beräkningsteknik. När skottsekunder förekommer ger dock sådana beräkningar fel svar. I tillämpningar där denna grad av noggrannhet krävs är det nödvändigt att konsultera en tabell över skottsekunder när man hanterar Unix-tider, och det är ofta att föredra att använda en annan tidskodning som inte lider av detta problem.

Ett Unix-tidstalet konverteras lätt tillbaka till en UTC-tid genom att ta kvoten och modulen av Unix-tidstalet, modulo 86400. Kvoten är antalet dagar sedan epok, och modulen är antalet sekunder sedan midnatt UTC den dagen. Om ett Unix-tidstal ges som är tvetydigt på grund av en positiv skottsekund, tolkar denna algoritm det som tiden strax efter midnatt. Den genererar aldrig en tid som ligger under en skottsekund. Om ett Unix-tidstal är ogiltigt på grund av en negativ skottsekund genererar algoritmen en lika ogiltig UTC-tid. Om dessa förhållanden är betydande är det nödvändigt att konsultera en tabell över skottsekunder för att upptäcka dem.

Icke-synkron variant baserad på Network Time ProtocolEdit

Sällan implementeras en Mills-style Unix-klocka med hantering av skottsekunder som inte är synkron med ändringen av Unix-tidstalet. Tidsnumret minskar till en början där ett språng borde ha inträffat, och sedan hoppar det till den korrekta tiden 1 sekund efter språnget. Detta underlättar genomförandet och beskrivs i Mills artikel. Detta är vad som händer över en positiv skottsekund:

Detta kan avkodas korrekt genom att uppmärksamma tillståndsvariabeln skottsekund, som otvetydigt anger om skottet har utförts ännu. Tillståndsvariabelns förändring är synkron med skottet.

En liknande situation uppstår med en negativ skottsekund, där den sekund som hoppar över är något för sen. Mycket kortvarigt visar systemet ett nominellt omöjligt tidstal, men detta kan upptäckas av tillståndet TIME_DEL och korrigeras.

I denna typ av system bryter Unix tidstal mot POSIX kring båda typerna av skottsekunder. Genom att samla in tillståndsvariabeln skottsekund tillsammans med tidsnumret möjliggörs otvetydig avkodning, så att det korrekta POSIX-tidsnumret kan genereras om så önskas, eller så kan den fullständiga UTC-tiden lagras i ett lämpligare format.

Den avkodningslogik som krävs för att hantera den här typen av Unix-klocka skulle också korrekt avkoda en hypotetisk POSIX-anpassad klocka som använder samma gränssnitt. Detta skulle uppnås genom att indikera tillståndet TIME_INS under hela en infogad skottsekund och sedan indikera TIME_WAIT under hela den följande sekunden samtidigt som sekundräkningen upprepas. Detta kräver synkron hantering av skottsekunder. Detta är förmodligen det bästa sättet att uttrycka UTC-tid i Unix-klockform, via ett Unix-gränssnitt, när den underliggande klockan i grunden inte störs av skottsekunder.

TAI-baserad variantRedigera

Detta avsnitts faktiska riktighet är omtvistad. Relevanta diskussioner kan hittas på Talk:Unix time. Hjälp gärna till att se till att ifrågasatta påståenden har tillförlitliga källor. (April 2016) (Lär dig hur och när du tar bort det här mallmeddelandet)

En annan, mycket mer sällsynt, avvikande variant av Unix-tidshållning innebär att TAI kodas i stället för UTC; vissa Linuxsystem är konfigurerade på detta sätt. Eftersom TAI inte har några skottsekunder, och varje TAI-dag är exakt 86400 sekunder lång, är denna kodning faktiskt en ren linjär räkning av sekunder som förflutit sedan 1970-01-01T00:00:00:00 TAI. Detta gör tidsintervallsaritmetik mycket enklare. Tidsvärden från dessa system lider inte av den tvetydighet som strikt överensstämmande POSIX-system eller NTP-drivna system har.

I dessa system är det nödvändigt att konsultera en tabell över skottsekunder för att korrekt konvertera mellan UTC och pseudo-Unix-tidsrepresentationen. Detta liknar det sätt på vilket tabeller över tidszoner måste konsulteras för att konvertera till och från civil tid; IANA:s databas över tidszoner innehåller information om skottsekunder, och den exempelkod som finns tillgänglig från samma källa använder denna information för att konvertera mellan TAI-baserade tidsstämplar och lokal tid. Konvertering stöter också på definitionsproblem före 1972 då den nuvarande formen av UTC började användas (se avsnittet UTC-basis nedan).

Detta TAI-baserade system är, trots sin ytliga likhet, inte Unix-tid. Det kodar tider med värden som skiljer sig med flera sekunder från POSIX-tidsvärdena. En version av detta system föreslogs ingå i ISO C:s time.h, men endast UTC-delen godkändes 2011. En tai_clock finns dock i C++20.

Representera taletRedigera

Ett Unix-tidstal kan representeras i vilken form som helst som kan representera tal. I vissa tillämpningar representeras numret helt enkelt textuellt som en sträng av decimalsiffror, vilket endast ger upphov till triviala ytterligare problem. Vissa binära representationer av Unix-tider är dock särskilt betydelsefulla.

Den Unix time_t-datatyp som representerar en tidpunkt är på många plattformar ett signerat heltal, traditionellt med 32 bitar (men se nedan), som direkt kodar Unix-tidstalet enligt beskrivningen i föregående avsnitt. Att vara 32 bitar innebär att den täcker ett intervall på totalt cirka 136 år. Det minsta representerbara datumet är fredagen 1901-12-13 och det högsta representerbara datumet är tisdagen 2038-01-19. En sekund efter 03:14:07 UTC 2038-01-19 kommer den här representationen att svämma över. Denna milstolpe väntas med en blandning av underhållning och skräck – se år 2038-problemet.

I vissa nyare operativsystem har time_t breddats till 64 bitar. Detta utökar de tider som kan representeras med cirka 293 miljarder år i båda riktningarna, vilket är över tjugo gånger universums nuvarande ålder per riktning.

Det fanns ursprungligen en viss kontrovers om huruvida Unix time_t skulle vara signerat eller osignerat. Om den var osignerad skulle dess räckvidd i framtiden fördubblas, vilket skulle skjuta upp 32-bitarsöverflödet (med 68 år). Den skulle då dock inte kunna representera tider före epoken. Det råder konsensus om att time_t ska vara signerad, och detta är den vanliga metoden. Programvaruutvecklingsplattformen för version 6 av QNX-operativsystemet har en osignerad 32-bitars time_t, även om äldre versioner använde en signerad typ.

Specifikationerna för POSIX och Open Group Unix innehåller standardbiblioteket C, som innehåller tidstyperna och funktionerna som definieras i headerfilen <time.h>. ISO C-standarden anger att time_t måste vara en aritmetisk typ, men föreskriver ingen specifik typ eller kodning för den. POSIX kräver att time_t ska vara en heltalstyp, men föreskriver inte att den ska vara signerad eller osignerad.

Unix har ingen tradition av att direkt representera icke heltaliga Unix-tidstal som binära bråk. Istället representeras tider med precision under en sekund med hjälp av sammansatta datatyper som består av två heltal, där det första är time_t (den integrerade delen av Unix-tiden) och det andra är den bråkiga delen av tidstalet i miljondelar (i struct timeval) eller miljarddelar (i struct timespec). Dessa strukturer ger ett decimalbaserat fastpunktsdataformat som är användbart för vissa tillämpningar och trivialt att konvertera för andra.

UTC-basEdit

Den nuvarande formen av UTC, med skottsekunder, är definierad först från och med den 1 januari 1972. Dessförinnan, sedan den 1 januari 1961, fanns det en äldre form av UTC där det inte bara förekom tillfälliga tidssteg, som var med icke heltalssiffror av sekunder, utan även UTC-sekunden var något längre än SI-sekunden, och ändrades periodiskt för att kontinuerligt närma sig jordens rotation. Före 1961 fanns det ingen UTC, och före 1958 fanns det ingen utbredd atomtidmätning; under dessa epoker användes någon approximation av GMT (baserad direkt på jordens rotation) i stället för en atomtidskala.

Den exakta definitionen av Unix-tid som en kodning av UTC är endast okontroversiell när den tillämpas på den nuvarande formen av UTC. Unix-epoken före starten av denna form av UTC påverkar inte dess användning i denna tid: antalet dagar från den 1 januari 1970 (Unix-epoken) till den 1 januari 1972 (starten av UTC) är inte ifrågasatt, och antalet dagar är allt som har betydelse för Unix-tiden.

Betydelsen av Unix-tidsvärden under +63072000 (dvs. före den 1 januari 1972) är inte exakt definierad. Grunden för sådana Unix-tider kan bäst förstås som en ospecificerad approximation av UTC. Datorerna på den tiden hade sällan klockor som var tillräckligt noggrant inställda för att ge meningsfulla tidsstämplar på under en sekund i alla fall. Unixtid är inte ett lämpligt sätt att representera tider före 1972 i tillämpningar som kräver subsekundersprecision; sådana tillämpningar måste åtminstone definiera vilken form av UT eller GMT de använder.

Sedan 2009 överväger man möjligheten att upphöra med användningen av skottsekunder i civil tid. Ett troligt sätt att genomföra denna förändring är att definiera en ny tidsskala, kallad internationell tid, som till en början överensstämmer med UTC men som därefter inte har några skottsekunder, vilket innebär att den förblir konstant förskjuten från TAI. Om detta sker är det troligt att Unix-tid i framtiden kommer att definieras i termer av denna nya tidsskala i stället för UTC. Osäkerheten om huruvida detta kommer att ske gör den framtida Unix-tiden inte mindre förutsägbar än den redan är: om UTC helt enkelt inte skulle ha några ytterligare skottsekunder skulle resultatet bli detsamma.

Lämna ett svar

Din e-postadress kommer inte publiceras.