Jak poprawanie zarządzać czasem w aplikacjach?


Zarządzanie datami w aplikacjach często może być źródłem kłopotów. Problemy pojawiają się w sytuacjach, gdy nasza aplikacja może być dostępna dla osób w różnych miejscach na świecie, a daty są zapisywane w niepoprawnym formacie. W tym artykule dowiemy się, dlaczego daty w systemie należy przechowywać w standardzie UTC i czym są strefy czasowe.
Na czym polega problem?
Wyobraźmy sobie, że w naszej aplikacji użytkownik może dodawać komentarze. Po dodaniu komentarza data jego utworzenia jest zapisywana do bazy danych zgodnie z datą systemową serwera, na którym stoi nasza aplikacja. Załóżmy, że taki serwer jest w Polsce, więc zapisuje do bazy danych jako datę dodania komentarza bieżącą datę w Polsce, czyli np. 01-01-2024 12:00
.
Jeżeli komentarz dodał użytkownik z Polski, to w aplikacji wyświetli mu się data dodania 01-01-2024 12:00
. Do tego momentu jest OK. Ale co się stanie, gdy komentarz dodał użytkownik z Portugalii?
Z racji tego, że aplikacja jako moment dodania komentarza bierze czas serwerowy, to do bazy danych zostanie wstawiona również data 01-01-2024 12:00
. Użytkownik z Portugalii zobaczy w przeglądarce również taką samą datę. Niestety, taka informacja może wywołać u niego zmieszanie, ponieważ w momencie dodawania komentarza w Polsce jest co prawda godzina 12:00, to jednak ze względu na inną strefę czasową w Portugalii będzie godzina 11:00.
I to właśnie godzinę 11:00, zamiast 12:00 powinien zobaczyć pod swoim komentarzem mieszkaniec Lizbony.
Nim jednak przejdziemy do rozwiązania tego problemu, najpierw musimy zrozumieć, czym są strefy czasowe i skąd wynikają różnice w czasie między krajami.
Podział na strefy czasowe
W XIX wieku, gdy ludzie zaczęli więcej przemieszczać się po świecie, zaczęto poszukiwać rozwiązania, które ułatwiłoby podróżowanie między krajami i mogłoby pomóc w ujednoliceniu czasu na całym globie. Wprowadzony został pomysł podziału świata na 24 strefy czasowe, w którym każda kolejna strefa ma inny czas, w zależności od swojego położenia względem strefy na południku zerowym. Południk zerowy przebiega przez obserwatorium Greenwich w Londynie, a czas, który panuje w tej strefie, jest czasem uniwersalnym (Greenwich Mean Time, w skrócie GMT). Ta strefa jest oznaczana jako GMT+0
i oznacza to, że od niej jest liczony czas w pozostałym strefach czasowych: im dalej na wschód, tym więcej godzin odejmujemy, a im dalej na zachód to więcej godzin dodajemy do czasu uniwersalnego. W zależności ile wynosi różnica godzin względem czasu uniwersalnego, to strefy czasowe oznacza się na przykład jako GMT+3
czy GMT-9
.
Dla przykładu: jeżeli w Greenwich jest godzina 12:00, to czasem uniwersalnym jest również 12:00. Warszawa znajduje się w strefie GMT+1
, co oznacza, że doliczamy jedną godzinę względem czasu uniwersalnego i na warszawskich zegarach zobaczymy godzinę 13:00. Analogicznie, jeżeli Nowy Jork jest w strefie GMT-4
, to czas lokalny tam będzie wskazywał na godzinę 8:00.

