Ingegneria · 22 settembre 2026

Conversione dei timestamp Unix spiegata: secondi d’epoca, millisecondi e ISO 8601

Un timestamp Unix sembra un singolo intero finché un’confusione di unità non trasforma oggi nel 1970. Secondi d’epoca contro millisecondi, ISO 8601, fusi orari e un cheat sheet di conversione per gli errori classici.

Ogni sistema che memorizza un istante pone prima o poi la stessa domanda: questo numero è in secondi o in millisecondi? I timestamp Unix sembrano banali — un intero che conta i secondi trascorsi dal 1 gennaio 1970 — e proprio per questo vengono gestiti male. Un valore sbagliato di un fattore 1000, una data nel 1970, uno sfasamento di fuso che compare solo negli utenti dall’altra parte del mondo: tutto nasce dai soliti pochi malintesi.

Questo articolo spiega cosa misura davvero un timestamp Unix, come distinguere secondi e millisecondi, come si inserisce ISO 8601 e come convertire tra formati senza indovinare.

Cosa è davvero un timestamp Unix

Un timestamp Unix — chiamato anche epoca — è il numero di secondi trascorsi dalle 00:00:00 UTC del 1 gennaio 1970, l’epoca Unix. È un intero senza informazioni di fuso orario: lo stesso numero descrive lo stesso istante in tutto il mondo.

Non portando con sé un fuso, l’epoca è un formato di scambio naturale per le macchine. API, log, database e code di messaggi memorizzano timestamp; gli esseri umani leggono date. La conversione tra i due mondi è dove vivono gli errori.

Nota cosa un timestamp non contiene: fuso orario, locale o calendario. 1758537600 è un istante. Che a Bangkok siano le 21:00 e a Madrid le 14:00 dipende solo da come lo presentate.

Secondi contro millisecondi: l’errore più frequente

Due convenzioni convivono e si trovano ovunque:

  • Secondi — oggi 10 cifre, per esempio 1758537600. Il Unix storico, Unix() di Go, getEpochSecond() di Java, Redis e la maggior parte dei database usano quest’unità.
  • Millisecondi — 13 cifre, per esempio 1758537600000. Date.now() di JavaScript, getTime() di Java e la maggior parte delle API dei browser usano quest’unità.

Confondere le unità fa saltare la data al 1970 o al 2286. Non esiste una regola universale per riconoscerle, quindi la strada affidabile è conoscere il contratto della fonte. Se dovete indovinare, 10 cifre sono quasi sempre secondi e 13 quasi sempre millisecondi — ma indovinare è l’errore, non la soluzione.

Regola: memorizzate l’unità accanto al valore. Usate un nome di colonna (created_at_ms), un campo API esplicito o una proprietà unit. Qualsiasi cosa è meglio di un intero nudo chiamato time.

ISO 8601: il lato leggibile

Le stringhe ISO 8601 sono il volto opposto dei numeri d’epoca: leggibili, ordinabili in UTC e non ambigue quando riportano uno sfasamento.

2026-09-22T14:00:00Z       # UTC, indicato dalla Z finale
2026-09-22T14:00:00+02:00  # lo stesso istante, ora locale di Berlino
2026-09-22T14:00:00.123Z   # conserva i millisecondi

La Z finale e lo sfasamento numerico non sono decorazioni. Senza uno dei due la stringa non ha fuso e il codice deve indovinare — ed è così che «la stessa ora» diventa silenziosamente un errore di tre ore.

Fusi orari e UTC

Memorizzate e confrontate in UTC, e convertite in un fuso locale nel layer di presentazione, solo quando dovete mostrare qualcosa a una persona.

const now = Date.now();                 // millisecondi dall’epoca
const seconds = Math.floor(now / 1000); // secondi dall’epoca
new Date(seconds * 1000).toISOString(); // "2026-09-22T14:00:00.000Z"

Due regole evitano la maggior parte dei problemi di fuso:

  • Mai confrontare un’ora locale naiva con un’altra. Serializzate prima entrambe in istanti, poi confrontate.
  • Conservate lo sfasamento accanto al valore quando conta il fuso dell’utente (appuntamenti, orari, periodi di fatturazione). Un istante UTC più un identificante IANA come Europe/Rome è meglio di uno sfasamento fisso, perché gli sfasamenti fissi cambiano con l’ora legale.

Cheat sheet di conversione

Convertire JavaScript Python
Millisecondi in stringa data new Date(1758537600000).toISOString() datetime.fromtimestamp(1758537600, tz=timezone.utc)
Stringa data in secondi Math.floor(Date.parse(s) / 1000) int(dt.replace(tzinfo=timezone.utc).timestamp())
Secondi in millisecondi seconds * 1000 seconds * 1000
Ora corrente Date.now() (millisecondi) int(time.time()) (secondi)

Nota che Date.now() restituisce millisecondi mentre time.time() restituisce secondi: l’illustrazione compatta del fatto che l’unità è una convenzione per linguaggio, non uno standard universale.

Errori da evitare

  • Moltiplicare per 1000 «per sicurezza». Decidete in base al contratto, mai in base al numero di cifre.
  • Memorizzare un’ora locale senza sfasamento. L’ora legale romperà l’aritmetica prima o poi.
  • Parsare spezzettando le stringhe. Usate il parser della libreria standard: ISO 8601 porta con sé settimana, formato compatto e frazionari che fanno fallire il codice scritto a mano.
  • Formati di data dentro SQL. Tenete il valore numerico o in UTC nel database e formattate nell’applicazione, dove controllate locale e fuso.
  • Usare il timestamp completo come riferimento umano. Chi lo legge ad alta voce perde cifre. Riducete o hashate se serve un riferimento corto.

Provalo

Incollate un valore d’epoca o una stringa data in un convertitore di timestamp per passare tra secondi, millisecondi, ISO 8601 e la vostra ora locale. La conversione avviene nel browser, così nessun timestamp — sensibile o no — deve lasciare il vostro dispositivo per essere leggibile.