Unix Timestamp UTC Spiegato: Fusi Orari, Offset e Conversioni

Mappa mondiale con fusi orari UTC e timestamp Unix collegato a più orologi locali

Se hai mai salvato una data in un database, costruito un'API, o fatto debug su un bug di scheduling che compariva solo in certi paesi, hai sicuramente incontrato la relazione tra Unix timestamp e UTC. La confusione è reale e causa bug in produzione. Questo articolo spiega in modo preciso cos'è UTC, perché i Unix timestamp sono definiti in UTC per default, come funzionano gli offset di fuso orario e come convertire correttamente i timestamp in JavaScript, Python e PHP. Troverai anche gli errori più comuni che fanno gli sviluppatori e come evitarli.

Punti chiave:

  • Un Unix timestamp conta sempre i secondi a partire dal 1° gennaio 1970, 00:00:00 UTC - non ha alcun fuso orario associato.
  • UTC è il punto di riferimento universale; l'ora locale è semplicemente UTC più o meno un offset.
  • Convertire correttamente un timestamp in ora locale richiede di conoscere il fuso orario di destinazione, non solo un numero di offset.
  • L'ora legale (DST) modifica l'offset di un fuso orario, ed è per questo che scrivere gli offset nel codice in modo fisso genera bug.

Cos'è UTC e perché è importante?

UTC sta per Coordinated Universal Time (Tempo Universale Coordinato). È lo standard di riferimento primario con cui il mondo regola orologi e misura il tempo. A differenza dei fusi orari, UTC non ha offset - è il punto zero. Non prevede l'ora legale e non si sposta per nessun paese o regione.

Prima di UTC esisteva il GMT (Greenwich Mean Time), e molte persone usano ancora i due termini in modo intercambiabile. Tecnicamente, UTC e GMT differiscono leggermente, ma per la maggior parte delle applicazioni software vengono trattati come equivalenti. UTC è stato formalmente definito dalla raccomandazione ITU-R TF.460 ed è mantenuto tramite orologi atomici.

Per gli sviluppatori, UTC è fondamentale perché fornisce un unico punto di riferimento non ambiguo. Se il tuo server a Francoforte e il tuo utente a Los Angeles registrano entrambi un evento usando UTC, puoi sempre confrontare quei due timestamp in modo corretto. Se ciascuno lo registra in ora locale senza metadati, hai un problema.

Perché i Unix timestamp sono sempre UTC

Un Unix timestamp (chiamato anche epoch time o POSIX time) è definito come il numero di secondi trascorsi dal 1° gennaio 1970, 00:00:00 UTC. Quel punto di ancoraggio - la mezzanotte del 1° gennaio 1970 in UTC - è parte integrante della definizione. Non esiste una versione del Unix time che parta dall'ora locale di New York o di Tokyo.

Questo significa che la risposta alla domanda "un Unix timestamp è sempre UTC?" è sì, per definizione. Il numero 1700000000 rappresenta lo stesso identico momento nel tempo per ogni persona sul pianeta. Ciò che cambia tra gli utenti è come quel momento viene visualizzato nel loro fuso orario locale.

Per approfondire le basi di questo concetto, leggi il nostro articolo su Epoch Time: le basi dei Unix timestamp.

Questo design ancorato a UTC è una delle proprietà più utili del Unix time. Poiché il numero stesso non contiene informazioni sul fuso orario, due sistemi in paesi diversi possono scambiarsi un timestamp e sapere entrambi esattamente a quale momento si riferisce, senza alcuna negoziazione aggiuntiva.

UTC vs. ora locale e fusi orari

UTC è il riferimento. L'ora locale è ciò che ottieni quando applichi una regola di fuso orario su di esso. Un fuso orario non è solo un offset fisso - è una regione con un nome e un insieme di regole che possono cambiare nel tempo (principalmente a causa dell'ora legale).

Ad esempio, l'"Eastern Time" negli Stati Uniti è UTC-5 in inverno e UTC-4 in estate. Il nome del fuso orario è "America/New_York" nel database dei fusi orari IANA, che è la fonte autorevole usata dalla maggior parte dei linguaggi di programmazione e dei sistemi operativi.

