Czym jest znacznik czasu Unix (Unix timestamp)?
Znacznik czasu Unix (Unix timestamp) to liczba sekund, jakie upłynęły od 1 stycznia 1970 roku, 00:00:00 UTC. Ten moment nazywa się epoką Unix i jest punktem zerowym, od którego komputery liczą czas w większości systemów, baz danych i języków programowania. Liczba 1700000000 nic nie mówi na pierwszy rzut oka, ale to konkretna sekunda w listopadzie 2023 roku, co za chwilę pokażemy na konkretnych przykładach.
Czym naprawdę jest znacznik czasu Unix
Zamiast zapisywać datę jako tekst w rodzaju “14 listopada 2023, 22:13:20”, komputer może zapisać ją jako jedną liczbę całkowitą: sekundy, które minęły od epoki. To pozorne uproszczenie ma konkretne powody praktyczne.
Po pierwsze, liczba jest kompaktowa, zajmuje mniej miejsca niż sformatowany napis i nie wymaga parsowania różnych formatów dat w zależności od kraju czy ustawień systemowych. Po drugie, jest jednoznaczna, nie ma tu miejsca na pomyłkę między formatem dzień-miesiąc-rok a miesiąc-dzień-rok, która potrafi zamienić 3 kwietnia w 4 marca. Po trzecie, jest niezależna od strefy czasowej, bo liczy sekundy od stałego punktu w czasie uniwersalnym (UTC), a to, jak ją wyświetlisz użytkownikowi w Warszawie czy w Nowym Jorku, to już osobna decyzja przy renderowaniu.
Ta ostatnia cecha jest tym, co czyni znacznik czasu tak wygodnym w kolumnie created_at w bazie danych albo w polu exp tokenu JWT: baza czy token przechowują jedną, absolutną liczbę, a każda aplikacja, która ją odczytuje, może pokazać ją w dowolnej strefie czasowej bez utraty precyzji. Dodatkowo dwie liczby sekund porównuje się i odejmuje trywialnie, 1700000000 - 1000000000 od razu mówi, ile sekund minęło między dwoma zdarzeniami, podczas gdy odejmowanie dwóch sformatowanych dat wymaga najpierw ich sparsowania.
W praktyce oznacza to też, że sortowanie chronologiczne wpisów w logu albo rekordów w tabeli sprowadza się do zwykłego sortowania liczb rosnąco, bez żadnej logiki uwzględniającej nazwy miesięcy czy separatory w dacie. Ten sam powód sprawia, że znacznik czasu jest wygodny jako klucz do porównań w zapytaniach SQL w stylu “wszystkie rekordy nowsze niż X”: wystarczy jedno porównanie liczbowe zamiast konwersji typu daty po obu stronach zapytania.
Przykład: co oznaczają te liczby
Poniższa tabela pokazuje kilka konkretnych znaczników czasu i odpowiadające im daty UTC.
| Znacznik czasu Unix (sekundy) | Data i godzina UTC |
|---|---|
| 0 | 1 stycznia 1970, 00:00:00 UTC (sama epoka) |
| 1000000000 | 9 września 2001, 01:46:40 UTC |
| 1700000000 | 14 listopada 2023, 22:13:20 UTC |
| 2000000000 | 18 maja 2033, 03:33:20 UTC |
| 2147483647 | 19 stycznia 2038, 03:14:07 UTC |
Warto prześledzić jeden z tych wierszy, żeby oswoić się z rzędem wielkości. 1700000000 sekund to w przybliżeniu 53,9 roku, więc licząc od 1 stycznia 1970 roku, lądujemy niemal dokładnie w drugiej połowie 2023 roku, konkretnie 14 listopada. Jeśli w logu serwera albo w odpowiedzi z jakiegoś API zobaczysz dziesięciocyfrową liczbę zaczynającą się od “17”, to niemal na pewno jest to znacznik czasu z 2023 roku, co jest przydatnym skrótem myślowym przy szybkim skanowaniu logów.
Sekundy czy milisekundy? Jak je odróżnić
To najczęstsza pułapka, na jaką trafiają programiści pracujący ze znacznikami czasu. Znaczniki w sekundach mają dziś dziesięć cyfr, na przykład 1700000000. Znaczniki w milisekundach mają trzynaście cyfr dla tego samego momentu, czyli 1700000000000, wciąż 14 listopada 2023 roku, tylko z trzema dodatkowymi zerami precyzji.
JavaScript i wiele przeglądarkowych API zwracają czas w milisekundach, Date.now() w JavaScripcie da ci właśnie trzynastocyfrową liczbę. Z kolei wywołania systemowe Uniksa, cron, polecenia w powłoce i większość narzędzi Unix/Linux operują na sekundach. Jeśli wkleisz wartość w milisekundach do pola, które oczekuje sekund, dostaniesz datę tysiąc razy dalej w przyszłości, niż zamierzałeś. 1700000000000 potraktowane jako sekundy zamiast milisekund wyląduje gdzieś w XXXVI wieku, co jest łatwym do zauważenia, ale mylącym błędem, jeśli akurat debugujesz coś innego i nie spodziewasz się absurdalnej daty na ekranie.
Zamień znacznik czasu na datę
Masz w logu, w odpowiedzi API albo w kolumnie created_at surową liczbę i chcesz wiedzieć, jakiej dacie odpowiada? Wklej ją poniżej.
Zamień datę na znacznik czasu
Odwrotna sytuacja zdarza się równie często: planujesz zadanie cron na konkretną godzinę, ustawiasz datę wygaśnięcia tokenu albo wysyłasz parametr do API, które oczekuje liczby sekund od epoki zamiast czytelnej daty. Wybierz datę i godzinę, a widżet od razu policzy odpowiadający jej znacznik czasu.
Częste błędy i przypadki brzegowe
Mylenie sekund z milisekundami. To błąd opisany w sekcji wyżej, ale warto go powtórzyć, bo jest najczęstszą przyczyną dat w stylu “rok 50000-coś” w interfejsie, gdy ktoś wklei trzynastocyfrową liczbę tam, gdzie narzędzie oczekuje dziesięciu cyfr.
Problem roku 2038. Systemy, które przechowują znacznik czasu jako 32-bitową liczbę całkowitą ze znakiem, mają twardy limit 2147483647, czyli dokładnie 19 stycznia 2038 roku, 03:14:07 UTC. Po tej sekundzie licznik przepełnia się i zawija do liczby ujemnej, co potrafi zepsuć logikę porównywania dat w starszym kodzie, na przykład sprawić, że data w przyszłości nagle wygląda jak data sprzed epoki. Nowoczesne systemy 64-bitowe nie mają tego ograniczenia, bo zakres liczb, jakie potrafią zapisać, sięga miliardów lat w obie strony.
Mylenie znacznika czasu ze strefą czasową. Sam znacznik czasu Unix nie ma żadnej strefy czasowej, to absolutny moment w czasie, liczba sekund od stałego punktu odniesienia. Zamieszanie bierze się z tego, jak go wyświetlasz. Dwie osoby w różnych strefach czasowych patrzące na ten sam znacznik 1700000000 zobaczą różne godziny na zegarze (jedna może zobaczyć 23:13 czasu lokalnego, druga 17:13), ale obie patrzą dokładnie na tę samą sekundę w historii świata.
Wartości ujemne. Znaczniki czasu mogą być ujemne i wtedy reprezentują daty sprzed 1 stycznia 1970 roku. Na przykład -86400 to 31 grudnia 1969 roku, dokładnie jedna doba przed epoką (86400 to liczba sekund w jednej dobie). Nie każde narzędzie ani nie każdy system obsługuje wartości ujemne, więc jeśli pracujesz z datami historycznymi sprzed 1970 roku, warto to sprawdzić zawczasu, zanim cały pipeline danych wywali błąd na pierwszym rekordzie z XIX wieku.
Najczęściej zadawane pytania
Czym jest znacznik czasu Unix?
To liczba sekund, jakie upłynęły od 1 stycznia 1970 roku, 00:00:00 UTC, zwanego epoką Unix. Jest to sposób zapisu dowolnej daty i godziny jako pojedynczej liczby całkowitej, niezależnej od strefy czasowej i formatu regionalnego, dzięki czemu komputerom łatwo się go porównuje, sortuje i przechowuje.
Jak sprawdzić, czy mój znacznik czasu jest w sekundach czy w milisekundach?
Policz cyfry. Dla dat z ostatnich kilkudziesięciu lat znacznik w sekundach ma dziesięć cyfr, na przykład 1700000000, a ten sam moment w milisekundach ma trzynaście cyfr, 1700000000000. Jeśli liczba, którą masz przed oczami, ma trzynaście cyfr, podziel ją przez 1000, zanim wkleisz do narzędzia oczekującego sekund.
Co to jest problem roku 2038?
To ograniczenie systemów, które zapisują znacznik czasu Unix jako 32-bitową liczbę całkowitą ze znakiem. Taki licznik przepełnia się dokładnie 19 stycznia 2038 roku o 03:14:07 UTC (czyli przy wartości 2147483647) i zawija się do liczby ujemnej, co może zepsuć logikę dat w starszym oprogramowaniu. Nowoczesne systemy 64-bitowe nie mają tego problemu.
Czy mogę przeliczyć datę sprzed 1970 roku?
Tak, taka data ma po prostu ujemny znacznik czasu. Na przykład -86400 odpowiada 31 grudnia 1969 roku. Sam format na to pozwala, choć część systemów i bibliotek ogranicza obsługę wyłącznie do wartości dodatnich, więc przy pracy z datami historycznymi warto to zweryfikować w konkretnym narzędziu, którego używasz.
Dlaczego bazy danych przechowują daty jako znaczniki czasu Unix zamiast tekstu?
Bo liczba całkowita jest kompaktowa, jednoznaczna i niezależna od strefy czasowej, w przeciwieństwie do sformatowanego napisu w rodzaju “14/11/2023”. Kolumna created_at zapisana jako znacznik czasu pozwala trywialnie sortować rekordy chronologicznie, odejmować dwa momenty od siebie i wyświetlać wynik w dowolnej strefie czasowej po stronie aplikacji, bez ryzyka pomyłki przy parsowaniu formatu daty.