Polski

Szczegółowy przewodnik po Temporal API w JavaScript – nowoczesnym rozwiązaniu do efektywnego zarządzania datami i czasem w różnych kontekstach międzynarodowych.

Temporal API w JavaScript: Nowoczesne zarządzanie datą i czasem dla globalnej publiczzności

Obiekt `Date` w JavaScript od dawna był źródłem frustracji dla deweloperów. Jego mutowalność, niespójne API i słabe wsparcie dla stref czasowych doprowadziły do powstania licznych bibliotek, takich jak Moment.js i date-fns, które miały wypełnić te luki. Teraz, dzięki Temporal API, JavaScript oferuje nowoczesne, wbudowane rozwiązanie do obsługi dat i czasu z lepszą przejrzystością i precyzją. Ten artykuł stanowi kompleksowy przegląd Temporal API, koncentrując się na jego funkcjach, korzyściach i zastosowaniu w różnorodnych kontekstach międzynarodowych.

Czym jest Temporal API?

Temporal API to nowy, globalny obiekt w JavaScript, zaprojektowany w celu rozwiązania problemów obiektu `Date`. Zapewnia on czyste, niemutowalne API do pracy z datami, czasem, strefami czasowymi i systemami kalendarzowymi. Co kluczowe, ma na celu przedstawienie koncepcji daty i czasu w sposób, który jest bardziej zgodny z rzeczywistym użyciem i oczekiwaniami, co znacznie ułatwia internacjonalizację.

Kluczowe cechy:

Podstawowe obiekty Temporal

Temporal API wprowadza kilka nowych typów obiektów. Oto niektóre z najważniejszych:

Praca z datami

Tworzenie `Temporal.PlainDate`

Aby utworzyć `Temporal.PlainDate`, możesz użyć konstruktora:

const plainDate = new Temporal.PlainDate(2024, 10, 27); // Rok, Miesiąc (1-12), Dzień
console.log(plainDate.toString()); // Wynik: 2024-10-27

Możesz także użyć metody `from`, która akceptuje ciąg znaków w formacie ISO 8601:

const plainDateFromString = Temporal.PlainDate.from('2024-10-27');
console.log(plainDateFromString.toString()); // Wynik: 2024-10-27

Pobieranie składników daty

Możesz uzyskać dostęp do poszczególnych składników daty za pomocą właściwości takich jak `year`, `month` i `day`:

console.log(plainDate.year); // Wynik: 2024
console.log(plainDate.month); // Wynik: 10
console.log(plainDate.day); // Wynik: 27

Arytmetyka na datach

Aby dodać lub odjąć dni, tygodnie, miesiące lub lata, użyj metod `plus` i `minus`. Metody te zwracają nowy obiekt `Temporal.PlainDate`:

const nextWeek = plainDate.plus({ days: 7 });
console.log(nextWeek.toString()); // Wynik: 2024-11-03

const lastMonth = plainDate.minus({ months: 1 });
console.log(lastMonth.toString()); // Wynik: 2024-09-27

Porównywanie dat

Możesz porównywać daty za pomocą metody `compare`:

const date1 = new Temporal.PlainDate(2024, 10, 27);
const date2 = new Temporal.PlainDate(2024, 11, 15);

console.log(Temporal.PlainDate.compare(date1, date2)); // Wynik: -1 (date1 jest wcześniejsza niż date2)

Praca z czasem

Tworzenie `Temporal.PlainTime`

Aby utworzyć `Temporal.PlainTime`, użyj konstruktora:

const plainTime = new Temporal.PlainTime(10, 30, 0); // Godzina, Minuta, Sekunda
console.log(plainTime.toString()); // Wynik: 10:30:00

Lub użyj metody `from` z ciągiem znaków czasu w formacie ISO 8601:

const plainTimeFromString = Temporal.PlainTime.from('10:30:00');
console.log(plainTimeFromString.toString()); // Wynik: 10:30:00

Pobieranie składników czasu

console.log(plainTime.hour); // Wynik: 10
console.log(plainTime.minute); // Wynik: 30
console.log(plainTime.second); // Wynik: 0

Arytmetyka na czasie

const later = plainTime.plus({ minutes: 15 });
console.log(later.toString()); // Wynik: 10:45:00

Praca z datą i czasem jednocześnie

Tworzenie `Temporal.PlainDateTime`

Możesz utworzyć `Temporal.PlainDateTime` bezpośrednio lub łącząc `Temporal.PlainDate` i `Temporal.PlainTime`:

const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
console.log(plainDateTime.toString()); // Wynik: 2024-10-27T10:30:00

const date = new Temporal.PlainDate(2024, 10, 27);
const time = new Temporal.PlainTime(10, 30, 0);
const combinedDateTime = date.toPlainDateTime(time);
console.log(combinedDateTime.toString()); // Wynik: 2024-10-27T10:30:00

