Welches Format für Zeitstempel in JSON
Fazit: Epoch-Zahlen und ISO-Strings haben je ihre Abwägungen, aber sie zu mischen ist das, was tatsächlich bricht. Verwenden Sie ISO 8601 mit Offset, speichern Sie UTC und rendern Sie in der Zeitzone des Nutzers.

Kurz gesagt: Verwenden Sie auf der Leitung ISO 8601 mit ausdrücklichem Offset, speichern Sie UTC mit abschließendem Z und konvertieren Sie erst bei der Anzeige; entscheiden Sie sich stattdessen für Epoch-Zahlen, legen Sie Sekunden versus Millisekunden global fest und schreiben Sie die Einheit in den Feldnamen.
Warum 2026-10-30 14:30:00 nicht genügt
Dieser String trägt keine Zone. 14:30 in Shanghai und 14:30 in London liegen acht Stunden auseinander, und es gibt keine Möglichkeit zu sagen, welches gemeint ist. new Date('2026-10-30 14:30:00') parst in der lokalen Zone der Laufzeitumgebung, Server und Browser leiten also zwei verschiedene Zeitpunkte aus einer Payload ab – die Art Bug, die nie reproduzierbar ist.
Ein nacktes 2026-10-30 ist überhaupt kein Zeitpunkt. Gut für Geburtstage und Abrechnungszeiträume, falsch für eine Erstellungszeit.
Zwei praktikable Formate
ISO-8601-Strings
{
"createdAt": "2026-10-30T14:30:00+08:00",
"updatedAt": "2026-10-30T06:30:00Z"
}
Lesbar, sortierbar bei konsistentem Format, Millisekundenpräzision bei Bedarf und selbstbeschreibend.
Epoch-Zahlen
{ "createdAt": 1793519400 }
Kompakt und eindeutig, aber unlesbar, und Sekunden versus Millisekunden ist eine dauerhafte Gefahr. Wählen Sie Epochs, standardisieren Sie die Einheit und schreiben Sie sie in den Feldnamen: createdAtMs ist weit sicherer als createdAt.
Konventionen, die sich früh lohnen
| Element | Konvention |
|---|---|
| Leitungsformat | ISO 8601 mit Z oder +08:00 |
| Speicherzone | UTC, damit Sommerzeit nie ins Bild kommt |
| Präzision | Millisekunden genügen |
| Feldbenennung | createdAt, updatedAt, expiresAt |
| Reine Daten | Ein separates date-Feld, etwa birthday: "1990-01-01" |
| Dauern | Ganzzahl plus Einheit, etwa timeoutMs: 3000 |
Rendern
new Intl.DateTimeFormat('en-GB', {
dateStyle: 'medium',
timeStyle: 'short',
timeZone: 'Europe/London',
}).format(new Date('2026-10-30T06:30:00Z'));
Geben Sie timeZone ausdrücklich an, wenn die Anzeige nicht dem Gerät folgen soll. Sich auf den Browser-Standard zu verlassen ist für nutzerseitige Zeiten korrekt und für Berichte falsch.
Drei wiederkehrende Bugs
Nackte Daten parsen als UTC-Mitternacht. Nach der ECMAScript-Spezifikation sind reine Datumsstrings UTC, während Datum-Zeit-Strings lokal sind. Diese Inkonsistenz ist eine verlässliche Quelle von Off-by-one-Day-Bugs.
Die Datenbankzone widerspricht dem Serializer. MySQL datetime hat keine Zone; lokal schreiben, als UTC lesen, und alles verschiebt sich um den Offset.
Sommerzeit. Zukünftige lokale Zeiten zu speichern erzeugt Zeitpunkte, die nicht existieren oder zweimal auftreten. UTC hat solche Lücken nicht.
FAQ
Wie soll ich zwischen ISO 8601 und Epoch-Zahlen wählen?
Verwenden Sie ISO 8601, wenn Menschen die Payload lesen, wenn Sie lexikographische Sortierreihenfolge wollen oder wenn der Wert seine eigene Zone tragen muss; der Preis sind grob ein Dutzend zusätzliche Bytes und eine Parsing-Bibliothek. Verwenden Sie Epoch-Zahlen, wenn Kompaktheit und triviale sprachübergreifende Handhabung mehr zählen, legen Sie aber Sekunden versus Millisekunden global fest und sagen Sie, welche Einheit das Feld hält.
Sollten ein nacktes Datum und ein Zeitstempel dasselbe Feld teilen?
Nein. Ein nacktes 2026-10-30 ist ein Kalendertag ohne Zeit und ohne Zone, während ein Zeitstempelfeld einen exakten Zeitpunkt tragen soll. Halten Sie Geburtstage und Abrechnungszeiträume in einem separaten date-Feld und verwenden Sie ein ISO-8601-At-Feld für Erstellungs- oder Änderungszeiten.