Due strati di codifica costituiscono il tempo Unix. Il primo strato codifica un punto nel tempo come un numero reale scalare che rappresenta il numero di secondi passati dalle 00:00:00 UTC di giovedì 1 gennaio 1970. Il secondo strato codifica quel numero come una sequenza di bit o cifre decimali.
Come è standard con UTC, questo articolo etichetta i giorni usando il calendario gregoriano, e conta i tempi in ogni giorno in ore, minuti e secondi. Alcuni degli esempi mostrano anche il Tempo Atomico Internazionale (TAI), un altro schema temporale che usa gli stessi secondi e viene visualizzato nello stesso formato dell’UTC, ma in cui ogni giorno è lungo esattamente 86400 secondi, perdendo gradualmente la sincronizzazione con la rotazione terrestre al ritmo di circa un secondo all’anno.
Codificare il tempo come un numeroModifica
Il tempo Unix è un singolo numero firmato che aumenta ogni secondo, il che lo rende più facile da memorizzare e manipolare per i computer rispetto ai tradizionali sistemi di data. I programmi di interpretazione possono poi convertirlo in un formato leggibile dall’uomo.
L’epoca Unix è l’ora 00:00:00 UTC del 1° gennaio 1970. C’è un problema con questa definizione, in quanto UTC non esisteva nella sua forma attuale fino al 1972; questo problema è discusso più avanti. Per brevità, il resto di questa sezione usa il formato di data e ora ISO 8601, in cui l’epoca Unix è 1970-01-01T00:00:00Z.
Il numero di tempo Unix è zero all’epoca Unix, e aumenta esattamente di 86400 al giorno dall’epoca. Così 2004-09-16T00:00:00Z, 12677 giorni dopo l’epoca, è rappresentato dal numero di tempo Unix 12677 × 86400 = 1095292800. Questo può essere esteso anche all’indietro dall’epoca, usando numeri negativi; così 1957-10-04T00:00:00Z, 4472 giorni prima dell’epoca, è rappresentato dal numero di tempo Unix -4472 × 86400 = -386380800. Questo si applica anche all’interno dei giorni; il numero di tempo in qualsiasi momento di un giorno è il numero di secondi che è passato dalla mezzanotte che inizia quel giorno aggiunto al numero di tempo di quella mezzanotte.
Perché il tempo di Unix è basato su un’epoca, e a causa di un malinteso comune che l’epoca di Unix è l’unica epoca (spesso chiamata “l’Epoca” ), il tempo di Unix è talvolta indicato come tempo Epoca.
Leap secondsEdit
Lo schema di cui sopra significa che in un normale giorno UTC, che ha una durata di 86400 secondi, il numero del tempo Unix cambia in modo continuo attraverso la mezzanotte. Per esempio, alla fine del giorno utilizzato negli esempi precedenti, le rappresentazioni temporali progrediscono come segue:
Quando si verifica un secondo bisestile, il giorno UTC non è esattamente lungo 86400 secondi e il numero temporale Unix (che aumenta sempre esattamente di 86400 ogni giorno) sperimenta una discontinuità. I secondi bisestili possono essere positivi o negativi. Nessun secondo bisestile negativo è mai stato dichiarato, ma se lo fosse, allora alla fine di un giorno con un secondo bisestile negativo, il numero di tempo Unix salterebbe di 1 all’inizio del giorno successivo. Durante un secondo bisestile positivo alla fine di un giorno, che si verifica in media ogni anno e mezzo, il numero di tempo Unix aumenta continuamente nel giorno successivo durante il secondo bisestile e poi alla fine del secondo bisestile salta indietro di 1 (tornando all’inizio del giorno successivo). Per esempio, questo è ciò che è successo sui sistemi POSIX.1 strettamente conformi alla fine del 1998:
I numeri temporali Unix sono ripetuti nel secondo immediatamente successivo a un secondo bisestile positivo. Il numero di tempo Unix 1483142400 è quindi ambiguo: può riferirsi sia all’inizio del secondo bisestile (2016-12-31 23:59:60) sia alla fine di esso, un secondo dopo (2017-01-01 00:00:00). Nel caso teorico in cui si verifica un secondo bisestile negativo, non c’è ambiguità, ma invece c’è una gamma di numeri di tempo Unix che non si riferiscono a nessun punto nel tempo UTC.
Un orologio Unix è spesso implementato con un diverso tipo di gestione del secondo bisestile positivo associato al Network Time Protocol (NTP). Questo produce un sistema che non è conforme allo standard POSIX. Vedere la sezione sottostante riguardante NTP per i dettagli.
Quando si tratta di periodi che non comprendono un secondo intercalare UTC, la differenza tra due numeri di tempo Unix è uguale alla durata in secondi del periodo tra i corrispondenti punti nel tempo. Questa è una tecnica di calcolo comune. Tuttavia, quando si verificano secondi bisestili, questi calcoli danno una risposta sbagliata. Nelle applicazioni in cui è richiesto questo livello di precisione, è necessario consultare una tabella dei secondi bisestili quando si ha a che fare con i tempi Unix, ed è spesso preferibile utilizzare una codifica temporale diversa che non soffre di questo problema.
Un numero di tempo Unix è facilmente riconvertito in un tempo UTC prendendo il quoziente e il modulo del numero di tempo Unix, modulo 86400. Il quoziente è il numero di giorni dall’epoca, e il modulo è il numero di secondi dalla mezzanotte UTC di quel giorno. Se viene dato un numero di tempo Unix che è ambiguo a causa di un secondo bisestile positivo, questo algoritmo lo interpreta come il tempo subito dopo la mezzanotte. Non genera mai un tempo che sia durante un secondo bisestile. Se viene dato un numero di tempo Unix che non è valido a causa di un secondo bisestile negativo, genera un tempo UTC altrettanto non valido. Se queste condizioni sono significative, è necessario consultare una tabella dei secondi bisestili per rilevarle.
Variante non sincrona basata sul Network Time ProtocolModifica
Comunemente un orologio Unix stile Mills è implementato con una gestione dei secondi bisestili non sincrona con il cambiamento del numero di tempo Unix. Il numero di tempo inizialmente diminuisce dove dovrebbe essersi verificato un salto, e poi salta al tempo corretto 1 secondo dopo il salto. Questo rende l’implementazione più facile, ed è descritto nel documento di Mills. Questo è ciò che accade in un secondo bisestile positivo:
Questo può essere decodificato correttamente prestando attenzione alla variabile di stato del secondo bisestile, che indica senza ambiguità se il salto è già stato eseguito. Il cambiamento della variabile di stato è sincrono con il salto.
Una situazione simile si verifica con un secondo bisestile negativo, dove il secondo che viene saltato è leggermente troppo tardi. Molto brevemente il sistema mostra un numero di tempo nominalmente impossibile, ma questo può essere rilevato dallo stato TIME_DEL e corretto.
In questo tipo di sistema il numero di tempo Unix viola POSIX intorno a entrambi i tipi di secondo intercalare. Raccogliere la variabile di stato del secondo intercalare insieme al numero di tempo permette una decodifica non ambigua, così il corretto numero di tempo POSIX può essere generato, se lo si desidera, o il tempo UTC completo può essere memorizzato in un formato più adatto.
La logica di decodifica richiesta per far fronte a questo stile di orologio Unix dovrebbe anche decodificare correttamente un ipotetico orologio conforme a POSIX utilizzando la stessa interfaccia. Questo si otterrebbe indicando lo stato TIME_INS durante tutto il secondo intercalare inserito, poi indicando TIME_WAIT durante tutto il secondo successivo mentre si ripete il conteggio dei secondi. Questo richiede una gestione sincrona dei secondi bisestili. Questo è probabilmente il modo migliore per esprimere il tempo UTC in forma di orologio Unix, attraverso un’interfaccia Unix, quando l’orologio sottostante è fondamentalmente non disturbato dai secondi bisestili.
Variante basata sul TAIModifica
Un’altra, molto più rara, variante non conforme di Unix time keeping comporta la codifica TAI piuttosto che UTC; alcuni sistemi Linux sono configurati in questo modo. Poiché il TAI non ha secondi bisestili, e ogni giorno TAI è lungo esattamente 86400 secondi, questa codifica è in realtà un puro conteggio lineare dei secondi trascorsi dal 1970-01-01T00:00:00 TAI. Questo rende l’aritmetica degli intervalli di tempo molto più semplice. I valori temporali di questi sistemi non soffrono dell’ambiguità che hanno i sistemi POSIX strettamente conformi o i sistemi guidati da NTP.
In questi sistemi è necessario consultare una tabella dei secondi bisestili per convertire correttamente tra UTC e la rappresentazione pseudo-temporale di Unix. Questo assomiglia al modo in cui le tabelle dei fusi orari devono essere consultate per convertire da e verso l’ora civile; il database dei fusi orari IANA include informazioni sui secondi bisestili, e il codice di esempio disponibile dalla stessa fonte usa queste informazioni per convertire tra gli orari basati su TAI e l’ora locale. La conversione si imbatte anche in problemi di definizione prima dell’inizio del 1972 dell’attuale forma di UTC (vedi la sezione Base UTC qui sotto).
Questo sistema basato sul TAI, nonostante la sua somiglianza superficiale, non è il tempo Unix. Codifica i tempi con valori che differiscono di diversi secondi dai valori del tempo POSIX. Una versione di questo sistema è stata proposta per l’inclusione in time.h
di ISO C, ma solo la parte UTC è stata accettata nel 2011. Un tai_clock
esiste comunque in C++20.
Rappresentare il numeroEdit
Un numero di tempo Unix può essere rappresentato in qualsiasi forma capace di rappresentare numeri. In alcune applicazioni il numero è semplicemente rappresentato testualmente come una stringa di cifre decimali, sollevando solo banali problemi aggiuntivi. Tuttavia, alcune rappresentazioni binarie dei tempi Unix sono particolarmente significative.
Il tipo di dati Unix time_t
che rappresenta un punto nel tempo è, su molte piattaforme, un intero firmato, tradizionalmente di 32 bit (ma vedi sotto), che codifica direttamente il numero temporale Unix come descritto nella sezione precedente. Essere di 32 bit significa che copre un intervallo di circa 136 anni in totale. La data minima rappresentabile è venerdì 1901-12-13, e la data massima rappresentabile è martedì 2038-01-19. Un secondo dopo le 03:14:07 UTC 2038-01-19 questa rappresentazione trabocca. Questa pietra miliare è prevista con un misto di divertimento e terrore – vedi problema dell’anno 2038.
In alcuni sistemi operativi più recenti, time_t
è stato ampliato a 64 bit. Questo espande i tempi rappresentabili di circa 293 miliardi di anni in entrambe le direzioni, che è più di venti volte l’età attuale dell’universo per direzione.
All’inizio c’era qualche controversia se il time_t
di Unix dovesse essere firmato o senza segno. Se non firmato, il suo raggio d’azione in futuro sarebbe raddoppiato, posticipando l’overflow a 32 bit (di 68 anni). Tuttavia, sarebbe incapace di rappresentare tempi precedenti all’epoca. Il consenso è per time_t
essere firmato, e questa è la pratica abituale. La piattaforma di sviluppo software per la versione 6 del sistema operativo QNX ha un time_t
non firmato a 32 bit, anche se le versioni precedenti usavano un tipo firmato.
Le specifiche POSIX e Open Group Unix includono la libreria standard C, che include i tipi di tempo e le funzioni definite nel file header <time.h>
. Lo standard ISO C afferma che time_t
deve essere un tipo aritmetico, ma non impone alcun tipo o codifica specifica per esso. POSIX richiede che time_t
sia un tipo intero, ma non impone che sia firmato o non firmato.
Unix non ha la tradizione di rappresentare direttamente i numeri di tempo Unix non interi come frazioni binarie. Invece, i tempi con precisione inferiore al secondo sono rappresentati usando tipi di dati compositi che consistono di due interi, il primo è un time_t
(la parte integrale del tempo Unix), e il secondo è la parte frazionaria del numero di tempo in milionesimi (in struct timeval
) o miliardesimi (in struct timespec
). Queste strutture forniscono un formato di dati a virgola fissa basato sul decimale, utile per alcune applicazioni e banale da convertire per altre.
Base UTCModifica
La forma attuale di UTC, con i secondi bisestili, è definita solo a partire dal 1° gennaio 1972. Prima di allora, dal 1º gennaio 1961 c’era una forma più vecchia di UTC in cui non solo c’erano passi temporali occasionali, che erano di numeri non interi di secondi, ma anche il secondo UTC era leggermente più lungo del secondo SI, e cambiava periodicamente per approssimare continuamente la rotazione della Terra. Prima del 1961 non c’era UTC, e prima del 1958 non c’era un timekeeping atomico diffuso; in queste epoche, veniva usata una qualche approssimazione di GMT (basata direttamente sulla rotazione terrestre) invece di una scala temporale atomica.
La definizione precisa del tempo Unix come codifica di UTC è solo incontestabile quando applicata alla forma attuale di UTC. L’epoca di Unix che precede l’inizio di questa forma di UTC non influisce sul suo uso in quest’epoca: il numero di giorni dal 1° gennaio 1970 (l’epoca di Unix) al 1° gennaio 1972 (l’inizio di UTC) non è in discussione, e il numero di giorni è tutto ciò che è significativo per il tempo Unix.
Il significato dei valori del tempo Unix sotto +63072000 (cioè, prima del 1° gennaio 1972) non è definito con precisione. La base di tali tempi Unix è meglio intesa come un’approssimazione non specificata di UTC. I computer di quell’epoca raramente avevano orologi regolati con sufficiente precisione per fornire timestamp significativi al di sotto del secondo in ogni caso. Il tempo Unix non è un modo adatto per rappresentare i tempi precedenti al 1972 in applicazioni che richiedono precisione al sub-secondo; tali applicazioni devono, almeno, definire quale forma di UT o GMT usano.
A partire dal 2009, si sta considerando la possibilità di porre fine all’uso dei secondi bisestili nel tempo civile. Un mezzo probabile per eseguire questo cambiamento è quello di definire una nuova scala temporale, chiamata Tempo Internazionale, che inizialmente corrisponde a UTC ma in seguito non ha secondi bisestili, rimanendo così ad un offset costante dal TAI. Se questo accade, è probabile che il tempo Unix venga prospetticamente definito in termini di questa nuova scala temporale, invece che di UTC. L’incertezza sul fatto che questo accada rende il tempo Unix prospettico non meno prevedibile di quanto non lo sia già: se UTC dovesse semplicemente non avere più secondi intercalari il risultato sarebbe lo stesso.