Strefy czasowe

Prawidłowa obsługa stref czasowych jest kluczowa dla aplikacji, które mają do czynienia z użytkownikami w różnych lokalizacjach. Temporal API zapewnia solidne wsparcie dla stref czasowych za pośrednictwem obiektów `Temporal.ZonedDateTime` i `Temporal.TimeZone`.

Tworzenie `Temporal.ZonedDateTime`

Aby utworzyć `Temporal.ZonedDateTime`, potrzebujesz `Temporal.PlainDateTime` oraz identyfikatora strefy czasowej. Identyfikatory stref czasowych opierają się na bazie danych stref czasowych IANA (np. `America/Los_Angeles`, `Europe/London`, `Asia/Tokyo`).

const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
const timeZone = 'America/Los_Angeles';
const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);
console.log(zonedDateTime.toString()); // Wynik: 2024-10-27T10:30:00-07:00[America/Los_Angeles] (Przesunięcie będzie zależeć od zasad czasu letniego)

Alternatywnie, utwórz `Temporal.ZonedDateTime` z obiektu `Instant`.

const instant = Temporal.Instant.fromEpochSeconds(1666866600); // Przykładowy znacznik czasu
const zonedDateTimeFromInstant = instant.toZonedDateTimeISO(timeZone); // Strefa czasowa, np. 'America/Los_Angeles'
console.log(zonedDateTimeFromInstant.toString());

Konwersja między strefami czasowymi

Możesz przekonwertować `Temporal.ZonedDateTime` na inną strefę czasową za pomocą metody `withTimeZone`:

const newTimeZone = 'Europe/London';
const zonedDateTimeInLondon = zonedDateTime.withTimeZone(newTimeZone);
console.log(zonedDateTimeInLondon.toString()); // Wynik: 2024-10-27T18:30:00+01:00[Europe/London]

Praca z przesunięciami stref czasowych

Metoda `getOffsetStringFor` obiektu `Temporal.TimeZone` zwraca ciąg znaków przesunięcia dla danego `Temporal.Instant`:

const timeZoneObject = new Temporal.TimeZone(timeZone);
const offsetString = timeZoneObject.getOffsetStringFor(zonedDateTime.toInstant());
console.log(offsetString); // Wynik: -07:00 (W zależności od zasad czasu letniego)

Kluczowe jest używanie poprawnych identyfikatorów stref czasowych IANA w celu uzyskania dokładnych obliczeń. Identyfikatory te są regularnie utrzymywane i aktualizowane, aby odzwierciedlać zmiany w czasie letnim i granicach stref czasowych.

Okresy czasu (Durations)

Obiekt `Temporal.Duration` reprezentuje okres czasu. Może być używany do dodawania lub odejmowania od dat i czasów.

Tworzenie `Temporal.Duration`

Możesz utworzyć `Temporal.Duration` za pomocą konstruktora, określając lata, miesiące, dni, godziny, minuty, sekundy, milisekundy, mikrosekundy i nanosekundy:

const duration = new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 8, 9); // Lata, Miesiące, Dni, Godziny, Minuty, Sekundy, Milisekundy, Mikrosekundy, Nanosekundy
console.log(duration.toString()); // Wynik: P1Y2M3DT4H5M6.007008009S

Lub używając ciągu znaków okresu w formacie ISO 8601:

const durationFromString = Temporal.Duration.from('P1Y2M3DT4H5M6S');
console.log(durationFromString.toString()); // Wynik: P1Y2M3DT4H5M6S

Dodawanie okresów czasu do dat i czasów

const plainDate = new Temporal.PlainDate(2024, 10, 27);
const duration = new Temporal.Duration(0, 0, 7); // 7 dni
const newDate = plainDate.plus(duration);
console.log(newDate.toString()); // Wynik: 2024-11-03

Należy pamiętać, że dodawanie okresów czasu obejmujących miesiące lub lata do dat wymaga ostrożności, ponieważ liczba dni w miesiącu lub roku może się różnić.

Systemy kalendarzowe

Temporal API obsługuje różne systemy kalendarzowe poza kalendarzem gregoriańskim. Jest to kluczowe dla aplikacji, które muszą obsługiwać daty w różnych kontekstach kulturowych. Chociaż wsparcie wciąż się rozwija, stanowi to fundament dla przyszłej rozbudowy.

Używanie alternatywnych kalendarzy

Aby użyć określonego kalendarza, możesz go zdefiniować podczas tworzenia obiektów Temporal:

const hebrewDate = new Temporal.PlainDate(5785, 1, 1, { calendar: 'hebrew' });
console.log(hebrewDate.toString()); // Konkretny wynik może się różnić w zależności od implementacji i formatowania. W momencie pisania tego tekstu wymaga polyfilla w wielu środowiskach.

