Die Unix-Zeit besteht aus zwei Kodierungsschichten. Die erste Schicht kodiert einen Zeitpunkt als skalare reelle Zahl, die die Anzahl der Sekunden darstellt, die seit 00:00:00 UTC Donnerstag, 1. Januar 1970, vergangen sind. Die zweite Schicht kodiert diese Zahl als eine Folge von Bits oder Dezimalziffern.
Wie bei UTC üblich, werden in diesem Artikel die Tage nach dem gregorianischen Kalender bezeichnet und die Zeiten innerhalb jedes Tages in Stunden, Minuten und Sekunden gezählt. Einige der Beispiele zeigen auch die Internationale Atomzeit (TAI), ein anderes Zeitschema, das die gleichen Sekunden verwendet und im gleichen Format wie UTC angezeigt wird, bei dem aber jeder Tag genau 86400 Sekunden lang ist, wobei die Synchronisation mit der Erdrotation allmählich mit einer Rate von etwa einer Sekunde pro Jahr verloren geht.
Kodierung der Zeit als ZahlBearbeiten
Unix-Zeit ist eine einzelne vorzeichenbehaftete Zahl, die jede Sekunde inkrementiert, wodurch sie für Computer leichter zu speichern und zu bearbeiten ist als herkömmliche Datumssysteme. Interpreterprogramme können sie dann in ein für Menschen lesbares Format umwandeln.
Die Unix-Epoche ist die Zeit 00:00:00 UTC am 1. Januar 1970. Es gibt ein Problem mit dieser Definition, da die UTC in ihrer heutigen Form erst 1972 existierte; dieses Problem wird weiter unten diskutiert. Der Rest dieses Abschnitts verwendet der Kürze halber das ISO 8601 Datums- und Zeitformat, in dem die Unix-Epoche 1970-01-01T00:00:00Z ist.
Die Unix-Zeitnummer ist bei der Unix-Epoche Null und erhöht sich seit der Epoche um genau 86400 pro Tag. So wird 2004-09-16T00:00:00Z, 12677 Tage nach der Epoche, durch die Unix-Zeitnummer 12677 × 86400 = 1095292800 dargestellt. Dies kann auch rückwärts von der Epoche ausgedehnt werden, indem man negative Zahlen verwendet; so wird 1957-10-04T00:00:00Z, 4472 Tage vor der Epoche, durch die Unix-Zeitnummer -4472 × 86400 = -386380800 dargestellt. Dies gilt auch innerhalb von Tagen; die Zeitnummer zu einem bestimmten Zeitpunkt eines Tages ist die Anzahl der Sekunden, die seit der Mitternacht, mit der dieser Tag beginnt, vergangen sind, addiert zur Zeitnummer dieser Mitternacht.
Da die Unix-Zeit auf einer Epoche basiert und aufgrund eines weit verbreiteten Missverständnisses, dass die Unix-Epoche die einzige Epoche ist (oft als „die Epoche“ bezeichnet), wird die Unix-Zeit manchmal als Epochenzeit bezeichnet.
SchaltsekundenBearbeiten
Das obige Schema bedeutet, dass sich an einem normalen UTC-Tag, der eine Dauer von 86400 Sekunden hat, die Unix-Zeitnummer kontinuierlich über Mitternacht ändert. Am Ende des in den obigen Beispielen verwendeten Tages verlaufen die Zeitdarstellungen beispielsweise wie folgt:
Wenn eine Schaltsekunde auftritt, ist der UTC-Tag nicht genau 86400 Sekunden lang und die Unix-Zeitnummer (die sich jeden Tag immer um genau 86400 erhöht) erfährt eine Diskontinuität. Schaltsekunden können positiv oder negativ sein. Es wurde noch nie eine negative Schaltsekunde deklariert, aber wenn dies der Fall wäre, würde die Unix-Zeitnummer am Ende eines Tages mit einer negativen Schaltsekunde zum Beginn des nächsten Tages um 1 hochspringen. Bei einer positiven Schaltsekunde am Ende eines Tages, die im Durchschnitt etwa alle anderthalb Jahre vorkommt, steigt die Unix-Zeitnummer während der Schaltsekunde kontinuierlich bis zum nächsten Tag an und springt dann am Ende der Schaltsekunde um 1 zurück (zurück zum Beginn des nächsten Tages). Dies geschah zum Beispiel auf streng POSIX.1-konformen Systemen Ende 1998:
Unix-Zeitnummern werden in der Sekunde unmittelbar nach einer positiven Schaltsekunde wiederholt. Die Unix-Zeitnummer 1483142400 ist daher zweideutig: Sie kann sich entweder auf den Beginn der Schaltsekunde (2016-12-31 23:59:60) oder auf das Ende der Schaltsekunde, eine Sekunde später (2017-01-01 00:00:00), beziehen. Im theoretischen Fall einer negativen Schaltsekunde entsteht keine Mehrdeutigkeit, sondern es gibt einen Bereich von Unix-Zeitnummern, die sich auf keinen Punkt in der UTC-Zeit beziehen.
Eine Unix-Uhr wird oft mit einer anderen Art von positiver Schaltsekundenbehandlung implementiert, die mit dem Network Time Protocol (NTP) verbunden ist. Dies führt zu einem System, das nicht mit dem POSIX-Standard konform ist. Einzelheiten dazu finden Sie im Abschnitt über NTP.
Bei Zeiträumen, die keine UTC-Schaltsekunde umfassen, ist die Differenz zwischen zwei Unix-Zeitnummern gleich der Dauer des Zeitraums in Sekunden zwischen den entsprechenden Zeitpunkten. Dies ist eine übliche Rechentechnik. In Fällen, in denen Schaltsekunden auftreten, führen solche Berechnungen jedoch zu einer falschen Antwort. In Anwendungen, in denen diese Genauigkeit erforderlich ist, ist es notwendig, eine Tabelle mit Schaltsekunden zu konsultieren, wenn man mit Unix-Zeiten arbeitet, und es ist oft besser, eine andere Zeitkodierung zu verwenden, die nicht unter diesem Problem leidet.
Eine Unix-Zeitnummer lässt sich leicht in eine UTC-Zeit umwandeln, indem man den Quotienten und den Modulus der Unix-Zeitnummer, modulo 86400, nimmt. Der Quotient ist die Anzahl der Tage seit der Epoche, und der Modulus ist die Anzahl der Sekunden seit Mitternacht UTC an diesem Tag. Wird eine Unix-Zeitnummer angegeben, die aufgrund einer positiven Schaltsekunde nicht eindeutig ist, interpretiert dieser Algorithmus sie als die Zeit kurz nach Mitternacht. Er erzeugt niemals eine Zeit, die während einer Schaltsekunde liegt. Wird eine Unix-Zeitnummer angegeben, die aufgrund einer negativen Schaltsekunde ungültig ist, wird eine ebenso ungültige UTC-Zeit erzeugt. Wenn diese Bedingungen signifikant sind, ist es notwendig, eine Tabelle mit Schaltsekunden zu konsultieren, um sie zu erkennen.
Nicht-synchrone Variante auf der Grundlage des Network Time ProtocolBearbeiten
Gemeinsam wird eine Unix-Uhr im Mills-Stil implementiert, bei der die Schaltsekundenbehandlung nicht synchron mit der Änderung der Unix-Zeitnummer erfolgt. Die Zeitnummer verringert sich zunächst an der Stelle, an der ein Schaltvorgang hätte stattfinden sollen, und springt dann eine Sekunde nach dem Schaltvorgang auf die korrekte Zeit. Dies erleichtert die Implementierung und wird in Mills‘ Dokument beschrieben. Dies geschieht bei einer positiven Schaltsekunde:
Dies kann richtig entschlüsselt werden, wenn man auf die Zustandsvariable für die Schaltsekunde achtet, die eindeutig anzeigt, ob der Sprung bereits erfolgt ist. Die Änderung der Zustandsvariablen ist synchron mit dem Schaltsprung.
Eine ähnliche Situation ergibt sich bei einer negativen Schaltsekunde, bei der die übersprungene Sekunde etwas zu spät ist. Ganz kurz zeigt das System eine nominell unmögliche Zeitzahl an, aber das kann durch den TIME_DEL-Zustand erkannt und korrigiert werden.
In dieser Art von System verstößt die Unix-Zeitzahl bei beiden Arten von Schaltsekunden gegen POSIX. Das Sammeln der Schaltsekunden-Zustandsvariable zusammen mit der Zeitnummer ermöglicht eine eindeutige Dekodierung, so dass die korrekte POSIX-Zeitnummer erzeugt werden kann, falls gewünscht, oder die vollständige UTC-Zeit in einem geeigneteren Format gespeichert werden kann.
Die Dekodierungslogik, die erforderlich ist, um mit dieser Art von Unix-Uhr zurechtzukommen, würde auch eine hypothetische POSIX-konforme Uhr korrekt dekodieren, die die gleiche Schnittstelle verwendet. Dies würde dadurch erreicht, dass der Zustand TIME_INS während der gesamten Dauer einer eingefügten Schaltsekunde angezeigt wird und dann TIME_WAIT während der gesamten Dauer der folgenden Sekunde, während die Sekundenzählung wiederholt wird. Dies erfordert eine synchrone Behandlung von Schaltsekunden. Dies ist wahrscheinlich der beste Weg, die UTC-Zeit in Form einer Unix-Uhr über eine Unix-Schnittstelle auszudrücken, wenn die zugrunde liegende Uhr grundsätzlich nicht durch Schaltsekunden gestört wird.
TAI-basierte VarianteBearbeiten
Eine andere, viel seltenere, nicht konforme Variante der Unix-Zeithaltung beinhaltet die Kodierung von TAI anstelle von UTC; einige Linux-Systeme sind auf diese Weise konfiguriert. Da TAI keine Schaltsekunden kennt und jeder TAI-Tag genau 86400 Sekunden lang ist, ist diese Kodierung eigentlich eine rein lineare Zählung der seit 1970-01-01T00:00:00 TAI verstrichenen Sekunden. Das macht die Zeitintervallarithmetik sehr viel einfacher. Zeitwerte aus diesen Systemen leiden nicht unter der Mehrdeutigkeit, die streng konforme POSIX-Systeme oder NTP-gesteuerte Systeme haben.
In diesen Systemen ist es notwendig, eine Tabelle mit Schaltsekunden zu konsultieren, um korrekt zwischen UTC und der Pseudo-Unix-Zeitdarstellung umzurechnen. Dies ähnelt der Art und Weise, wie Zeitzonentabellen konsultiert werden müssen, um in und aus der bürgerlichen Zeit zu konvertieren; die IANA-Zeitzonendatenbank enthält Schaltsekundeninformationen, und der aus derselben Quelle verfügbare Beispielcode verwendet diese Informationen, um zwischen TAI-basierten Zeitstempeln und der Ortszeit zu konvertieren. Die Konvertierung stößt auch auf Definitionsprobleme, die vor dem Beginn der aktuellen Form von UTC im Jahr 1972 auftraten (siehe Abschnitt UTC-Basis unten).
Dieses TAI-basierte System ist trotz seiner oberflächlichen Ähnlichkeit keine Unix-Zeit. Es kodiert Zeiten mit Werten, die sich um mehrere Sekunden von den POSIX-Zeitwerten unterscheiden. Eine Version dieses Systems wurde zur Aufnahme in ISO C’s time.h
vorgeschlagen, aber nur der UTC-Teil wurde 2011 akzeptiert. Eine tai_clock
existiert jedoch in C++20.
Darstellung der ZahlEdit
Eine Unix-Zeitzahl kann in jeder Form dargestellt werden, die Zahlen darstellen kann. In einigen Anwendungen wird die Zahl einfach textuell als eine Kette von Dezimalziffern dargestellt, was nur triviale zusätzliche Probleme aufwirft. Bestimmte binäre Darstellungen von Unix-Zeiten sind jedoch besonders bedeutsam.
Der Unix time_t
-Datentyp, der einen Zeitpunkt repräsentiert, ist auf vielen Plattformen eine vorzeichenbehaftete Ganzzahl, die traditionell aus 32 Bits besteht (siehe jedoch unten) und die Unix-Zeitnummer wie im vorangegangenen Abschnitt beschrieben direkt kodiert. 32 Bits bedeuten, dass es einen Bereich von insgesamt 136 Jahren abdeckt. Das kleinste darstellbare Datum ist Freitag 1901-12-13, das größte darstellbare Datum ist Dienstag 2038-01-19. Eine Sekunde nach 03:14:07 UTC 2038-01-19 wird diese Darstellung überlaufen. Dieser Meilenstein wird mit einer Mischung aus Belustigung und Entsetzen erwartet – siehe das Problem des Jahres 2038.
In einigen neueren Betriebssystemen wurde time_t
auf 64 Bit erweitert. Dies erweitert die darstellbaren Zeiten um etwa 293 Milliarden Jahre in beide Richtungen, was mehr als das Zwanzigfache des gegenwärtigen Alters des Universums pro Richtung ist.
Es gab ursprünglich eine Kontroverse darüber, ob das Unix-time_t
mit oder ohne Vorzeichen sein sollte. Wäre sie vorzeichenlos, würde sich ihre Reichweite in der Zukunft verdoppeln, was den 32-Bit-Überlauf (um 68 Jahre) hinauszögern würde. Allerdings wäre er dann nicht in der Lage, Zeiten vor der Epoche darzustellen. Der Konsens ist, dass time_t
vorzeichenbehaftet ist, und dies ist auch die übliche Praxis. Die Software-Entwicklungsplattform für Version 6 des QNX-Betriebssystems hat ein vorzeichenloses 32-Bit-time_t
, obwohl ältere Versionen einen vorzeichenbehafteten Typ verwendeten.
Die POSIX- und Open-Group-Unix-Spezifikationen enthalten die C-Standardbibliothek, die die in der <time.h>
-Header-Datei definierten Zeittypen und Funktionen enthält. Der ISO C-Standard legt fest, dass time_t
ein arithmetischer Typ sein muss, schreibt aber keinen bestimmten Typ oder eine bestimmte Kodierung vor. POSIX verlangt, dass time_t
ein Integer-Typ ist, schreibt aber nicht vor, dass er vorzeichenbehaftet oder vorzeichenlos sein muss.
Unix hat keine Tradition, nicht-ganzzahlige Unix-Zeitzahlen direkt als binäre Brüche darzustellen. Stattdessen werden Zeiten mit einer Genauigkeit von weniger als einer Sekunde durch zusammengesetzte Datentypen dargestellt, die aus zwei ganzen Zahlen bestehen, wobei die erste eine time_t
(der ganzzahlige Teil der Unix-Zeit) und die zweite der gebrochene Teil der Zeitzahl in Millionstel (in struct timeval
) oder Milliardstel (in struct timespec
) ist. Diese Strukturen bieten ein dezimal-basiertes Festkomma-Datenformat, das für einige Anwendungen nützlich und für andere trivial zu konvertieren ist.
UTC basisEdit
Die gegenwärtige Form von UTC, mit Schaltsekunden, ist erst seit dem 1. Januar 1972 definiert. Davor gab es seit dem 1. Januar 1961 eine ältere Form der UTC, bei der es nicht nur gelegentlich Zeitschritte gab, die nicht ganzzahlig waren, sondern bei der auch die UTC-Sekunde etwas länger war als die SI-Sekunde und sich periodisch änderte, um sich der Erdrotation kontinuierlich anzunähern. Vor 1961 gab es keine UTC, und vor 1958 gab es keine weit verbreitete atomare Zeitmessung; in diesen Epochen wurde anstelle einer atomaren Zeitskala eine Annäherung an die GMT (die direkt auf der Erdrotation basiert) verwendet.
Die genaue Definition der Unix-Zeit als Kodierung der UTC ist nur dann unumstritten, wenn sie auf die heutige Form der UTC angewendet wird. Die Unix-Epoche, die vor dem Beginn dieser Form von UTC liegt, hat keinen Einfluss auf die Verwendung in dieser Ära: Die Anzahl der Tage vom 1. Januar 1970 (der Unix-Epoche) bis zum 1. Januar 1972 (dem Beginn von UTC) steht nicht in Frage, und die Anzahl der Tage ist alles, was für die Unix-Zeit von Bedeutung ist.
Die Bedeutung von Unix-Zeitwerten unter +63072000 (d. h. vor dem 1. Januar 1972) ist nicht genau definiert. Die Grundlage solcher Unix-Zeiten ist am besten als eine nicht näher spezifizierte Annäherung an die UTC zu verstehen. Die Uhren der damaligen Computer waren selten genau genug eingestellt, um sinnvolle Zeitstempel im Subsekundenbereich zu liefern. Die Unix-Zeit ist nicht geeignet, um Zeiten vor 1972 in Anwendungen darzustellen, die eine Genauigkeit von weniger als einer Sekunde erfordern; solche Anwendungen müssen zumindest festlegen, welche Form von UT oder GMT sie verwenden.
Seit 2009 wird die Möglichkeit in Betracht gezogen, die Verwendung von Schaltsekunden in der zivilen Zeit zu beenden. Ein wahrscheinliches Mittel, um diese Änderung durchzuführen, ist die Definition einer neuen Zeitskala, genannt Internationale Zeit, die anfangs mit der UTC übereinstimmt, danach aber keine Schaltsekunden mehr hat und somit einen konstanten Abstand zur TAI aufweist. Wenn dies geschieht, ist es wahrscheinlich, dass die Unix-Zeit in Zukunft anhand dieser neuen Zeitskala anstelle von UTC definiert wird. Die Ungewissheit darüber, ob dies der Fall sein wird, macht die zukünftige Unix-Zeit nicht weniger vorhersehbar, als sie es bereits ist: Wenn UTC einfach keine weiteren Schaltsekunden hätte, wäre das Ergebnis dasselbe.