Jaký formát pro časová razítka v JSON
Shrnutí: Epochy i řetězce ISO mají kompromisy, ale to, co věci skutečně rozbíjí, je jejich míchání. Použijte ISO 8601 s offsetem, ukládejte UTC, zobrazujte v časovém pásmu uživatele.

Stručně: na drátě používejte ISO 8601 s explicitním offsetem, ukládejte UTC s koncovým Z a převádějte jen při zobrazení; pokud zvolíte epochy, zafixujte globálně sekundy versus milisekundy a jednotku dejte do názvu pole.
Proč 2026-10-30 14:30:00 nestačí
Ten řetězec nenese žádné pásmo. 14:30 v Šanghaji a 14:30 v Londýně jsou osm hodin od sebe a nelze poznat, které je myšleno. new Date('2026-10-30 14:30:00') parsuje v místním pásmu běhového prostředí, takže server i prohlížeč odvodí z jednoho payloadu dva různé okamžiky – typ chyby, která se nikdy nereprodukuje.
Samotné 2026-10-30 není okamžik. Vhodné pro narozeniny a fakturační období, špatné pro čas vytvoření.
Dva použitelné formáty
Řetězce ISO 8601
{
"createdAt": "2026-10-30T14:30:00+08:00",
"updatedAt": "2026-10-30T06:30:00Z"
}
Čitelné, seřaditelné při konzistentním formátu, s přesností na milisekundy, pokud je potřeba, a sebe popisné.
Epochy
{ "createdAt": 1793519400 }
Kompaktní a jednoznačné, ale nečitelné, a sekundy versus milisekundy jsou trvalé nebezpečí. Pokud zvolíte epochy, zstandardizujte jednotku a dejte ji do názvu pole: createdAtMs je mnohem bezpečnější než createdAt.
Konvence, které stojí za to zafixovat brzy
| Položka | Konvence |
|---|---|
| Formát na drátě | ISO 8601 s Z nebo +08:00 |
| Zóna úložiště | UTC, aby DST nikdy nevstoupil do hry |
| Přesnost | Milisekundy stačí |
| Pojmenování polí | createdAt, updatedAt, expiresAt |
| Čistá data | Samostatné pole date, například birthday: "1990-01-01" |
| Trvání | Celé číslo plus jednotka, například timeoutMs: 3000 |
Vykreslování
new Intl.DateTimeFormat('en-GB', {
dateStyle: 'medium',
timeStyle: 'short',
timeZone: 'Europe/London',
}).format(new Date('2026-10-30T06:30:00Z'));
Uveďte timeZone explicitně, když zobrazení nemá následovat zařízení. Spoléhat na výchozí nastavení prohlížeče je správné pro časy určené uživateli a špatné pro reporty.
Tři opakující se chyby
Samotná data se parsují jako půlnoc UTC. Podle specifikace ECMAScript jsou řetězce jen s datem UTC, zatímco řetězce s datem a časem jsou místní. Tato nekonzistence je spolehlivým zdrojem chyb o jeden den.
Zóna databáze se neshoduje se serializátorem. MySQL datetime nemá zónu; zapište místní čas, čtěte jako UTC a všechno se posune o offset.
Letní čas. Ukládání budoucích místních časů vytváří okamžiky, které neexistují nebo nastanou dvakrát. UTC takové mezery nemá.
Časté dotazy
Jak volit mezi ISO 8601 a epochami?
ISO 8601 použijte, když payload čtou lidé, když chcete lexikální pořadí řazení, nebo když hodnota musí nést vlastní zónu; cenou je zhruba tucet bajtů navíc a knihovna pro parsování. Epochy použijte, když záleží více na kompaktnosti a triviálním zpracování napříč jazyky, ale zafixujte globálně sekundy versus milisekundy a uveďte, jakou jednotku pole nese.
Mají samotné datum a časové razítko sdílet stejné pole?
Ne. Samotné 2026-10-30 je kalendářní den bez času i pásma, zatímco od pole s časovým razítkem se očekává přesný okamžik. Narozeniny a fakturační období držte v samostatném poli date a pro časy vytvoření nebo aktualizace použijte pole ISO 8601 s At.