Czas wydaje się prosty, dopóki nie spróbujesz napisać oprogramowania, które prawidłowo go obsługuje. Wydarzenie zaplanowane na „15:00" oznacza różne rzeczy w Tokio, Londynie i Nowym Jorku. Czas letni przesuwa zegary do przodu lub do tyłu — ale nie wszędzie i nie w tych samych terminach. Znacznik czasu, który wygląda poprawnie w Twoim lokalnym środowisku, psuje się na produkcji, bo serwer jest w innej strefie.
Strefy czasowe to jeden z najbardziej niezawodnie mylących tematów w inżynierii oprogramowania. Ten artykuł wyjaśnia, jak działają, skąd bierze się złożoność i jak unikać najczęstszych błędów.
Dlaczego strefy czasowe istnieją
Ziemia obraca się o 360 stopni w 24 godziny, co oznacza, że słońce jest w zenicie w różnych momentach w zależności od długości geograficznej. Przed XIX wiekiem każde miasto ustawiało zegary według lokalnego czasu słonecznego — południe było wtedy, gdy słońce było najwyżej. Działało to dobrze, dopóki koleje nie połączyły odległych miast i rozkład jazdy pociągów nie potrzebował jednego spójnego zegara.
W 1884 roku delegaci z 25 krajów spotkali się na Międzynarodowej Konferencji Południkowej w Waszyngtonie i uzgodnili podział świata na 24 standardowe strefy czasowe, każda przesunięta względem południka zerowego (0 stopni długości geograficznej) przechodzącego przez Greenwich w Anglii.
W praktyce granice stref czasowych podążają za granicami politycznymi, a nie schludnymi liniami południkowymi. Chiny obejmują pięć geograficznych stref, ale używają jednego oficjalnego czasu (UTC+8). Indie używają UTC+5:30 — przesunięcia o pół godziny. Nepal używa UTC+5:45. Rzeczywista mapa stref czasowych jest chaotyczna.
UTC vs. GMT
GMT (Greenwich Mean Time) to średni czas słoneczny w Królewskim Obserwatorium w Greenwich. Był światowym wzorcem czasu przez ponad wiek.
UTC (Coordinated Universal Time) zastąpił GMT jako międzynarodowy standard w 1972 roku. UTC opiera się na zegarach atomowych, a nie obserwacjach astronomicznych, co czyni go znacznie precyzyjniejszym. W praktyce UTC i GMT pokazują ten sam czas, ale UTC jest poprawnym odniesieniem technicznym.
Dlaczego „UTC", a nie „CUT"? Skrót jest kompromisem między angielskim „Coordinated Universal Time" (CUT) a francuskim „Temps Universel Coordonné" (TUC). Żadna ze stron nie dostała preferowanego akronimu, więc wybrano UTC jako neutralny językowo alternatywę.
Czas letni: zorganizowany chaos
Około 70 krajów przestrzega czasu letniego (DST), przesuwając zegary o godzinę do przodu wiosną i do tyłu jesienią. Celem jest dostosowanie godzin czuwania do światła dziennego. Rezultatem jest półroczne źródło błędów.
Kluczowe komplikacje:
- Nie jest uniwersalny. Większość Afryki, Azji i Ameryki Południowej nie przestrzega czasu letniego. W USA Arizona i Hawaje rezygnują.
- Różne daty. UE przesuwa zegary w ostatnią niedzielę marca i października. USA przesuwa w drugą niedzielę marca i pierwszą niedzielę listopada. Przez kilka tygodni każdego roku nie są zsynchronizowane.
- Niejednoznaczne czasy. Gdy zegary cofają się, godzina od 1:00 do 2:00 występuje dwukrotnie. Znacznik czasu „1:30" tego dnia jest niejednoznaczny.
- Pominięte czasy. Gdy zegary przesuwają się do przodu, godzina od 2:00 do 3:00 nie istnieje. Spotkanie zaplanowane na 2:30 tego dnia nigdy nie nastąpi.
- Zmiany polityczne. Rządy mogą (i zmieniają) zasady czasu letniego z niewielkim wyprzedzeniem. Rosja przyjęła stały czas letni w 2011, potem przeszła na stały czas standardowy w 2014. Maroko zmieniało zasady czasu letniego wielokrotnie.
ISO 8601: uniwersalny format daty
Aby uniknąć niejednoznaczności, międzynarodowy standard ISO 8601 definiuje jasny format daty i czasu:
2026-03-29T14:30:00Z
2026-03-29T14:30:00+02:00
2026-03-29T14:30:00-05:00
Toddziela datę od czasu.Zoznacza UTC (strefa „Zulu" w terminologii wojskowej).+02:00lub-05:00to przesunięcie względem UTC.
Ten format jest jednoznaczny, sortowalny jako zwykły tekst i powszechnie rozumiany przez biblioteki parsujące daty. W razie wątpliwości używaj ISO 8601.
Znaczniki czasu Unix
Znacznik czasu Unix (zwany też czasem epoki lub czasem POSIX) to liczba sekund, które upłynęły od 1 stycznia 1970, 00:00:00 UTC — momentu znanego jako epoka Unix.
| Czytelna forma | Znacznik czasu Unix |
|---|---|
| 1970-01-01 00:00:00 UTC | 0 |
| 2000-01-01 00:00:00 UTC | 946684800 |
| 2026-03-29 12:00:00 UTC | 1774987200 |
Znaczniki czasu Unix nie mają strefy czasowej — są zawsze w UTC. To czyni je idealnymi do przechowywania i porównywania czasów w oprogramowaniu. Konwertujesz do lokalnej strefy czasowej tylko na warstwie prezentacji.
Problem roku 2038: Systemy przechowujące znaczniki czasu Unix jako 32-bitową liczbę całkowitą ze znakiem przepełnią się 19 stycznia 2038 o 03:14:07 UTC. Maksymalna wartość (2 147 483 647) przekroczy zakres do liczby ujemnej, interpretowanej jako grudzień 1901. Większość nowoczesnych systemów używa 64-bitowych liczb całkowitych, które nie przepełnią się przez kolejne 292 miliardy lat.
Baza danych stref czasowych IANA
Oprogramowanie potrzebuje nie tylko przesunięć UTC — musi znać pełną historię i przyszłe zasady dla każdego regionu, włącznie z przejściami czasu letniego, zmianami politycznymi i anomaliami historycznymi. Te informacje znajdują się w bazie danych stref czasowych IANA (zwanej też bazą Olsona lub tzdata).
Używa identyfikatorów takich jak America/New_York, Europe/Paris, Asia/Tokyo. Każdy wpis koduje pełną historię przesunięć UTC i zasad czasu letniego dla danej lokalizacji.
Dlatego nigdy nie należy przechowywać strefy czasowej jako stałego przesunięcia jak „+02:00". Przesunięcie mówi o aktualnej różnicy od UTC, ale nic nie mówi o zasadach czasu letniego. Europe/Paris to UTC+1 zimą i UTC+2 latem. Identyfikator IANA obejmuje oba przypadki.
Typowe błędy w oprogramowaniu
- Przechowywanie czasu lokalnego bez strefy czasowej. Wartość jak
2026-03-29 14:30:00jest bez znaczenia bez wiedzy, do której strefy czasowej się odnosi. Zawsze przechowuj UTC lub dołączaj przesunięcie. - Zakładanie, że przesunięcie UTC równa się strefie czasowej. UTC+2 w marcu może być UTC+3 w lipcu (jeśli region przestrzega czasu letniego). Przechowuj identyfikator IANA, nie przesunięcie.
- Ignorowanie przejść czasu letniego w planowaniu. Zadanie codzienne o 2:30 będzie pominięte raz w roku i uruchomione dwukrotnie raz w roku, jeśli nie obsługujesz czasu letniego.
- Zakładanie, że dni mają 24 godziny. W dniach zmiany czasu dzień ma 23 lub 25 godzin. Obliczanie „jutro o tej samej porze" przez dodanie 86 400 sekund będzie przesunięte o godzinę.
- Naiwne używanie JavaScript
Date.new Date("2026-03-29")jest parsowany jako UTC w niektórych silnikach i jako czas lokalny w innych. Zawsze bądź jednoznaczny co do strefy czasowej.
Najlepsze praktyki dla programistów
- Przechowuj czasy w UTC. Konwertuj do lokalnej strefy czasowej użytkownika tylko na warstwie prezentacji.
- Używaj identyfikatorów stref czasowych IANA (
America/New_York), nie stałych przesunięć (-05:00). - Używaj ISO 8601 do serializacji. Jest jednoznaczny i uniwersalnie parsowalny.
- Używaj dojrzałej biblioteki dat. W JavaScript użyj
Intl.DateTimeFormatlub biblioteki jakdate-fns-tz. W Pythonie użyjzoneinfo(3.9+) lubpytz. W Javie użyjjava.time.ZonedDateTime. - Aktualizuj
tzdata. Rządy zmieniają zasady czasu letniego. Twój system operacyjny i środowisko uruchomieniowe potrzebują aktualnych danych o strefach czasowych. - Testuj z wieloma strefami czasowymi. Nie zakładaj, że Twój serwer i użytkownicy współdzielą tę samą strefę.
Więcej informacji
Czas jest pozornie złożony, ale zasady są dobrze udokumentowane, a narzędzia dojrzałe. Kluczem jest szanowanie tej złożoności zamiast zakładania, że jej nie ma.
- Wyrażenia cron wyjaśnione — planowanie zadań w różnych strefach czasowych
- Generator haszy i Tester regex — więcej narzędzi developerskich na ToolK
