Warum speichert Unix Zeitstempel in einer Ganzzahl mit Vorzeichen?

24

Warum wird eine vorzeichenbehaftete Ganzzahl zur Darstellung von Zeitstempeln verwendet? Es gibt einen klar definierten Start bei 1970, der als 0 dargestellt wird. Warum sollten wir also vorher Zahlen brauchen? Werden negative Zeitstempel irgendwo verwendet?

Bakudan
quelle
2
Deshalb konnte Nostradamus seinen Computer nicht verwenden, um seine Vorhersagen für die Jahre 3000+ zu schreiben. Dies würde einen Überlauf verursachen und seine Daten als negativ anzeigen. Ich denke, sie haben es den Y3K-Bug oder so genannt!
1.
3
Die alten Römer hatten ein noch größeres Problem, als die Jahreszahlen von negativ zu positiv wechselten. Sie hätten es das Y0K-Problem genannt, wenn sie die Zahl Null hätten ausdrücken können. 8-)}
Keith Thompson

Antworten:

35

Frühe Versionen von C hatten keine vorzeichenlosen ganzen Zahlen. (Einige Programmierer verwendeten Zeiger, wenn sie vorzeichenlose Arithmetik benötigten.) Ich weiß nicht, welche als erstes kamen, welche time()Funktion oder welche vorzeichenlosen Typen, aber ich vermute, dass die Darstellung hergestellt wurde, bevor vorzeichenlose Typen allgemein verfügbar waren. Und 2038 war in der Zukunft weit genug, dass es sich wahrscheinlich nicht lohnte, sich Sorgen zu machen. Ich bezweifle, dass viele Leute dachten, Unix würde bis dahin noch existieren.

Ein weiterer Vorteil von signed time_tist, dass Sie durch eine Erweiterung auf 64 Bit (was auf einigen Systemen bereits vorkommt) Zeiten von mehreren hundert Milliarden Jahren in die Zukunft abbilden können, ohne die Fähigkeit zu verlieren, Zeiten vor 1970 abzubilden 32-Bit ohne Vorzeichen time_t , wir haben genug Zeit, um auf 64-Bit umzusteigen.)

Keith Thompson
quelle
7
Die timeFunktion ist älter als die Epoche: Unix v1 (1971) wird ab Mitternacht am 1.1.1971 in Einheiten von 1/60 Sekunde gezählt. Es war bereits ein bekannter Fehler , dass „Der chronologische - gesinnten Anwender wird feststellen , dass 2 ** 32/60 von nur etwa 2,5 Einer zweiten Jahren.“ unsigned Wurde von eingeführt K & R 1978 , auch nach der 1970 Epoche gegründet wurde.
Gilles 'SO- hör auf böse zu sein'
Ich habe einen schnellen Test gemacht und auf meiner 64-Bit-Linux-Box. gmtimeund localtimemaximal im Jahr 2147483647 (mit der nächsten Sekunde nach -2147483648 als Jahr). Um mehr als 55 Bit Zeit zu haben, muss die Ausgaberoutine aktualisiert werden, sodass ein 64-Bit-Int für das Jahr anstelle eines vorzeichenlosen 32-Bit-Int verwendet wird. Hoffentlich wird sich irgendwann in den nächsten paar Milliarden Jahren jemand um diesen Fehler kümmern.
freiheit
@freiheit: Interessant. Das Problem dort ist, dass der struct tmTyp ein Mitglied tm_year(das Jahre seit 1900 darstellt) hat, das vom Typ ist int. 64-Bit-Systeme können problemlos über 64-Bit- time_tVersionen verfügen, in der Regel jedoch über 32-Bit-Versionen int. (Wenn char8 Bit und int64 Bit vorhanden sind, shortkann dies entweder 16 oder 32 Bit sein, und für die andere Größe gibt es keinen vordefinierten Typ.) Dies time()ist jedoch wahrscheinlich die einzige Funktion, für <time.h>die eine Unterstützung auf Systemebene erforderlich ist. Sie können Ihren eigenen Code schreiben, um time_tWerte in lesbare Zeichenfolgen umzuwandeln .
Keith Thompson
12

Es soll Zeitstempel und Daten vor dem 1. Januar 1970 unterstützen.

Amphetamachine
quelle
1
Das sind erst 68 Jahre in der Vergangenheit - 1902. Das scheint ein bisschen.
Bakudan
2
POSIX muss nicht time_tnur aus 32 Bit bestehen. Auf vielen Systemen sind es bereits 64 Bit.
Keith Thompson
1
mktime()Die Funktion gibt -1im Fehlerfall zurück, so dass es wahrscheinlich unmöglich ist, zwischen korrekten Zeitstempeln vor dem 01.01.1970 und Fehlern zu unterscheiden. Bewerbungstermine vor dem 01.01.1970 sind verboten
DimG 21.04.17
@DimG: Es ist schwierig, zwischen einem Fehler und dem spezifischen Zeitstempel zu unterscheiden 1969-12-31 23:59:59 UTC. Ein anderer negativer Wert als -1ist eindeutig.
Keith Thompson
1
@mtraceur: Der C-Standard erfordert keinen fehlgeschlagenen mktime()Aufruf zum Festlegen errno. (POSIX tut.)
Keith Thompson