Unix vremenske oznake: sekunde vs milisekunde i greške koje nastaju
Ako ste radili na web aplikacijama bilo koje duljine vremena, sigurno ste se susreli s greški u vremenskoj oznaci koja na prvi pogled nije imala smisla. Datum koji se pojavljuje kao 1970. Vrijeme prikazano 52 godine u budućnosti. API koji odbija vremensku oznaku koja izgleda savršeno razumno.
Vrlo je vjerojatno da je krivac bila neusaglašenost između sekundi i milisekundi — jedna od najčešćih grešaka pri rukovanju datumima u softveru, i jedna od onih koju je najlakše propustiti.
Glavni Problem
Unix vremenske oznake trebale bi brojiti sekunde od 1. siječnja 1970. godine (Unix epoha). To je originalni standard, i to je ono što koristi praktički svaki server-side jezik i sustav:
- Python-ov
time.time()vraća sekunde - PHP-ova
time()vraća sekunde - Većina SQL baza podataka sprema i vraća sekunde
- Unix naredba ljuske
date +%svraća sekunde - Većina REST API dokumentacije, kada kaže "Unix vremenska oznaka", misli na sekunde
JavaScript radi nešto drugačije. Date.now() i new Date().getTime() vraćaju milisekunde — 1000 puta veću vrijednost od ekvivalentne Unix vremenske oznake.
To znači da vrijednost vremenske oznake kao što je 1712534400 predstavlja 8. travnja 2024. u sekundama. Ali 1712534400000 predstavlja isti trenutak u milisekundama — i ako slučajno koristiš milisekundnu vrijednost gdje su očekivane sekunde, ili obrnuto, dobit ćeš datume koji su potpuno pogrešni.
Kako Greške Zapravo Izgledaju
Scenarij 1: JavaScript milisekunde poslane API-ju koji očekuje sekunde
Frontend šalje Date.now() — recimo, 1712534400000 — direktno na backend koji ga sprema kao Unix vremensku oznaku u sekundama. Backend sprema 1712534400000 kao vremensku oznaku. Konvertiraj to nazad u datum i dobit ćeš nešto oko godine 56000.
Ovo je greška "datum se pojavljuje u dalekoj budućnosti".
Scenarij 2: Vrijednost u sekundama korištena u JavaScript-u
Backend vraća Unix vremensku oznaku u sekundama — recimo, 1712534400. JavaScript razvojni programer je prosleđuje direktno new Date(1712534400). JavaScript ga tumači kao 1.712.534.400 milisekundi od epohe — oko 19,8 dana nakon epohe. Sučelje prikazuje datum u siječnju 1970.
Ovo je greška "datum se pojavljuje u 1970.".
Scenarij 3: JWT istek postavljen u pogrešnoj jedinici
JSON Web Token je izdan s exp zahtjevom koji trebao istjeći za 24 sata. Razvojni programer izračuna Date.now() + 86400 — s namjerom dodati 86.400 sekundi (24 sata). Ali Date.now() je u milisekundama, a 86.400 je u sekundama. Rezultat je vremenska oznaka oko 86.400 milisekundi (86,4 sekundi) u budućnosti. Svaki token ističe za manje od 2 minute umjesto za 24 sata.
Scenarij 4: Vremenska oznaka baze podataka pročitana pogrešno
PostgreSQL stupac sprema Unix vremensku oznaku kao integer (sekunde). Vrijednost se preuzima i koristi u JavaScript-u kako je, što daje datum iz 1970. Rješenje: pomnoži s 1000 prije proslijeđivanja new Date().
Možeš koristiti Unix vremenski pretvarač za brzu provjeru je li broj koji gledaš vremenska oznaka u sekundama ili milisekundama i koji datum joj odgovara — korisno za otklanjanje grešaka.
Kako Razlikovati Sekunde od Milisekundi
Najbrži način: broji znamenke.
- 10 znamenki (npr.
1712534400) → vremenska oznaka u sekundama. Predstavlja datum u razumnom sadašnjosti ili nedavnoj prošlosti/budućnosti. - 13 znamenki (npr.
1712534400000) → vremenska oznaka u milisekundama.
Vremenska oznaka Unix-a u sekundama za datume od 2000. do 2050. ide od oko 946.684.800 do 2.524.608.000 — uvijek 10 znamenki. Ako vidiš 13-znamenkasti broj u vremenskom kontekstu, gotovo je sigurno da su to milisekunde.
Ovo pravilo radi za trenutne datume. Datumi u dalekoj budućnosti (nakon 2286. godine) bi imali 11-znamenkaste vremenske oznake u sekundama, ali to je rubni slučaj koji možeš zanemariti u praksi.
Rješenje Za Svaki Jezik
JavaScript (konvertiraj u sekunde pri slanju na backend): `javascript const timestampSeconds = Math.floor(Date.now() / 1000); `
JavaScript (konvertiraj sekunde s backend-a za korištenje u Date): `javascript const date = new Date(timestampSeconds * 1000); `
Python (već je u sekundama): `python import time timestamp_seconds = int(time.time()) `
PHP (već je u sekundama): `php $timestamp_seconds = time(); `
SQL (PostgreSQL, izdvoji sekunde): `sql SELECT EXTRACT(EPOCH FROM NOW())::int; `
Konvertiraj vremensku oznaku u milisekundama u sekunde (bilo koji jezik): ` podijeli s 1000, zatim zaokruži dolje/skrati `
JWT Istek: Pravi Način
JWT zahtjevi (exp, iat, nbf) moraju biti u sekundama prema RFC 7519 specifikaciji. U JavaScript-u:
const now = Math.floor(Date.now() / 1000); // sekunde
const exp = now + 86400; // 24 sata od sada, u sekundama
Ne: `javascript const exp = Date.now() + 86400; // pogrešno: miješa milisekundnu bazu s sekundnim pomakom `
I ne: `javascript const exp = Date.now() + (86400 * 1000); // pogrešno: exp bi bio ~28 dana u budućnosti u milisekundama `
JWT s exp vrijednosti od 13 znamenki će biti odbijen od strane većine JWT biblioteka kao nevaljani ili iz daleke budućnosti. Unix vremenski alat može te pomoći provjeri što se određena exp vrijednost dekodira u.
Spremi Vremenske Oznake u Bazama Podataka
Pri oblikovanju shema, budi dosljedno glede jedinice:
- Ako spremaš sekunde, dokumentiraj to. Imena stupaca kao što su
created_at_unixili komentar koji pojašnjava "Unix vremenska oznaka u sekundama" sprječavaju dvosmislenost. - Ako tvoj ORM ili okvir sprema milisekunde (neki JavaScript ORM-ovi to rade), budi eksplicitan i oko toga.
- Izbjegavaj miješanje — ne spremi neke vremenske oznake u sekundama i druge u milisekundama u istom sustavu.
PostgreSQL-ov nativni TIMESTAMPTZ tip je često bolji izbor od spremmanja sirovih brojeva, jer nativno rukovati konverzijom vremenskog pojasa i oblikovanjem. Ali kada korististiš brojeve za vremenske oznake, odluči se na jednu jedinicu i drži se je.
Napomena o Mikrosekundama
Neki sustavi idu još dalje i koriste mikrosekunde (milijuntini dio sekunde). Python-ov time.time_ns() vraća nanoskunde. Sustavi za trgovinu visokom frekvencijom, alati za profiliranje i neka interna baza podataka koriste mikrosekundnu preciznost.
Ako vidiš 16-znamenkasti broj u vremenskom kontekstu, mogao bi biti u mikrosekundama. 19-znamenkasti broj mogao bi biti u nanosekundama. Ista heuristika za detekciju se primjenjuje — broj znamenki ti govori približnu ljestvicu.
Za vremenske oznake web aplikacija, milisekundna preciznost je sve što će ti trebati. Mikrosekundna preciznost je važna samo u sustavima orijentiranima na performanse i visokom frekvencijom.
Praktično Pravilo
Kadgod vremenska oznaka prelazi granicu jezika ili sustava — JavaScript frontend na Python/PHP/Go/Java backend, aplikacija na bazu podataka, aplikacija na vanjski API — pitaj se: koja strana koristi sekunde a koja milisekunde? Dodaj konverziju na granici, dokumentiraj je, i testiraj s poznatim datumom da provjeriš rezultat ima smisla.
Test je jednostavan: konvertiraj vremensku oznaku koju generiraš i provjeri prikazuje li razuman datum. Ako prikazuje 1970 ili 55000, odmah znašda nešto nije u redu.