La conclusione pratica: quando salvi un Unix timestamp nel tuo database, stai salvando un valore UTC. Quando lo mostri a un utente, lo converti nel suo fuso orario locale. Non salvare mai l'ora locale come numero grezzo assumendo che sia UTC. È lì che iniziano i bug.

Come funzionano gli offset UTC

Un offset UTC descrive quanto un fuso orario si discosta da UTC. Si scrive come +HH:MM o -HH:MM. Alcuni esempi:

  • UTC+02:00 - Ora legale dell'Europa centrale (CEST), usata in Germania e Francia durante l'estate.
  • UTC-05:00 - Eastern Standard Time (EST), usato sulla costa est degli USA in inverno.
  • UTC+05:30 - India Standard Time (IST), che ha un offset di mezz'ora.
  • UTC+00:00 - UTC stesso, usato anche dal Regno Unito in inverno (GMT).

Per convertire manualmente un epoch time UTC in ora locale, si aggiunge o sottrae l'offset in secondi. Per UTC+02:00, sono 2 * 3600 = 7200 secondi. Quindi se il tuo Unix timestamp è 1700000000, l'ora locale in UTC+02:00 corrisponde a 1700000000 + 7200 prima della formattazione.

Tuttavia, farlo manualmente è rischioso perché gli offset cambiano con l'ora legale. Usa sempre una libreria per la gestione dei fusi orari invece di scrivere un offset fisso nel codice. Consulta la nostra guida su come convertire un Unix timestamp in data per un approfondimento sui metodi di conversione.

Convertire Unix timestamp in ora locale

Ecco un esempio concreto usando il Unix timestamp 1700000000, che corrisponde al 14 novembre 2023, 22:13:20 UTC. Lo convertiremo in "America/New_York" (UTC-5 a novembre) in tre linguaggi.

JavaScript

const ts = 1700000000;

// JavaScript Date accetta millisecondi
const date = new Date(ts * 1000);

// Visualizza nell'ora locale di New York
const options = {
  timeZone: 'America/New_York',
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit',
  timeZoneName: 'short'
};

console.log(date.toLocaleString('en-US', options));
// Output: November 14, 2023 at 05:13:20 PM EST

Nota che l'oggetto Date di JavaScript memorizza il tempo internamente come millisecondi UTC. Il metodo toLocaleString con l'opzione timeZone gestisce per te l'offset e le regole sull'ora legale.

Python

from datetime import datetime, timezone
import zoneinfo  # Python 3.9+

ts = 1700000000

# Crea un datetime con timezone UTC dal timestamp
utc_dt = datetime.fromtimestamp(ts, tz=timezone.utc)

# Converti nell'ora locale di New York
ny_tz = zoneinfo.ZoneInfo('America/New_York')
local_dt = utc_dt.astimezone(ny_tz)

print(local_dt.strftime('%Y-%m-%d %H:%M:%S %Z'))
# Output: 2023-11-14 17:13:20 EST

Il punto fondamentale è usare datetime.fromtimestamp(ts, tz=timezone.utc). Se ometti l'argomento tz, Python usa il fuso orario locale del server per interpretare il timestamp - ed è una fonte comune di bug.

PHP

$ts = 1700000000;

// Crea un oggetto DateTime dal Unix timestamp (sempre UTC)
$dt = new DateTime('@' . $ts);

// Imposta il fuso orario di destinazione
$dt->setTimezone(new DateTimeZone('America/New_York'));

echo $dt->format('Y-m-d H:i:s T');
// Output: 2023-11-14 17:13:20 EST

In PHP, il prefisso @ nella costruzione di un oggetto DateTime indica a PHP di trattare il valore come un Unix timestamp (UTC). Senza di esso, PHP potrebbe interpretare la stringa usando il fuso orario di default del server.

Errori comuni degli sviluppatori

Anche gli sviluppatori più esperti inciampano nella gestione dei fusi orari. Ecco i problemi più frequenti:

1. Assumere che l'ora locale del server sia UTC

Se il tuo server è impostato su "Europe/Rome" e chiami time() in PHP o datetime.now() in Python senza un argomento per il fuso orario, ottieni l'ora locale - non UTC. Sii sempre esplicito riguardo a UTC quando registri i timestamp.

2. Scrivere offset UTC fissi nel codice invece di usare nomi di fuso orario

