¿Por qué Unix almacena marcas de tiempo en un entero con signo?

24

¿Por qué se usa un entero con signo para representar marcas de tiempo? Hay un comienzo claramente definido en 1970 que se representa como 0, entonces, ¿por qué necesitaríamos números antes de eso? ¿Se usan marcas de tiempo negativas en alguna parte?

Bakudan
fuente
2
Es por eso que Nostradamus no pudo usar su computadora para escribir sus predicciones para los años 3000+ ... causaría un desbordamiento y mostraría sus fechas como negativas. ¡Creo que lo llamaron el error Y3K o algo así!
Jeach
3
Los antiguos romanos tuvieron un problema aún peor cuando los números del año cambiaron de negativo a positivo. Lo habrían llamado el problema Y0K si hubieran tenido una forma de expresar el número cero. 8-)}
Keith Thompson

Respuestas:

35

Las primeras versiones de C no tenían enteros sin signo. (Algunos programadores usaron punteros cuando necesitaban aritmética sin signo). No sé cuál vino primero, la time()función o los tipos sin signo, pero sospecho que la representación se estableció antes de que los tipos sin signo estuvieran disponibles universalmente. Y 2038 estaba lo suficientemente lejos en el futuro que probablemente no valía la pena preocuparse. Dudo que mucha gente pensara que Unix todavía existiría para entonces.

Otra ventaja de un firmado time_tes que extenderlo a 64 bits (que ya está sucediendo en algunos sistemas) le permite representar varios cientos de millones de años en el futuro sin perder la capacidad de representar tiempos anteriores a 1970. (Es por eso que me opongo a cambiar a un 32 bits sin signo time_t ; tenemos tiempo suficiente para hacer la transición a 64 bits).

Keith Thompson
fuente
77
La timefunción es más antigua que la época: Unix v1 (en 1971) contaba en unidades de 1/60 de segundo, desde la medianoche del 1 de enero de 1971. Ya era un error conocido que "el usuario con mentalidad cronológica notará que 2 ** 32 sexagésimas de segundo son solo unos 2.5 años". unsigned Fue introducido por K&R en 1978 , mucho después de que se estableciera la época de 1970.
Gilles 'SO- deja de ser malvado'
Hice una prueba rápida y en mi caja de Linux de 64 bits. gmtimey localtimemáximo en el año 2147483647 (con el siguiente segundo después de dar -2147483648 como año). Entonces, para pasar más de 55 bits de tiempo, alguien tendrá que actualizar la rutina de salida para usar un int de 64 bits durante el año en lugar de un int de 32 bits sin signo. Esperemos que alguien se encargue de ese error en algún momento de los próximos mil millones de años.
Freiheit
@freiheit: Interesante. El problema es que el struct tmtipo tiene un miembro tm_year(que representa años desde 1900) que es de tipo int. Los sistemas de 64 bits pueden tener fácilmente un de 64 bits time_t, pero generalmente tienen uno de 32 bits int. (Si chares de 8 bits y intes de 64 bits, shortpuede ser de 16 o 32 bits, y no habrá un tipo predefinido para el otro tamaño). Pero time()es probablemente la única función <time.h>que realmente requiere soporte a nivel de sistema; puede escribir su propio código para convertir time_tvalores en cadenas legibles por humanos.
Keith Thompson
12

Es para admitir marcas de tiempo y fechas anteriores al 1 de enero de 1970.

anfetamaquina
fuente
1
Esto hace solo 68 años en el pasado - 1902. Esto parece bastante poco.
Bakudan
2
POSIX no requiere time_ttener solo 32 bits; Ya es de 64 bits en muchos sistemas.
Keith Thompson el
1
mktime()la función regresa -1en caso de error, por lo que probablemente sea imposible distinguir entre las marcas de tiempo correctas antes de 1970-01-01 y el error ts. Las fechas de aparición antes de 1970-01-01 están prohibidas
DimG
@DimG: Es difícil distinguir entre un error y la marca de tiempo específica 1969-12-31 23:59:59 UTC. Un valor negativo que -1no sea inequívoco.
Keith Thompson
1
@mtraceur: El estándar C no requiere una mktime()llamada fallida para establecer errno. (POSIX sí.)
Keith Thompson