Obiekt Date to moment w czasie
Date w JavaScript reprezentuje jedną konkretną chwilę: wewnętrznie to po prostu liczba milisekund od 1 stycznia 1970 roku UTC (tak zwana „epoka Uniksa”). Cała reszta, czyli lata, miesiące, dni, strefy czasowe i formatowanie, to widok nałożony na tę liczbę.
now.getTime() to surowa liczba milisekund. Wszystko, co robi Date (porównywanie, dodawanie dni, formatowanie), sprowadza się do operacji na tej liczbie i ponownej jej interpretacji.
Zapamiętaj ten model. Date to nie „14 marca w Paryżu”. To uniwersalna chwila, którą można pokazać jako 14 marca w Paryżu albo 13 marca w Los Angeles, zależnie od strefy czasowej, przez którą na nią patrzysz.
Tworzenie dat
Są cztery główne sposoby na utworzenie obiektu Date:
Zwróć uwagę na dwie rzeczy:
- Konstruktor z częściami używa miesięcy numerowanych od zera.
2oznacza marzec. Styczeń to0. To stałe źródło błędów o jeden, ale przynajmniej API jest konsekwentne: wszędzie miesiące liczy się od 0. new Date("2026-03-14")(bez godziny) jest parsowane jako północ UTC.new Date("2026-03-14T09:30")(bezZ) jest parsowane jako czas lokalny. Ta asymetria to klasyczna pułapka.
Jeśli chcesz dostać „teraz” jako liczbę, wybierz Date.now(): nie tworzy obiektu.
Date.now() to właściwe narzędzie do mierzenia upływu czasu, limitów czasu i wszystkiego, co nie wymaga obliczeń kalendarzowych.
Odczytywanie części daty
Mając obiekt Date, wyciągasz z niego składniki za pomocą getterów. Każdy występuje w dwóch wersjach: dla czasu lokalnego i dla UTC.
Wersje lokalne zależą od komputera, na którym działa kod. Jeśli zapisujesz albo porównujesz daty między użytkownikami i serwerami, jawnie wybierz UTC, bo inaczej będziesz ścigać błędy widma. Praktyczna zasada: gettery UTC do wszystkiego, co trafia do bazy danych albo logu; gettery lokalne do tego, co za chwilę pokażesz człowiekowi.
Nie używaj getYear(). To przestarzała metoda, która zwraca year - 1900 i istnieje tylko dla zgodności. Zawsze sięgaj po getFullYear().
Formatowanie dla ludzi
Unikaj date.toString() wszędzie tam, gdzie wynik ma znaczenie: jego format zależy od ustawień regionalnych i silnika. Warto znać dwa formatery.
Do standardowego tekstu czytelnego dla maszyn użyj toISOString():
Tego formatu używasz przy logowaniu, zapisie do JSON i wysyłaniu przez sieć. Zawsze jest w UTC i zawsze jednoznaczny.
Do tekstu dla ludzi użyj Intl.DateTimeFormat albo metod toLocale*, które z niego korzystają:
Intl.DateTimeFormat obsługuje ustawienia regionalne, strefy czasowe i każdą kombinację pól, jakiej możesz potrzebować. Sięgnij po niego, zanim zaczniesz ręcznie składać ${year}-${month}-${day}: właśnie w takim sklejaniu tekstu żyją błędy z miesiącem przesuniętym o jeden.
Porównywanie dat
Dwa obiekty Date oznaczające tę samą chwilę nie są równe przez ===, bo === sprawdza tożsamość obiektów, a nie wartość. Porównuj zamiast tego ich znaczniki czasu:
Do ustalania kolejności operatory porównania działają bezpośrednio, bo zamieniają daty na liczby:
Odejmowanie daje różnicę w milisekundach. Podziel przez 1000 * 60 * 60 * 24, żeby dostać dni. Za pierwszym razem rozpisz tę stałą; z czasem 86_400_000 rozpoznasz na pierwszy rzut oka.
Arytmetyka na datach
Nie ma metody addDays. Idiomatyczny sposób to setDate, setMonth i podobne: przyjmują wartości spoza zakresu i poprawnie je przenoszą:
Dwie rzeczy warte podkreślenia:
new Date(date)kopiuje datę.setDatemodyfikuje obiekt, więc zawsze najpierw zrób kopię, bo inaczej zmienisz wartość należącą do kodu wywołującego.setDate(35)w miesiącu z 31 dniami automatycznie przechodzi na następny miesiąc. Tak samosetMonth(14)przesuwa rok. Dzięki temu arytmetyka jest dużo mniej bolesna, niż się wydaje.
Do wszystkiego bardziej złożonego (dni robocze, wydarzenia cykliczne, okresy uwzględniające miesiące) użyj biblioteki (date-fns, Luxon albo nadchodzącego API Temporal). Własne obliczenia kalendarzowe wykraczające poza „dodaj kilka dni” to grzęzawisko.
Strefy czasowe bez złudzeń
Strefy czasowe to największe pojedyncze źródło błędów z datami. Zasady, które warto sobie przyswoić:
Dateprzechowuje chwilę w UTC. Strefa czasowa jest stosowana dopiero przy odczycie części albo formatowaniu.- Strefa czasowa używana przez
getHours(),getDate()itd. to lokalna strefa komputera, na którym działa kod. Serwery i przeglądarki często się w tym różnią. new Date("2026-03-14")(sama data) jest parsowane jako UTC.new Date("2026-03-14T00:00")(z godziną, bez strefy) jako czas lokalny.new Date(2026, 2, 14)(z części) też jako czas lokalny.
Gdy musisz pokazać datę w konkretnej strefie czasowej, przekaż timeZone do Intl.DateTimeFormat:
Ta sama chwila, dwa widoki. Sam obiekt Date się nie zmienił.
Mały działający przykład
Wszystko razem: funkcja, która opisuje, jak dawno coś się wydarzyło:
Na wejściu znaczniki czasu, na wyjściu czytelny tekst. Tak wygląda 90% prawdziwego kodu z datami: odejmij dwie chwile, podziel przez jednostkę, zaokrąglij, sformatuj.
Co warto zapamiętać
Dateto chwila w UTC. Strefy czasowe pojawiają się przy odczycie albo formatowaniu.- Używaj
Date.now()do znaczników czasu, anew Date()do pracy z kalendarzem. toISOString()do zapisu i logów,Intl.DateTimeFormatdla użytkowników.- Porównuj przez
getTime()albo</>. Nigdy przez===. - Miesiące liczy się od 0. Uważaj na pułapkę przy parsowaniu tekstu z samą datą.
- Do poważnych obliczeń na datach użyj biblioteki.
Dalej: adresy URL i query stringi
Daty często trafiają do adresów URL: filtrowanie po zakresie dat, znacznik czasu jako parametr zapytania. Ręczne parsowanie i budowanie adresów URL jest tak samo podatne na błędy jak ręczne formatowanie dat, a biblioteka standardowa ma obiekt URL, który robi to porządnie. O tym jest następna strona.
Najczęściej zadawane pytania
Jak pobrać aktualną datę w JavaScript?
Wywołaj new Date() bez argumentów. Zwraca obiekt Date reprezentujący chwilę, w której uruchomiono konstruktor. Jeśli potrzebujesz tylko liczbowego znacznika czasu (milisekundy od 1970 roku), użyj Date.now(): jest szybsze i nie tworzy całego obiektu.
Jak porównać dwie daty w JavaScript?
Porównuj ich znaczniki czasu, a nie same obiekty Date. a.getTime() < b.getTime() działa, podobnie jak a < b, bo < zamienia daty na liczby. Ale a === b nie działa: === sprawdza tożsamość obiektów, więc dwa obiekty Date oznaczające tę samą chwilę nigdy nie są ściśle równe.
Jak sformatować datę w JavaScript?
Do wszystkiego, co widzi użytkownik, używaj Intl.DateTimeFormat albo date.toLocaleDateString(): poprawnie obsługują języki i strefy czasowe. Do danych dla maszyn date.toISOString() daje standardowy tekst, np. 2026-03-14T09:30:00.000Z. Unikaj date.toString() przy zapisywaniu danych, bo jego format zależy od ustawień regionalnych.
Dlaczego moja data w JavaScript przesuwa się o jeden dzień?
Zwykle to kwestia strefy czasowej. new Date('2026-03-14') jest parsowane jako północ UTC, ale date.getDate() zwraca dzień w lokalnej strefie czasowej, a to może być dzień wcześniej. Użyj getUTCDate(), żeby dostać dzień w UTC, albo twórz daty przez new Date(year, month, day), które od początku używa czasu lokalnego.