JSON Toolkit

Che formato per i timestamp in JSON

In sintesi: I numeri epoch e le stringhe ISO hanno ciascuno i propri compromessi, ma è mescolarli ciò che davvero rompe le cose. Usa ISO 8601 con un offset, memorizza in UTC, renderizza nel fuso orario dell'utente.

Principiante~3 min di letturaPubblicato il 2026-10-30Aggiornato il 2026-10-30
Scegliere un formato timestamp per le API JSON

In sintesi: usa ISO 8601 con un offset esplicito sul filo, memorizza UTC con una Z finale, e converti solo al momento della visualizzazione; se scegli invece numeri epoch, fissa globalmente secondi versus millisecondi e metti l'unità nel nome del campo.

Perché 2026-10-30 14:30:00 non basta

Quella stringa non porta alcun fuso. Le 14:30 a Shanghai e le 14:30 a Londra sono a otto ore di distanza, e non c'è modo di sapere quale si intenda. new Date('2026-10-30 14:30:00') analizza nel fuso locale del runtime, quindi il server e il browser ricavano due istanti diversi dallo stesso payload — il tipo di bug che non si riproduce mai.

Una 2026-10-30 nuda non è affatto un istante. Va bene per compleanni e periodi di fatturazione, sbagliata per un orario di creazione.

Due formati praticabili

Stringhe ISO 8601

{
  "createdAt": "2026-10-30T14:30:00+08:00",
  "updatedAt": "2026-10-30T06:30:00Z"
}

Leggibili, ordinabili quando il formato è coerente, con precisione al millisecondo se necessario, e autodescrittive.

Numeri epoch

{ "createdAt": 1793519400 }

Compatti e non ambigui, ma illeggibili, e secondi versus millisecondi è un pericolo permanente. Se scegli gli epoch, standardizza l'unità e mettila nel nome del campo: createdAtMs è molto più sicuro di createdAt.

Convenzioni da fissare presto

Voce Convenzione
Formato sul filo ISO 8601 con Z o +08:00
Fuso di archiviazione UTC, così l'ora legale non entra mai in gioco
Precisione Il millisecondo basta
Denominazione dei campi createdAt, updatedAt, expiresAt
Date pure Un campo date separato, per esempio birthday: "1990-01-01"
Durate Intero più un'unità, per esempio timeoutMs: 3000

Rendering

new Intl.DateTimeFormat('en-GB', {
  dateStyle: 'medium',
  timeStyle: 'short',
  timeZone: 'Europe/London',
}).format(new Date('2026-10-30T06:30:00Z'));

Specifica timeZone esplicitamente quando la visualizzazione non deve seguire il dispositivo. Affidarsi al default del browser è corretto per gli orari mostrati all'utente e sbagliato per i report.

Tre bug ricorrenti

Le date nude si analizzano come mezzanotte UTC. Secondo la specifica ECMAScript, le stringhe solo-data sono UTC mentre le stringhe data-ora sono locali. Questa incoerenza è una fonte affidabile di bug di un giorno in più o in meno.

Il fuso del database non concorda con il serializzatore. Il datetime di MySQL non ha fuso; scrivi locale, leggi come UTC, e tutto si sposta dell'offset.

Ora legale. Memorizzare orari locali futuri crea istanti che non esistono o che si verificano due volte. UTC non ha questi buchi.

FAQ

Come devo scegliere tra ISO 8601 e numeri epoch?

Usa ISO 8601 quando le persone leggono il payload, quando vuoi un ordine lessicografico o quando il valore deve portare il proprio fuso; il costo è circa una dozzina di byte in più e una libreria di parsing. Usa i numeri epoch quando compattezza e gestione banale tra linguaggi contano di più, ma fissa globalmente secondi versus millisecondi e indica quale unità contiene il campo.

Una data nuda e un timestamp devono condividere lo stesso campo?

No. Una 2026-10-30 nuda è un giorno di calendario senza ora e senza fuso, mentre un campo timestamp ci si aspetta che porti un istante esatto. Mantieni compleanni e periodi di fatturazione in un campo date separato, e usa un campo ISO 8601 con suffisso At per gli orari di creazione o aggiornamento.

Ulteriori letture