Ważne: Wsparcie dla kalendarzy innych niż gregoriański może wymagać polyfilli lub specyficznego wsparcia przeglądarki/środowiska. Sprawdź najnowsze tabele kompatybilności przeglądarek i dokumentację Temporal API, aby uzyskać aktualne informacje.

Formatowanie dat i czasu

Chociaż Temporal API koncentruje się na manipulacji datą i czasem, formatowanie jest zazwyczaj obsługiwane przez obiekt `Intl.DateTimeFormat`, który jest częścią Internationalization API. Obiekty Temporal bezproblemowo współpracują z `Intl.DateTimeFormat`.

Używanie `Intl.DateTimeFormat`

Oto jak sformatować `Temporal.PlainDate` za pomocą `Intl.DateTimeFormat`:

const plainDate = new Temporal.PlainDate(2024, 10, 27);
const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
console.log(formatter.format(plainDate)); // Wynik: October 27, 2024

const formatterGerman = new Intl.DateTimeFormat('de-DE', { year: 'numeric', month: 'long', day: 'numeric' });
console.log(formatterGerman.format(plainDate)); // Wynik: 27. Oktober 2024

Możesz dostosować opcje formatowania do swoich potrzeb. Pierwszym argumentem `Intl.DateTimeFormat` jest lokalizacja (locale), która określa język i regionalne konwencje używane do formatowania. Używanie różnych lokalizacji (np. 'en-US', 'de-DE', 'fr-FR', 'ja-JP') daje różne formaty wyjściowe.

Formatowanie `Temporal.ZonedDateTime`

Formatowanie `Temporal.ZonedDateTime` jest podobne, ale możesz również uwzględnić informacje o strefie czasowej w wyniku:

const plainDateTime = new Temporal.PlainDateTime(2024, 10, 27, 10, 30, 0);
const timeZone = 'America/Los_Angeles';
const zonedDateTime = plainDateTime.toZonedDateTime(timeZone);

const formatter = new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', timeZoneName: 'short' });
console.log(formatter.format(zonedDateTime)); // Wynik: October 27, 2024, 10:30 AM PDT (Skrót strefy czasowej zależy od zasad czasu letniego)

Dobre praktyki internacjonalizacji

Pracując z datami i czasem w kontekście globalnym, należy pamiętać o następujących dobrych praktykach:

Porównanie Temporal API z przestarzałym obiektem Date

Oto tabela podkreślająca kluczowe różnice i zalety Temporal API w porównaniu z przestarzałym obiektem `Date`:

Cecha Przestarzały obiekt `Date` Temporal API
Mutowalność Mutowalny (modyfikuje oryginalny obiekt) Niemutowalny (zwraca nowe obiekty)
Wsparcie dla stref czasowych Ograniczone i często problematyczne Solidne i dokładne, oparte na bazie danych stref czasowych IANA
API Niespójne i trudne w użyciu Przejrzyste, spójne i intuicyjne
Precyzja Milisekunda Nanosekunda
Systemy kalendarzowe Ograniczone do gregoriańskiego Wspiera alternatywne systemy kalendarzowe (ze wsparciem w fazie rozwoju)
Internacjonalizacja Wymaga zewnętrznych bibliotek do solidnej internacjonalizacji Wbudowane wsparcie i bezproblemowa integracja z `Intl.DateTimeFormat`

Wsparcie przeglądarek i polyfille

Jako stosunkowo nowe API, wsparcie przeglądarek dla Temporal API wciąż się rozwija. Sprawdź najnowsze tabele kompatybilności przeglądarek (np. na MDN Web Docs), aby zobaczyć, które przeglądarki i środowiska obsługują je natywnie. W przypadku starszych przeglądarek lub środowisk bez natywnego wsparcia można użyć polyfilli, aby zapewnić funkcjonalność Temporal API. Wyszukaj w internecie "Temporal API polyfill", aby znaleźć odpowiednie opcje.

Podsumowanie

Temporal API w JavaScript stanowi znaczący krok naprzód w obsłudze dat i czasu w JavaScript. Jego niezmienność, przejrzyste API, solidne wsparcie dla stref czasowych i możliwości systemów kalendarzowych czynią go potężnym narzędziem dla deweloperów tworzących aplikacje, które muszą pracować z datami i czasem w sposób dokładny i niezawodny w różnorodnych kontekstach międzynarodowych. Chociaż wsparcie przeglądarek wciąż się rozwija, korzyści płynące z Temporal API sprawiają, że warto się go uczyć i wdrażać w nowych projektach. Przyjmując Temporal API i stosując dobre praktyki internacjonalizacji, możesz tworzyć aplikacje, które zapewniają bezproblemowe i dokładne doświadczenie z datą i czasem dla użytkowników na całym świecie.

Dalsza nauka