Usare +02:00 come offset fisso per la Germania andrà in errore in inverno, quando la Germania passa a +01:00. Usa sempre fusi orari con nome come Europe/Berlin in modo che la libreria applichi automaticamente le regole sull'ora legale corrette.

3. Salvare i timestamp come stringhe di ora locale senza metadati sul fuso orario

Una stringa come 2023-11-14 17:13:20 in un database è ambigua. È UTC? EST? CET? Se salvi i timestamp come interi Unix o come stringhe ISO 8601 con un offset UTC (ad es. 2023-11-14T22:13:20Z), il significato è non ambiguo. Consulta il nostro confronto tra Unix Timestamp e ISO 8601 per capire quale scegliere.

4. Ignorare l'ora legale nella pianificazione dei job

Se pianifichi un job da eseguire "alle 09:00 ogni giorno" aggiungendo 86400 secondi all'ultima esecuzione, si sfaserà di un'ora nei giorni in cui cambia l'ora legale. Usa una libreria di scheduling o un cron che comprenda le regole dei fusi orari.

5. Confondere millisecondi e secondi

JavaScript usa i millisecondi per il suo oggetto Date, ma la maggior parte dei Unix timestamp è in secondi. Passare un timestamp in secondi a new Date() senza moltiplicare per 1000 restituisce una data nel gennaio 1970. Questo argomento è trattato in dettaglio nel nostro articolo su secondi, millisecondi e microsecondi.

Conclusione

Unix timestamp e UTC sono inseparabili per definizione. Il timestamp è sempre un valore UTC - un conteggio di secondi da un punto di ancoraggio UTC fisso. L'ora locale è solo un formato di visualizzazione, non un tipo diverso di timestamp. L'approccio più sicuro è salvare tutto in UTC, convertire in ora locale solo al momento della visualizzazione, e usare sempre fusi orari con nome invece di offset scritti nel codice in modo fisso. Segui queste regole e la maggior parte dei bug legati ai fusi orari smette semplicemente di verificarsi. Per le best practice su come salvare questi valori, consulta la nostra guida su Unix timestamp nei database.

Converti Unix timestamp in UTC o ora locale con unixtimestamp.app

Converti qualsiasi Unix timestamp in UTC o ora locale - Istantaneamente

Incolla qualsiasi Unix timestamp e visualizzalo convertito in UTC e nel tuo fuso orario locale con un solo clic. Gratuito, senza registrazione, compatibile con secondi e millisecondi.

Prova il nostro strumento gratuito →

Sì. Per definizione, un Unix epoch timestamp conta i secondi dal 1° gennaio 1970, 00:00:00 UTC. Il numero stesso non contiene alcun fuso orario - è un valore UTC. Il fuso orario diventa rilevante solo quando converti il timestamp in una data e ora leggibile dall'utente per la visualizzazione.

Usa la libreria per i fusi orari integrata nel tuo linguaggio. In JavaScript, usa toLocaleString con l'opzione timeZone. In Python, usa datetime.fromtimestamp(ts, tz=timezone.utc).astimezone() con un fuso orario con nome. In PHP, crea un DateTime dal timestamp e chiama setTimezone(). Usa sempre fusi orari con nome, non offset grezzi.

Di solito accade perché una funzione sta usando il fuso orario di default del server invece di UTC per interpretare il timestamp. In Python, omettere l'argomento tz a datetime.fromtimestamp() usa l'ora di sistema locale. In PHP, non usare il prefisso @ ha lo stesso effetto. Sii sempre esplicito riguardo a UTC al momento della creazione.

Un offset UTC è il numero di ore (e a volte minuti) di cui un fuso orario è in anticipo o in ritardo rispetto a UTC. Ad esempio, UTC-05:00 è cinque ore indietro rispetto a UTC. Quando si converte un Unix timestamp in ora locale, l'offset viene applicato al valore UTC. Poiché gli offset cambiano con l'ora legale, dovresti usare un fuso orario con nome invece di un offset scritto nel codice in modo fisso.

Sì, ed è uno dei principali vantaggi dei Unix timestamp. Poiché ogni timestamp è un valore UTC, puoi confrontare direttamente due timestamp qualsiasi come interi. Un numero più alto indica sempre un momento successivo nel tempo, indipendentemente da dove sono stati generati i timestamp. Non è necessaria alcuna conversione di fuso orario per il confronto.