Почему Unix хранит метки времени в целых числах со знаком?

24

Почему целое число со знаком используется для представления меток времени? В 1970 году четко определено начало, обозначенное как 0, так зачем нам нужны цифры до этого? Используются ли где-нибудь отрицательные метки времени?

Bakudan
источник
2
Вот почему Нострадамус не мог использовать свой компьютер, чтобы написать свои прогнозы на 3000+ лет ... это вызвало бы переполнение и показало бы его даты как отрицательные. Я думаю, что они назвали это ошибкой Y3K или что-то!
Jeach
3
У древних римлян проблема была еще хуже, когда цифры года переключались с отрицательных на положительные. Они бы назвали это проблемой Y0K, если бы у них был способ выразить ноль. 8-)}
Кит Томпсон

Ответы:

35

Ранние версии C не имели целых чисел без знака. (Некоторые программисты использовали указатели, когда им требовалась арифметика без знака.) Я не знаю, что было первым, time()типы функций или без знака, но я подозреваю, что представление было установлено до того, как типы без знака стали общедоступными. И 2038 год был достаточно далеко в будущем, о котором, вероятно, не стоило беспокоиться. Я сомневаюсь, что многие думали, что Unix все еще будет существовать к тому времени.

Другое преимущество подписанного time_tсостоит в том, что расширение его до 64 бит (что уже происходит в некоторых системах) позволяет вам представлять времена в несколько сотен миллиардов лет в будущем, не теряя возможности представлять времена до 1970 года. (Вот почему я против перехода на 32-разрядный без знака time_t ; у нас достаточно времени для перехода на 64-разрядный.)

Кит Томпсон
источник
7
Эта timeфункция старше эпохи: Unix v1 (в 1971 году) отсчитывается с шагом 1/60 секунды с полуночи 1971/01/01. Это была уже известная ошибка: «Хронологически настроенный пользователь заметит, что 2 ** 32 шестидесятых секунды - это всего лишь около 2,5 лет». Он unsigned был введен K & R в 1978 году , задолго до того, как была установлена ​​эпоха 1970 года.
Жиль "ТАК - перестать быть злым"
Я сделал быстрый тест и на моей 64-битной Linux-коробке. gmtimeи localtimeмаксимум в году 2147483647 (со следующей секундой после предоставления -2147483648 в качестве года). Таким образом, чтобы преодолеть 55 бит времени, кому-то придется обновить процедуру вывода, чтобы использовать 64-битное int для года вместо беззнакового 32-битного int. Надеюсь, кто-нибудь позаботится об этой ошибке в ближайшие пару миллиардов лет.
Freiheit
@freiheit: интересно. Проблема в том, что у struct tmтипа есть член tm_year(представляющий годы с 1900 года), который имеет тип int. 64-разрядные системы могут легко иметь 64-разрядные time_t, но обычно они имеют 32-разрядные int. (Если значение charравно 8 битам и intравно 64 битам, то shortможет быть 16 или 32 бита, и не будет предопределенного типа для другого размера.) Но time(), вероятно, это единственная функция, для <time.h>которой действительно требуется поддержка на уровне системы; Вы можете написать свой собственный код для преобразования time_tзначений в понятные человеку строки.
Кит Томпсон
12

Он должен поддерживать временные метки и даты до 1 января 1970 года.

amphetamachine
источник
1
Это составляет всего 68 лет в прошлом - 1902 году. Это кажется совсем немного.
Бакудан
2
POSIX не обязательно time_tдолжен быть только 32 битами; это уже 64 бит на многих системах.
Кит Томпсон
1
mktime()функция возвращает -1в случае ошибки, поэтому, вероятно, невозможно различить правильные временные метки до 1970-01-01 и ошибку ts. Даты до 1970-01-01 запрещены
DimG
@DimG: трудно отличить ошибку от конкретной отметки времени 1969-12-31 23:59:59 UTC. Отрицательное значение, кроме -1однозначного.
Кит Томпсон
1
@mtraceur: стандарт C не требует сбоя mktime()вызова для установки errno. (POSIX делает.)
Кит Томпсон