Czas letni
Podział na strefy czasowe może nieco komplikować czas letni (Daylight Saving Time, DST), który obowiązuje na całym świecie (głównie w większości krajów europejskim i Ameryce Północnej). Polega on na przesunięciu wskazówek zegara w ostatnią niedzielę marca o 01:00 czasu uniwersalnego o jedną godzinę do przodu (w Polsce jest to wg czasu lokalnego z 2:00 na 3:00) oraz o cofnięciu o godzinę w ostatnią niedzielę października. Główna motywacja dla tego rozwiązania to większa oszczędność energii poprzez lepsze zarządzanie światłem słonecznym. Jeżeli przestawiamy godzinę do przodu, to zyskujemy więcej światła po południu i wieczorem, gdy wracam z pracy i chcemy zająć się obowiązkami domowymi. Dzięki temu — przynajmniej w teorii — możemy oszczędzić energię, ponieważ nie musimy używać tyle oświetlenia elektrycznego. Obecnie, to rozwiązanie jest coraz częściej krytykowane ze względu na problemy, jakie powoduje m.in. w transporcie i logistyce oraz marginalny wpływ na oszczędność energii.
Jeżeli przechodzimy na czas letni, to wtedy różnica między czasem lokalnym w Polsce a czasem uniwersalnym wynosi 2 godziny, co możemy oznaczyć jako GMT+2
.
Różnica między GMT i UTC
W kontekście pracy z datami często obok skrótu GMT używany jest również skrót UTC (Coordinated Universal Time). Najczęściej są one traktowane jako synonimy i można je stosować wymiennie, ale warto wprowadzić tutaj rozróżnienie.
GMT jest oznaczeniem wskazującym na czas słoneczny w Greenwich, a zapis GMT+0
oznaczeniem tej strefy czasowej. Pozostałe strefy czasowe przyjmują oznaczenia zgodne z różnicą od czasu GMT — czyli np. GMT-5
dla Nowego Jorku albo GMT+2
dla czasu letniego środkowoeuropejskiego.
UTC jest następcą standardu GMT stosowanym na całym świecie, który uwzględnia jego liczenie za pomocą zegarów atomowych, które są dokładniejsze. W praktyce wskazuje on na ten sam czas co GMT, czyli czas UTC+02:00
oznacza czas w strefie czasowej GMT+2
.
GMT jest zarówno strefą czasową jak i standardem czasu, natomiast UTC jest tylko standardem czasu.
Jak poprawnie zapisywać daty?
Do zapisu dat używamy międzynarodowego standardu ISO-8601. W zależności od tego, dla jakiej strefy czasowej chcemy zapisać datę, możemy użyć dwóch formatów:
- dla czasu uniwersalnego:
YYYY-MM-DDThh:mm:ssZ
- dla innych stref czasowych:
YYYY-MM-DDThh:mm:ss+hh:mm
W obu przypadkach T
oddziela datę od godziny, a dla czasu uniwersalnego Z
wskazuje na czas Greenwich (Zulu time).
Najlepiej pokazać to na przykładzie. W momencie pisania tego artykułu mamy w Polsce 17 marca 2024, godz. 12:00
. Polska jest w strefie czasowej GMT+1
, co oznacza, że jest 1 godzinę za czasem uniwersalnym. Zgodnie ze standardem ISO możemy taką datę zapisać na dwa wymienione wyżej sposoby:
- dla czasu uniwersalnego:
2024-03-17T11:00Z
- dla naszej strefy czasowej:
2024-03-17T12:00+01:00
Zauważ, że dla czasu uniwersalnego podajemy czas o godzinę wstecz. Każdy z tych formatów jest właściwy, jednak w aplikacjach powinniśmy się skłaniać do używania formatu YYYY-MM-DDThh:mm:ssZ
. Jest on łatwiejszy w zrozumieniu, czytelniejszy i bardziej uniwersalny. Niezależnie od tego, w jakiej strefie czasowej jesteśmy i czy mamy czas letni, data zawsze wygląda tak samo i pokazuje czas w Greenwich.
W Javascripcie możemy otrzymać datę w formacie ISO używając metody toISOString
z klasy Date.
new Date().toISOString();
// 2024-03-17T11:00:00.000Z
Podsumowanie
Wracając do problemu omawianego na początku artykułu, jeżeli zapiszemy datę dodania komentarza w czasie uniwersalnym, to z łatwością będziemy mogli przekonwertować taką datę na czas lokalny, który jest na urządzeniu użytkownika. Niezależnie od tego, w którym miejscu na świecie użytkownik dodał komentarz, to data wyświetli się odpowiednio dla innych użytkowników korzystających z naszej aplikacji w innych częściach globu, zgodnie z ich czasem lokalnym.
Jeżeli użytkownik z Pekinu (GMT+8) doda komentarz o godz. 20:00 czasu lokalnego w Pekinie, to zapiszemy tę godzinę jako 12:00 czasu uniwersalnego (2024-03-17T12:00:00.000Z
). Użytkownik z Warszawy (GMT+1) zobaczy z kolei, że komentarz chińskiego użytkownika został dodany o 13:00 czasu polskiego.
Zawsze należy przechowywać daty w formacie ISO ze wskazaniem na strefę czasową, nawet jeżeli zakładamy, że aplikacja będzie odwiedzana tylko przez użytkowników z Polski. Uchroni nas to przed potencjalnymi błędami związanymi z wyświetlaniem daty, które niejednokrotnie mogą być poważnymi problemami, które będą uniemożliwiały użytkownikowi interakcje z systemem.