Dos capas de codificación componen el tiempo Unix. La primera capa codifica un punto en el tiempo como un número real escalar que representa el número de segundos que han pasado desde las 00:00:00 UTC del jueves 1 de enero de 1970. La segunda capa codifica ese número como una secuencia de bits o dígitos decimales.
Como es estándar con UTC, este artículo etiqueta los días usando el calendario gregoriano, y cuenta los tiempos dentro de cada día en horas, minutos y segundos. Algunos de los ejemplos también muestran el Tiempo Atómico Internacional (TAI), otro esquema de tiempo que utiliza los mismos segundos y se muestra en el mismo formato que el UTC, pero en el que cada día dura exactamente 86400 segundos, perdiendo gradualmente la sincronización con la rotación de la Tierra a un ritmo de aproximadamente un segundo por año.
Codificación del tiempo como un númeroEditar
La hora de Unix es un único número con signo que se incrementa cada segundo, lo que hace que sea más fácil para los ordenadores almacenar y manipular que los sistemas de fecha convencionales. Los programas de interpretación pueden entonces convertirlo a un formato legible para los humanos.
La época de Unix es la hora 00:00:00 UTC del 1 de enero de 1970. Hay un problema con esta definición, ya que UTC no existió en su forma actual hasta 1972; esta cuestión se discute más adelante. Por brevedad, el resto de esta sección utiliza el formato de fecha y hora ISO 8601, en el que la época de Unix es 1970-01-01T00:00:00Z.
El número de tiempo de Unix es cero en la época de Unix, y aumenta exactamente 86400 por día desde la época. Así, 2004-09-16T00:00:00Z, 12677 días después de la época, está representado por el número de tiempo Unix 12677 × 86400 = 1095292800. Esto también puede extenderse hacia atrás desde la época, utilizando números negativos; así, 1957-10-04T00:00:00Z, 4472 días antes de la época, se representa con el número de tiempo Unix -4472 × 86400 = -386380800. Esto se aplica dentro de los días también; el número de tiempo en cualquier momento de un día es el número de segundos que ha pasado desde la medianoche que comienza ese día añadido al número de tiempo de esa medianoche.
Debido a que el tiempo de Unix se basa en una época, y debido a un malentendido común de que la época de Unix es la única época (a menudo llamado «la época» ), el tiempo de Unix se refiere a veces como tiempo de la época.
Segundos bisiestosEditar
El esquema anterior significa que en un día UTC normal, que tiene una duración de 86400 segundos, el número de tiempo de Unix cambia de manera continua a través de la medianoche. Por ejemplo, al final del día utilizado en los ejemplos anteriores, las representaciones del tiempo progresan de la siguiente manera:
Cuando se produce un segundo bisiesto, el día UTC no tiene exactamente 86400 segundos de duración y el número de tiempo Unix (que siempre aumenta exactamente en 86400 cada día) experimenta una discontinuidad. Los segundos bisiestos pueden ser positivos o negativos. Nunca se ha declarado un segundo bisiesto negativo, pero si lo hubiera, al final de un día con un segundo bisiesto negativo, el número de tiempo de Unix saltaría en 1 hasta el comienzo del día siguiente. Durante un segundo bisiesto positivo al final de un día, que ocurre aproximadamente cada año y medio en promedio, el número de tiempo de Unix aumenta continuamente hasta el día siguiente durante el segundo bisiesto y luego al final del segundo bisiesto salta de nuevo en 1 (volviendo al comienzo del día siguiente). Por ejemplo, esto es lo que ocurrió en los sistemas POSIX.1 estrictamente conformes a finales de 1998:
Los números de tiempo Unix se repiten en el segundo inmediatamente posterior a un segundo bisiesto positivo. El número de tiempo Unix 1483142400 es, por tanto, ambiguo: puede referirse tanto al inicio del segundo bisiesto (2016-12-31 23:59:60) como al final del mismo, un segundo después (2017-01-01 00:00:00). En el caso teórico de que se produzca un segundo bisiesto negativo, no se produce ninguna ambigüedad, sino que hay un rango de números de hora Unix que no se refieren a ningún punto de la hora UTC en absoluto.
Un reloj Unix se implementa a menudo con un tipo diferente de manejo de segundos bisiestos positivos asociado al Protocolo de Tiempo de Red (NTP). Esto produce un sistema que no se ajusta al estándar POSIX. Ver la sección más abajo sobre NTP para más detalles.
Cuando se trata de períodos que no abarcan un segundo bisiesto UTC, la diferencia entre dos números de tiempo Unix es igual a la duración en segundos del período entre los puntos correspondientes en el tiempo. Esta es una técnica computacional común. Sin embargo, cuando hay segundos bisiestos, estos cálculos dan una respuesta errónea. En aplicaciones donde se requiere este nivel de precisión, es necesario consultar una tabla de segundos bisiestos cuando se trata de tiempos Unix, y a menudo es preferible utilizar una codificación de tiempo diferente que no sufre de este problema.
Un número de tiempo Unix se convierte fácilmente de nuevo en un tiempo UTC tomando el cociente y el módulo del número de tiempo Unix, módulo 86400. El cociente es el número de días desde la época, y el módulo es el número de segundos desde la medianoche UTC de ese día. Si se da un número de hora Unix que es ambiguo debido a un segundo bisiesto positivo, este algoritmo lo interpreta como la hora justo después de la medianoche. Nunca genera una hora que esté durante un segundo bisiesto. Si se da un número de hora Unix que no es válido debido a un segundo bisiesto negativo, genera una hora UTC igualmente inválida. Si estas condiciones son significativas, es necesario consultar una tabla de segundos bisiestos para detectarlos.
Variante no sincrónica basada en el Protocolo de Tiempo de RedEditar
Comúnmente se implementa un reloj Unix estilo Mills con manejo de segundos bisiestos no sincrónicos con el cambio del número de hora Unix. El número de tiempo inicialmente disminuye donde debería haber ocurrido un salto, y luego salta a la hora correcta 1 segundo después del salto. Esto facilita la implementación, y se describe en el documento de Mills. Esto es lo que sucede a través de un segundo de salto positivo:
Esto se puede decodificar correctamente prestando atención a la variable de estado del segundo de salto, que indica sin ambigüedad si el salto se ha realizado ya. El cambio de la variable de estado es sincrónico con el salto.
Una situación similar se produce con un segundo bisiesto negativo, en el que el segundo que se salta está ligeramente retrasado. Muy brevemente el sistema muestra un número de tiempo nominalmente imposible, pero esto puede ser detectado por el estado TIME_DEL y corregido.
En este tipo de sistema el número de tiempo de Unix viola POSIX alrededor de ambos tipos de segundo bisiesto. Recoger la variable de estado del segundo bisiesto junto con el número de tiempo permite una decodificación inequívoca, por lo que el número de tiempo POSIX correcto puede ser generado si se desea, o la hora UTC completa puede ser almacenada en un formato más adecuado.
La lógica de decodificación requerida para hacer frente a este estilo de reloj Unix también decodificaría correctamente un hipotético reloj conforme a POSIX utilizando la misma interfaz. Esto se lograría indicando el estado TIME_INS durante la totalidad de un segundo bisiesto insertado, luego indicando TIME_WAIT durante la totalidad del siguiente segundo mientras se repite la cuenta de segundos. Esto requiere una gestión sincrónica de los segundos bisiestos. Esta es probablemente la mejor manera de expresar el tiempo UTC en forma de reloj Unix, a través de una interfaz Unix, cuando el reloj subyacente es fundamentalmente sin problemas por los segundos bisiestos.
Variante basada en TAIEdit
Otra variante, mucho más rara, no conforme con el mantenimiento de la hora de Unix implica la codificación de TAI en lugar de UTC; algunos sistemas Linux están configurados de esta manera. Debido a que el TAI no tiene segundos bisiestos, y a que cada día TAI dura exactamente 86400 segundos, esta codificación es en realidad una cuenta lineal pura de los segundos transcurridos desde 1970-01-01T00:00:00 TAI. Esto hace que la aritmética de los intervalos de tiempo sea mucho más fácil. Los valores de tiempo de estos sistemas no sufren la ambigüedad que tienen los sistemas POSIX estrictamente conformes o los sistemas impulsados por NTP.
En estos sistemas es necesario consultar una tabla de segundos bisiestos para convertir correctamente entre UTC y la representación de tiempo pseudo-Unix. Esto se asemeja a la forma en que se deben consultar las tablas de zonas horarias para convertir hacia y desde la hora civil; la base de datos de zonas horarias de IANA incluye información sobre los segundos intercalares, y el código de ejemplo disponible en la misma fuente utiliza esa información para convertir entre las marcas de tiempo basadas en TAI y la hora local. La conversión también se encuentra con problemas de definición anteriores al inicio en 1972 de la forma actual de UTC (véase la sección Base UTC más adelante).
Este sistema basado en TAI, a pesar de su parecido superficial, no es la hora de Unix. Codifica tiempos con valores que difieren en varios segundos de los valores de tiempo POSIX. Se propuso una versión de este sistema para su inclusión en time.h
de ISO C, pero sólo se aceptó la parte UTC en 2011. Sin embargo, existe un tai_clock
en C++20.
Representación del númeroEditar
Un número de tiempo de Unix puede representarse de cualquier forma capaz de representar números. En algunas aplicaciones el número es simplemente representado textualmente como una cadena de dígitos decimales, planteando sólo problemas adicionales triviales. Sin embargo, ciertas representaciones binarias de los tiempos Unix son particularmente significativas.
El tipo de datos Unix time_t
que representa un punto en el tiempo es, en muchas plataformas, un entero con signo, tradicionalmente de 32 bits (pero ver más abajo), codificando directamente el número de tiempo Unix como se describe en la sección anterior. El hecho de ser de 32 bits significa que cubre un rango de unos 136 años en total. La fecha mínima representable es el viernes 1901-12-13, y la fecha máxima representable es el martes 2038-01-19. Un segundo después de las 03:14:07 UTC del 2038-01-19 esta representación se desbordará. Este hito se anticipa con una mezcla de diversión y temor-ver el problema del año 2038.
En algunos sistemas operativos más recientes, time_t
se ha ampliado a 64 bits. Esto amplía los tiempos representables en aproximadamente 293.000 millones de años en ambas direcciones, lo que supone más de veinte veces la edad actual del universo por dirección.
Originalmente hubo cierta controversia sobre si el time_t
de Unix debía ser con o sin signo. Si fuera sin signo, su rango en el futuro se duplicaría, posponiendo el desbordamiento de 32 bits (en 68 años). Sin embargo, entonces sería incapaz de representar tiempos anteriores a la época. El consenso es que time_t
tenga signo, y ésta es la práctica habitual. La plataforma de desarrollo de software para la versión 6 del sistema operativo QNX tiene un time_t
de 32 bits sin signo, aunque las versiones anteriores utilizaban un tipo con signo.
Las especificaciones POSIX y Open Group Unix incluyen la biblioteca estándar C, que incluye los tipos y funciones de tiempo definidos en el archivo de cabecera <time.h>
. El estándar ISO C establece que time_t
debe ser un tipo aritmético, pero no exige ningún tipo o codificación específica para él. POSIX requiere que time_t
sea un tipo entero, pero no exige que sea con o sin signo.
Unix no tiene tradición de representar directamente los números de tiempo no enteros de Unix como fracciones binarias. En su lugar, los tiempos con una precisión inferior al segundo se representan utilizando tipos de datos compuestos que constan de dos enteros, siendo el primero un time_t
(la parte integral del tiempo Unix), y el segundo la parte fraccionaria del número de tiempo en millonésimas (en struct timeval
) o milmillonésimas (en struct timespec
). Estas estructuras proporcionan un formato de datos de punto fijo basado en decimales, que es útil para algunas aplicaciones, y trivial de convertir para otras.
Base UTCEditar
La forma actual de UTC, con segundos bisiestos, se define sólo a partir del 1 de enero de 1972. Antes de eso, desde el 1 de enero de 1961 había una forma más antigua de UTC en la que no sólo había pasos de tiempo ocasionales, que eran por números no enteros de segundos, sino que también el segundo UTC era ligeramente más largo que el segundo SI, y cambiaba periódicamente para aproximarse continuamente a la rotación de la Tierra. Antes de 1961 no existía el UTC, y antes de 1958 no se había generalizado el cronometraje atómico; en estas épocas, se utilizaba alguna aproximación del GMT (basada directamente en la rotación de la Tierra) en lugar de una escala de tiempo atómica.
La definición precisa de la hora Unix como codificación del UTC sólo es incontrovertible cuando se aplica a la forma actual del UTC. La época de Unix anterior al inicio de esta forma de UTC no afecta a su uso en esta época: el número de días desde el 1 de enero de 1970 (la época de Unix) hasta el 1 de enero de 1972 (el inicio de UTC) no se cuestiona, y el número de días es todo lo que es significativo para el tiempo de Unix.
El significado de los valores de tiempo de Unix por debajo de +63072000 (es decir, antes del 1 de enero de 1972) no está definido con precisión. La base de tales tiempos Unix se entiende mejor como una aproximación no especificada de UTC. Los ordenadores de esa época rara vez tenían relojes lo suficientemente precisos como para proporcionar marcas de tiempo de sub-segundos significativas en cualquier caso. La hora de Unix no es una forma adecuada de representar tiempos anteriores a 1972 en aplicaciones que requieren precisión de sub-segundos; tales aplicaciones deben, al menos, definir qué forma de UT o GMT utilizan.
A partir de 2009, se está considerando la posibilidad de poner fin al uso de los segundos bisiestos en la hora civil. Un medio probable para ejecutar este cambio es definir una nueva escala de tiempo, llamada Hora Internacional, que inicialmente coincida con la UTC pero que a partir de entonces no tenga segundos bisiestos, permaneciendo así con un desfase constante respecto al TAI. Si esto ocurre, es probable que la hora de Unix se defina prospectivamente en términos de esta nueva escala de tiempo, en lugar de UTC. La incertidumbre sobre si esto ocurrirá hace que la hora Unix prospectiva no sea menos predecible de lo que ya es: si el UTC simplemente no tuviera más segundos bisiestos el resultado sería el mismo.