JavaScript / Dates

    Biblioteki Dat w JavaScript

    date-fns, Day.js, Luxon, Temporal API i Intl — parsowanie, formatowanie, strefy czasowe, DST i walidacja w TypeScript i Next.js.

    date-fns
    Tree-shakeable
    Day.js
    2KB bundle
    Temporal
    Future standard
    Intl API
    Zero deps

    6 bibliotek dat JavaScript — porównanie

    date-fns, Day.js, Luxon, Moment.js (legacy), Temporal API i Intl — rozmiar, API, TypeScript i obsługa stref czasowych.

    Biblioteka Rozmiar API TypeScript Kiedy
    date-fns 13KB (tree-shaken) Pure functions (import per function) Natywny Modern projects, TypeScript, tree-shaking
    Day.js 2KB core Chainable (Moment-like) Natywny Moment.js migration, małe bundle
    Luxon 23KB Immutable, OOP Dobry Timezone-heavy, Moment successor
    Moment.js 232KB Chainable, mutable Zewnętrzny @types Legacy tylko — nie używaj w nowych
    Temporal API 0KB (native) Immutable, type-safe Natywny (spec) Future standard — polyfill teraz
    Intl.DateTimeFormat 0KB (native) Format only (native) Natywny Formatowanie bez manipulacji

    Często zadawane pytania

    Co to jest date-fns i dlaczego wygrała z Moment.js?

    date-fns: modularna biblioteka dat JavaScript (2014, Sasha Koss). Tree-shakeable — importuj tylko to co używasz. Immutable — nie mutuje dat. TypeScript natywny. Pure functions — bez side effects. Moment.js (legacy, 2011): pierwsza popularna biblioteka dat. Monolityczna — cały bundle (232KB minified). Mutable — mutuje obiekty Date. deprecated dla nowych projektów (oficjalne zalecenie od 2020). Przykład date-fns: import {format, addDays, differenceInDays, isAfter, parseISO, startOfWeek, endOfMonth} from 'date-fns'. import {pl} from 'date-fns/locale'. format(new Date(), 'dd MMMM yyyy', {locale: pl}) = '13 kwietnia 2024'. addDays(new Date(), 7) — za tydzień. differenceInDays(endDate, startDate) — ilość dni różnicy. isAfter(date1, date2). startOfWeek(new Date(), {weekStartsOn: 1}) — poniedziałek. parseISO('2024-04-13T12:00:00Z') — parse ISO string. Formatowanie: dd.MM.yyyy (PL format). yyyy-MM-dd (ISO format). HH:mm:ss. d MMMM yyyy, HH:mm. Strefy czasowe (date-fns-tz): format(utcDate, 'yyyy-MM-dd HH:mm', {timeZone: 'Europe/Warsaw'}). toZonedTime(), fromZonedTime(). Parsowanie: parse('13/04/2024', 'dd/MM/yyyy', new Date()). isValid(parsedDate). Comparison functions: isBefore, isAfter, isEqual. compareAsc, compareDesc do sortowania. Bundle size: date-fns v3 — 13KB dla podstawowych operacji (tree-shaken). Moment.js — 232KB zawsze.

    Day.js — ultralekka alternatywa dla Moment.js?

    Day.js: Moment.js-compatible API, 2KB gzipped (Ikaros Kun, 2018). Łatwa migracja z Moment.js (zmień import). Plugin system zamiast wszystkiego w bundle. Podstawy: dayjs() — bieżąca data. dayjs('2024-04-13'). dayjs(1712995200000) — ze timestamp. Formatowanie: dayjs().format('DD.MM.YYYY') = '13.04.2024'. dayjs().format('MMMM D, YYYY') = 'April 13, 2024'. Manipulacja: dayjs().add(7, 'day'). dayjs().subtract(1, 'month'). dayjs().startOf('week'). dayjs().endOf('year'). Różnica: dayjs('2024-04-20').diff(dayjs(), 'day') = 7. Porównania: dayjs().isBefore(dayjs('2024-12-31')). dayjs().isAfter(). dayjs().isSame('2024-04-13', 'day'). Pluginy (extend separately): import isSameOrBefore from 'dayjs/plugin/isSameOrBefore'. dayjs.extend(isSameOrBefore). Polskie locale: import 'dayjs/locale/pl'. dayjs.locale('pl'). dayjs().format('MMMM') = 'kwiecień'. Duration plugin: dayjs.duration(2, 'hours').humanize() = 'a few hours'. RelativeTime: dayjs('2024-01-01').fromNow() = '3 months ago'. Calendar: dayjs().calendar(null, {sameDay: '[Dzisiaj] HH:mm', nextDay: '[Jutro]'}). Day.js vs date-fns: Day.js — Moment.js migration, small bundle, mutable (clone przed mutacją). date-fns — pure functions, tree-shaking lepsza, TypeScript. Kiedy Day.js: legacy Moment.js codebase. Małe projekty. Mała nauka krzywej.

    Temporal API — nowy standard JavaScript dla dat i czasu?

    Temporal: nowy proposal TC39 dla JavaScript (Stage 3, 2024). Rozwiązuje wszystkie problemy native Date: mutability, timezone bugs, DST issues. Obiekty: Temporal.PlainDate — data bez czasu (2024-04-13). Temporal.PlainTime — czas bez daty (12:00:00). Temporal.PlainDateTime — data z czasem, bez timezone. Temporal.ZonedDateTime — z timezone. Temporal.Instant — punkt w czasie (Unix timestamp). Temporal.Duration — czas trwania. Temporal.Now: Temporal.Now.plainDateTimeISO() — bieżąca data i czas. Temporal.Now.zonedDateTimeISO('Europe/Warsaw'). Temporal.Now.instant(). Tworzenie: Temporal.PlainDate.from('2024-04-13'). Temporal.PlainDate.from({year: 2024, month: 4, day: 13}). Manipulacja (immutable!): const tomorrow = today.add({days: 1}). const nextMonth = date.add({months: 1}). const earlier = time.subtract({hours: 2}). Porównania: Temporal.PlainDate.compare(date1, date2) = -1|0|1. date1.equals(date2). Timezone-aware: const warsaw = Temporal.ZonedDateTime.from('2024-04-13T12:00:00[Europe/Warsaw]'). warsaw.withTimeZone('America/New_York'). DST handling automatyczny. Duration: const d = Temporal.Duration.from({hours: 2, minutes: 30}). d.add(Temporal.Duration.from({minutes: 15})). Wsparcie przeglądarek 2024: Chrome 121+, Firefox, Safari — za polyfill (@js-temporal/polyfill). Produkcja: używaj polyfill. Kiedy Temporal: nowe projekty TypeScript. Timezone-critical apps. Kompleksowe operacje na datach.

    Strefy czasowe — problemy UTC, DST i jak je rozwiązać w Node.js?

    Problemy z timezone w JavaScript: new Date() — zwraca local system time. JSON.stringify(date) — konwertuje do UTC. Różne wyniki na różnych serwerach (TZ env). DST (Daylight Saving Time) — zegarek przesuwa się o godzinę. Np. 2024-03-31 02:00 -> 03:00 w Europie. Błędy przy dodawaniu 24h zamiast 1 dnia. Najlepsze praktyki: Przechowuj zawsze UTC w bazie danych. Konwertuj na local time przy wyświetlaniu. Używaj timezone-aware bibliotek. PostgreSQL: timestamp with time zone (timestamptz). Przechowuje UTC. Konwertuje przy SET timezone. Prisma: DateTime -> timestamptz. date-fns-tz: toZonedTime(utcDate, 'Europe/Warsaw'). format(zonedDate, 'dd.MM.yyyy HH:mm', {timeZone: 'Europe/Warsaw'}). fromZonedTime(localDate, 'Europe/Warsaw') -> UTC. Luxon: DateTime.fromISO(iso).setZone('Europe/Warsaw'). dt.toISO() -> zawsze UTC. DateTime.now().setZone('Europe/Warsaw'). DST-safe date operations: addDays zamiast addHours(24). Temporal API obsługuje DST automatycznie. Przykład DST bug: addHours(new Date('2024-03-31 01:30'), 2) = '2024-03-31 04:30' (pominięcie 02:00-03:00). addDays(new Date('2024-03-31'), 1) = '2024-04-01' (poprawnie). Node.js TZ env: process.env.TZ = 'UTC'. Wymuszaj UTC na serwerze. Unikaj ambiguity. Intl.DateTimeFormat (native): formatowanie z timezone bez bibliotek. Intl.DateTimeFormat('pl-PL', {timeZone: 'Europe/Warsaw', hour12: false}).format(date).

    Parsowanie i walidacja dat — ISO 8601, locale formats i edge cases?

    ISO 8601: standard daty i czasu. 2024-04-13T12:00:00Z (UTC). 2024-04-13T14:00:00+02:00 (z offset). YYYY-MM-DD (data). HH:mm:ss (czas). Parsowanie native Date: new Date('2024-04-13') — interpretacja jako UTC midnight (problem ze strefami). new Date('2024-04-13T12:00:00Z') — explicit UTC. new Date('April 13, 2024') — locale-dependent (unikaj). Bezpieczne parsowanie z date-fns: parseISO('2024-04-13T12:00:00Z') — zawsze poprawne. parse('13/04/2024', 'dd/MM/yyyy', new Date()) — locale format. isValid(parsedDate) — sprawdź poprawność. Invalid date detection: isNaN(date.getTime()). isValid() z date-fns. Walidacja z Zod: z.string().datetime() — ISO datetime. z.coerce.date() — coerce string/number to Date. z.string().date() — tylko data (YYYY-MM-DD). Zod regex: z.string().regex(/^d{4}-d{2}-d{2}$/). Edge cases: 2024-02-29 (leap year). 2023-02-29 (nieistniejąca). isValid check. December 31, 23:59 -> January 1 midnight rollover. Century boundaries. Locale formats PL: dd.MM.yyyy (13.04.2024). dd/MM/yyyy (13/04/2024). dd MMMM yyyy (13 kwietnia 2024). Relative time: formatDistanceToNow(date, {locale: pl}) = 'ponad rok temu'. formatRelative(date, new Date(), {locale: pl}) = 'ostatni czwartek o 12:00'. Date range utilities: eachDayOfInterval({start, end}). isWithinInterval(date, {start, end}). clamp(date, {start, end}) — clamp do zakresu. Calendar utils: getDay(date) = 0-6 (0=niedziela). getWeek(date, {weekStartsOn: 1}) — numer tygodnia. getDaysInMonth(date) = 28-31.

    Czytaj dalej

    Powiązane artykuły

    Kontakt

    Skontaktuj się z nami

    Porozmawiajmy o Twoim projekcie. Bezpłatna wycena w ciągu 24 godzin.

    Wyślij zapytanie

    Bezpłatna wycena w 24h
    Bez zobowiązań
    Indywidualne podejście
    Ekspresowa realizacja

    Telefon

    +48 790 814 814

    Pon-Pt: 9:00 - 18:00

    Email

    adam@fotz.pl

    Odpowiadamy w ciągu 24h

    Adres

    Plac Wolności 16

    61-739 Poznań

    Godziny pracy

    Pon - Pt9:00 - 18:00
    Sob - NdzZamknięte

    Wolisz porozmawiać?

    Zadzwoń teraz i porozmawiaj z naszym specjalistą o Twoim projekcie.

    Zadzwoń teraz