De Unix-tijd bestaat uit twee coderingslagen. De eerste laag codeert een tijdstip als een scalair reëel getal dat het aantal seconden weergeeft dat is verstreken sinds 00:00:00 UTC donderdag, 1 januari 1970. De tweede laag codeert dat getal als een opeenvolging van bits of decimale cijfers.
Zoals standaard is bij UTC, geeft dit artikel dagen aan met de Gregoriaanse kalender, en telt de tijd binnen elke dag in uren, minuten, en seconden. Sommige voorbeelden tonen ook de Internationale Atoomtijd (TAI), een ander tijdschema dat dezelfde seconden gebruikt en in hetzelfde formaat wordt weergegeven als UTC, maar waarin elke dag precies 86400 seconden lang is, en geleidelijk de synchronisatie met de draaiing van de aarde verliest met een snelheid van ruwweg één seconde per jaar.
De tijd coderen als een getalEdit
Unix-tijd is een enkel ondertekend getal dat elke seconde toeneemt, waardoor het voor computers gemakkelijker is op te slaan en te manipuleren dan conventionele datumsystemen. Interpreterprogramma’s kunnen het dan omzetten naar een voor mensen leesbaar formaat.
De Unix epoch is de tijd 00:00:00 UTC op 1 januari 1970. Er is een probleem met deze definitie, in die zin dat UTC pas in 1972 in zijn huidige vorm bestond; dit probleem wordt hieronder besproken. Om het kort te houden, wordt in de rest van deze paragraaf het ISO 8601 datum- en tijdformaat gebruikt, waarin de Unix epoche 1970-01-01T00:00:00Z is.
Het Unix-tijdgetal is nul bij de Unix epoch, en neemt met precies 86400 per dag toe sinds de epoch. Dus 2004-09-16T00:00:00Z, 12677 dagen na de epoche, wordt vertegenwoordigd door het Unix-tijdgetal 12677 × 86400 = 1095292800. Dit kan ook teruggerekend worden vanaf de epoche, met negatieve getallen; dus 1957-10-04T00:00:00Z, 4472 dagen voor de epoche, wordt voorgesteld door het Unix-tijdsgetal -4472 × 86400 = -386380800. Dit geldt ook binnen dagen; het tijdnummer op elk gegeven tijdstip van een dag is het aantal seconden dat is verstreken sinds middernacht die dag begon opgeteld bij het tijdnummer van die middernacht.
Omdat Unix-tijd is gebaseerd op een epoche, en vanwege een veelvoorkomend misverstand dat de Unix-epoche de enige epoche is (vaak “de Epoche” genoemd ), wordt Unix-tijd soms aangeduid als Epoche-tijd.
SchrikkelsecondenEdit
Het bovenstaande schema betekent dat op een normale UTC-dag, die een duur heeft van 86400 seconden, het Unix-tijdnummer op een continue manier verandert over middernacht. Bijvoorbeeld, aan het eind van de dag die in de voorbeelden hierboven is gebruikt, verlopen de tijdvoorstellingen als volgt:
Wanneer een schrikkelseconde optreedt, is de UTC-dag niet precies 86400 seconden lang en ondervindt het Unix-tijdnummer (dat elke dag altijd met precies 86400 toeneemt) een discontinuïteit. Schrikkelseconden kunnen positief of negatief zijn. Er is nog nooit een negatieve schrikkelseconde afgekondigd, maar als dat wel zo zou zijn, dan zou aan het eind van een dag met een negatieve schrikkelseconde het Unix-tijdgetal met 1 omhoog springen naar het begin van de volgende dag. Tijdens een positieve schrikkelseconde aan het eind van een dag, die gemiddeld ongeveer elke anderhalf jaar voorkomt, loopt het Unix-tijdgetal tijdens de schrikkelseconde continu op naar de volgende dag en springt dan aan het eind van de schrikkelseconde met 1 terug (terug naar het begin van de volgende dag). Dit is bijvoorbeeld wat er gebeurde op strikt conforme POSIX.1 systemen aan het eind van 1998:
Unix-tijdnummers worden herhaald in de seconde direct volgend op een positieve schrikkelseconde. Het Unix-tijdnummer 1483142400 is dus ambigu: het kan zowel verwijzen naar het begin van de schrikkelseconde (2016-12-31 23:59:60) als naar het einde ervan, een seconde later (2017-01-01 00:00:00). In het theoretische geval dat een negatieve schrikkelseconde optreedt, wordt geen ambiguïteit veroorzaakt, maar is er in plaats daarvan een reeks Unix-tijdnummers die helemaal niet naar een punt in UTC-tijd verwijzen.
Een Unix-klok is vaak geïmplementeerd met een ander type afhandeling van positieve schrikkelseconden, geassocieerd met het Network Time Protocol (NTP). Dit levert een systeem op dat niet voldoet aan de POSIX-standaard. Zie de paragraaf hieronder over NTP voor details.
Wanneer we te maken hebben met perioden die geen UTC-schrikkelseconde omvatten, is het verschil tussen twee Unix-tijdnummers gelijk aan de duur in seconden van de periode tussen de overeenkomstige tijdstippen. Dit is een gebruikelijke rekentechniek. Echter, waar schrikkelseconden voorkomen, geven zulke berekeningen het verkeerde antwoord. In toepassingen waar dit niveau van nauwkeurigheid vereist is, is het nodig om een tabel met schrikkelseconden te raadplegen wanneer Unix-tijden worden gebruikt, en het is vaak beter om een andere tijdcodering te gebruiken die geen last heeft van dit probleem.
Een Unix-tijdnummer kan eenvoudig worden teruggerekend naar een UTC-tijd door het quotiënt en de modulus van het Unix-tijdnummer te nemen, modulo 86400. Het quotiënt is het aantal dagen sinds de epoche, en de modulus is het aantal seconden sinds middernacht UTC op die dag. Als een Unix-tijdnummer wordt gegeven dat dubbelzinnig is vanwege een positieve schrikkelseconde, interpreteert dit algoritme het als de tijd net na middernacht. Het genereert nooit een tijd die tijdens een schrikkelseconde valt. Als een Unix-tijdnummer ongeldig is vanwege een negatieve schrikkelseconde, dan genereert het een even ongeldige UTC-tijd. Als deze omstandigheden significant zijn, is het nodig om een tabel met schrikkelseconden te raadplegen om ze te detecteren.
Niet-synchrone Network Time Protocol-gebaseerde variantEdit
Normaal is een Mills-style Unix klok geïmplementeerd met een schrikkelseconde afhandeling die niet synchroon loopt met de verandering van het Unix-tijdnummer. Het tijdnummer neemt eerst af waar een schrikkel had moeten plaatsvinden, en springt dan 1 seconde na de schrikkel naar de juiste tijd. Dit maakt de implementatie eenvoudiger, en wordt beschreven in het artikel van Mills. Dit is wat er gebeurt over een positieve schrikkelseconde:
Dit kan goed worden gedecodeerd door te letten op de schrikkelseconde toestandsvariabele, die ondubbelzinnig aangeeft of de schrikkel al is uitgevoerd. De verandering van de toestandsvariabele loopt synchroon met de schrikkel.
Een soortgelijke situatie doet zich voor bij een negatieve schrikkelseconde, waarbij de seconde die wordt overgeslagen iets te laat is. Heel even toont het systeem een nominaal onmogelijk tijdnummer, maar dit kan worden gedetecteerd door de TIME_DEL toestand en gecorrigeerd.
In dit type systeem is het Unix-tijdnummer in strijd met POSIX rond beide soorten schrikkelseconden. Het verzamelen van de schrikkelseconde toestandsvariabele samen met het tijdnummer maakt een ondubbelzinnige decodering mogelijk, zodat desgewenst het juiste POSIX-tijdnummer kan worden gegenereerd, of de volledige UTC-tijd kan worden opgeslagen in een geschikter formaat.
De decoderingslogica die nodig is om met dit type Unix-klok om te gaan, zou ook een hypothetische POSIX-conforme klok correct decoderen met gebruikmaking van dezelfde interface. Dit zou worden bereikt door de status TIME_INS aan te geven gedurende de gehele ingevoegde schrikkelseconde, en dan TIME_WAIT aan te geven gedurende de gehele volgende seconde terwijl het tellen van de seconden wordt herhaald. Dit vereist synchrone afhandeling van schrikkelseconden. Dit is waarschijnlijk de beste manier om UTC-tijd in Unix-klokvorm uit te drukken, via een Unix-interface, als de onderliggende klok fundamenteel geen last heeft van schrikkelseconden.
TAI-gebaseerde variantEdit
Een andere, veel zeldzamere, niet-conforme variant van Unix-tijdwaarneming omvat het coderen van TAI in plaats van UTC; sommige Linux-systemen zijn op deze manier geconfigureerd. Omdat TAI geen schrikkelseconden kent, en elke TAI-dag precies 86400 seconden lang is, is deze codering eigenlijk een pure lineaire telling van verstreken seconden sinds 1970-01-01T00:00:00 TAI. Dit maakt het rekenen met tijdsintervallen veel eenvoudiger. Tijdwaarden van deze systemen hebben niet de dubbelzinnigheid die strikt conforme POSIX systemen of NTP-gestuurde systemen wel hebben.
In deze systemen is het nodig om een tabel met schrikkelseconden te raadplegen om correct om te rekenen tussen UTC en de pseudo-Unix-tijd weergave. Dit lijkt op de manier waarop tijdzonetabellen moeten worden geraadpleegd om om te rekenen naar en van civiele tijd; de IANA tijdzonedatabase bevat informatie over schrikkelseconden, en de voorbeeldcode die beschikbaar is via dezelfde bron gebruikt die informatie om te rekenen tussen op TAI gebaseerde tijdstempels en lokale tijd. Conversie stuit ook op definitieproblemen voorafgaand aan het begin van de huidige vorm van UTC in 1972 (zie de paragraaf UTC-basis hieronder).
Dit op TAI gebaseerde systeem is, ondanks zijn oppervlakkige gelijkenis, geen Unix-tijd. Het codeert tijden met waarden die enkele seconden afwijken van de POSIX-tijdwaarden. Een versie van dit systeem werd voorgesteld voor opname in ISO C’s time.h
, maar alleen het UTC-gedeelte werd in 2011 aanvaard. Een tai_clock
bestaat echter wel in C++20.
Het getal weergevenEdit
Een Unix-tijdnummer kan worden weergegeven in elke vorm waarmee getallen kunnen worden weergegeven. In sommige toepassingen wordt het getal eenvoudigweg tekstueel weergegeven als een reeks decimale cijfers, wat slechts triviale extra problemen oplevert. Bepaalde binaire weergaven van Unix-tijden zijn echter van bijzonder belang.
Het Unix time_t
-gegevenstype dat een tijdstip weergeeft is, op veel platforms, een ondertekend geheel getal, traditioneel van 32 bits (maar zie hieronder), dat direct het Unix-tijdnummer codeert zoals beschreven in de vorige sectie. Het feit dat het 32 bits is betekent dat het een bereik heeft van ongeveer 136 jaar in totaal. De minimum representeerbare datum is vrijdag 1901-12-13, en de maximum representeerbare datum is dinsdag 2038-01-19. Een seconde na 03:14:07 UTC 2038-01-19 zal deze weergave overlopen. Deze mijlpaal wordt met een mengeling van amusement en angst tegemoet gezien-zie het jaar 2038 probleem.
In sommige nieuwere besturingssystemen is time_t
verbreed tot 64 bits. Dit vergroot de tijd die kan worden weergegeven met ongeveer 293 miljard jaar in beide richtingen, dat is meer dan twintig keer de huidige leeftijd van het universum per richting.
Er was oorspronkelijk enige controverse over de vraag of de Unix time_t
ondertekend of niet ondertekend moest zijn. Indien unsigned, zou zijn bereik in de toekomst worden verdubbeld, waardoor de 32-bit overflow zou worden uitgesteld (met 68 jaar). Het zou dan echter niet in staat zijn om tijden van vóór de epoche weer te geven. De consensus is dat time_t
ondertekend moet zijn, en dit is de gebruikelijke praktijk. Het software-ontwikkelingsplatform voor versie 6 van het QNX-besturingssysteem heeft een niet-ondertekende 32-bit time_t
, hoewel oudere versies een ondertekend type gebruikten.
De POSIX en Open Group Unix specificaties bevatten de C standaard bibliotheek, die de tijdtypen en functies bevat die zijn gedefinieerd in het <time.h>
header-bestand. De ISO C standaard stelt dat time_t
een rekenkundig type moet zijn, maar schrijft geen specifiek type of codering voor. POSIX vereist dat time_t
een integer type is, maar schrijft niet voor dat het signed of unsigned moet zijn.
Unix heeft geen traditie in het direct weergeven van niet-integer Unix-tijdgetallen als binaire fracties. In plaats daarvan worden tijden met sub-seconde-precisie weergegeven met samengestelde gegevenstypen die bestaan uit twee gehele getallen, waarvan het eerste een time_t
is (het integrale deel van de Unix-tijd), en het tweede het fractionele deel van het tijdnummer in miljoensten (in struct timeval
) of miljardsten (in struct timespec
). Deze structuren bieden een decimaal-gebaseerd fixed-point data formaat, dat nuttig is voor sommige toepassingen, en triviaal om te zetten voor andere.
UTC basisEdit
De huidige vorm van UTC, met schrikkelseconden, is pas gedefinieerd vanaf 1 januari 1972. Daarvoor, sinds 1 januari 1961 was er een oudere vorm van UTC waarin niet alleen af en toe tijdstappen waren, die door niet-integer aantallen seconden, maar ook de UTC seconde iets langer was dan de SI seconde, en periodiek veranderde om de rotatie van de aarde voortdurend te benaderen. Vóór 1961 was er geen UTC, en vóór 1958 was er geen wijdverbreide atomaire tijdrekening; in deze tijdperken werd een benadering van GMT (direct gebaseerd op de draaiing van de Aarde) gebruikt in plaats van een atomaire tijdschaal.
De precieze definitie van Unix-tijd als een codering van UTC is alleen oncontroversieel wanneer toegepast op de huidige vorm van UTC. Het Unix-tijdperk dat voorafgaat aan het begin van deze vorm van UTC heeft geen invloed op het gebruik ervan in dit tijdperk: het aantal dagen van 1 januari 1970 (het Unix-tijdperk) tot 1 januari 1972 (het begin van UTC) staat niet ter discussie, en het aantal dagen is alles wat van belang is voor de Unix-tijd.
De betekenis van Unix-tijdwaarden onder +63072000 (d.w.z. vóór 1 januari 1972) is niet nauwkeurig gedefinieerd. De basis van zulke Unix-tijden kan het beste worden opgevat als een niet nader omschreven benadering van UTC. Computers uit die tijd hadden zelden klokken die nauwkeurig genoeg waren ingesteld om in elk geval zinvolle subseconde-tijdstempels te leveren. Unix-tijd is geen geschikte manier om tijden van voor 1972 weer te geven in toepassingen die subseconde-precisie vereisen; dergelijke toepassingen moeten op zijn minst definiëren welke vorm van UT of GMT ze gebruiken.
Vanaf 2009 wordt de mogelijkheid overwogen om het gebruik van schrikkelseconden in de burgerlijke tijd te beëindigen. Een mogelijke manier om deze verandering door te voeren is het definiëren van een nieuwe tijdschaal, Internationale Tijd genaamd, die aanvankelijk overeenkomt met UTC, maar daarna geen schrikkelseconden meer heeft, en dus op een constante afwijking van TAI blijft. Als dit gebeurt, is het waarschijnlijk dat de Unix-tijd in de toekomst zal worden gedefinieerd in termen van deze nieuwe tijdschaal, in plaats van UTC. Onzekerheid over de vraag of dit zal gebeuren maakt de toekomstige Unix-tijd niet minder voorspelbaar dan hij al is: als UTC gewoon geen schrikkelseconden meer zou hebben zou het resultaat hetzelfde zijn.