Więc przejdźmy dalej. Następną jednostką po dacie jest godzina reprezentowana przez klasę LocalTime . Klasycznym przykładem są godziny otwarcia sklepu, powiedzmy od 7:00 do 23:00. Sklepy są obecnie otwarte w całym kraju, ale faktyczne godziny otwarcia mogą się różnić w zależności od strefy czasowej. LocalTime to klasa wartości, która przechowuje tylko czas, bez powiązanej daty i strefy czasowej. Podczas dodawania lub odejmowania okresu czasu zostanie on ucięty o północy. Oznacza to, że 20:00 plus 6 godzin to 2:00. Używanie LocalTime jest podobne do LocalDate : LocalTime time = LocalTime.of(20, 30); int hour = date.getHour(); // 20 int minute = date.getMinute(); // 30 time = time.withSecond(6); // 20:30:06 time = time.plusMinutes(3); // 20:33:06 Modyfikatory mogą współpracować z LocalTime , ale operacje na czasie zwykle nie są tak skomplikowane, że wymagane są modyfikatory.
Łączenie daty i godziny
Następną klasą, której się przyjrzymy, jest
LocalDateTime . Ta klasa wartości jest kombinacją
LocalDate i
LocalTime . Reprezentuje zarówno datę, jak i godzinę, bez strefy czasowej.
LocalDateTime można utworzyć bezpośrednio lub poprzez połączenie daty i godziny:
LocalDateTime dt1 = LocalDateTime.of(2014, Month.JUNE, 10, 20, 30); LocalDateTime dt2 = LocalDateTime.of(date, time); LocalDateTime dt3 = date.atTime(20, 30); LocalDateTime dt4 = date.atTime(time); Trzecia i czwarta opcja wykorzystują metodę
atTime() , która zapewnia elastyczny sposób łączenia daty i godziny. Większość klas systemów daty i godziny ma metody „at”, których można użyć podczas łączenia obiektu z innym w celu utworzenia bardziej złożonego obiektu. Pozostałe metody klasy
LocalDateTime są podobne do metod
LocalDate i
LocalTime . Podobne wzorce nazewnictwa metod ułatwiają naukę
interfejsu API . W poniższej tabeli wymieniono wszystkie przedrostki metod, których to dotyczy:
Natychmiastowy
Kiedy mamy do czynienia z datami i godzinami, zwykle pracujemy z latami, miesiącami, dniami, godzinami, minutami i sekundami. Jest to jednak tylko jeden model czasu, który można nazwać „ludzkim”. Drugim powszechnie stosowanym modelem jest czas „maszynowy” lub „ciągły”. W tym modelu punkt na osi czasu jest reprezentowany przez jedną dużą liczbę. Takie podejście upraszcza algorytmy obliczeniowe i służy do przechowywania czasu w systemie operacyjnym
Unix , gdzie czas jest reprezentowany przez liczbę sekund, które upłynęły od 1 stycznia 1970 roku. Podobnie w
Javie czas jest przechowywany jako liczba milisekund, które upłynęły od 1 stycznia 1970 r. Maszynowe podejście do obliczeń czasu w
interfejsie API java.time zapewnia klasa wartości
Instant . Zapewnia możliwość przedstawienia punktu na osi czasu bez wszystkich towarzyszących informacji, takich jak strefa czasowa. W rzeczywistości ta klasa zawiera liczbę nanosekund, które upłynęły od północy 1 stycznia 1970 roku.
Instant start = Instant.now(); // произведем вычисления Instant end = Instant.now(); assert end.isAfter(start); //машина времени не сработала Zazwyczaj klasa
Instant służy do przechowywania i porównywania punktów w czasie, gdy trzeba zapisać, kiedy miało miejsce jakieś zdarzenie, ale nie przejmuje się strefą czasową, w której to nastąpiło. W większości przypadków bardziej interesujące jest to, czego nie możemy zrobić z klasą
Instant , niż to, co możemy z nią zrobić. Na przykład poniższe wiersze kodu spowodują wyjątki:
instant.get(ChronoField.MONTH_OF_YEAR); instant.plus(6, ChronoUnit.YEARS); Wyjątki występują, ponieważ obiekt
błyskawiczny przechowuje tylko liczbę nanosekund i nie zapewnia możliwości pracy z jednostkami czasu, które są bardziej przydatne dla ludzi. Aby użyć innych jednostek miary, musisz przynajmniej określić strefę czasową.
Strefy czasowe
Zasada stref czasowych powstała w Anglii, kiedy wynaleziono kolej i ulepszenia innych środków komunikacji, umożliwiono ludziom pokonywanie odległości wystarczających, aby różnice w czasie słonecznym były zauważalne. Do tego czasu każda wioska i miasto żyły według własnego czasu, który najczęściej mierzono zegarem słonecznym. To zdjęcie pokazuje przykład trudności, do jakich to doprowadziło - czerwone wskazówki zegara pokazują czas Greenwich, a czarne wskazówki pokazują czas lokalny, który różni się o 10 minut: rozwinął się system stref czasowych, zastępując lokalny czas słoneczny
. Kluczowym faktem jest jednak to, że strefy czasowe są tworzone przez polityków i często wykorzystywane do wykazania kontroli politycznej nad danym obszarem. Jak każda polityka, zasady dotyczące stref czasowych często zaprzeczają logice. Poza tym zasady te mogą się zmieniać, i to często, bez ostrzeżenia. Zasady dotyczące stref czasowych są opracowywane przez międzynarodową grupę publikującą bazę danych stref czasowych
IANA . Zawiera identyfikator każdego regionu Ziemi i historię zmian stref czasowych dla niego. Identyfikatory wyglądają jak
„Europa/Londyn” lub
„Ameryka/Nowy_Jork” . Przed udostępnieniem
interfejsu API java.time do reprezentowania strefy czasowej używana była klasa
TimeZone . Teraz zamiast tego używany jest
ZoneId . Istnieją dwie kluczowe różnice między nimi. Po pierwsze,
ZoneId jest niezmienny, co umożliwia między innymi przechowywanie obiektów tej klasy w zmiennych statycznych. Po drugie, same reguły przechowywane są w klasie
ZoneRules , a nie w samej
ZoneId , a żeby je uzyskać należy wywołać metodę
getRules() na obiekcie klasy
ZoneId . Wspólną cechą wszystkich stref czasowych jest stałe przesunięcie w stosunku do
czasu UTC/Greenwich . Najczęściej używasz tego, mówiąc o różnicach czasu między różnymi miastami, np. „Nowy Jork jest 5 godzin za Londynem”. Klasa
ZoneOffset , potomek
ZoneId , reprezentuje różnicę czasu z południkiem zerowym przechodzącym przez Greenwich w Londynie. Z punktu widzenia programisty byłoby wspaniale nie mieć do czynienia ze strefami czasowymi i ich złożonością.
API java.time pozwala to robić tak długo, jak to możliwe. Tam, gdzie to możliwe, używaj klas
LocalDate, LocalTime, LocalDateTime i
Instant . Jeśli nie możesz obejść się bez stref czasowych, użyj klasy
ZonedDateTime . Klasa
ZonedDateTimepozwala na przeliczenie dat i godzin z ludzkich jednostek miary, które widzimy na kalendarzach i zegarkach, na jednostki maszynowe. W rezultacie możesz utworzyć
ZonedTimeDate albo z klasy
Local , albo z
klasy Instant :
ZoneId zone = ZoneId.of("Europe/Paris"); LocalDate date = LocalDate.of(2014, Month.JUNE, 10); ZonedDateTime zdt1 = date.atStartOfDay(zone); Instant instant = Instant.now(); ZonedDateTime zdt2 = instant.atZone(zone); Jedną z najbardziej nieprzyjemnych cech stref czasowych jest tak zwany czas letni. W przypadku zmiany czasu letniego na i z Greenwich różnica stref czasowych w stosunku do Greenwich zmienia się dwa razy (lub częściej) w roku, zwykle zwiększając się wiosną i zmniejszając jesienią. Kiedy tak się stanie, będziemy musieli przestawić wszystkie zegary w naszym domu. W klasach
Java.time dane przesunięcia są reprezentowane jako
„transformacje przesunięcia” . Wiosną powoduje to „lukę” w czasie, gdy niektóre wartości czasu są niemożliwe, a jesienią wręcz przeciwnie, niektóre wartości czasu występują dwukrotnie. Wszystko to jest obsługiwane przez klasę
ZonedDateTime poprzez jej metody fabryczne i metody konwertera. Na przykład dodanie jednego dnia powoduje dodanie dnia logicznego, który może być reprezentowany przez więcej lub mniej niż 24 godziny, jeśli przejdziemy na czas letni lub odwrotnie. Podobnie nazywa się metoda
atStartOfDay() ponieważ nie możemy zagwarantować, że dzień zacznie się dokładnie o północy - musimy uwzględnić różnicę czasową przy przejściu na czas letni. I ostatnia wskazówka dotycząca czasu letniego. Jeśli chcesz wykazać, że uwzględniłeś nakładanie się czasu podczas przejścia z lata na zimę (gdy ta sama wartość czasu pojawia się dwukrotnie), możesz skorzystać z jednej z dwóch specjalnych metod przeznaczonych dla takich sytuacji: Metody te zwrócą wcześniejszą lub późniejszą
zdt = zdt.withEarlierOffsetAtOverlap(); zdt = zdt.withLaterOffsetAtOverlap(); wartość , jeśli obiekt zostanie nałożony na siebie podczas przejścia z czasu letniego na zimowy. We wszystkich innych sytuacjach zwracane wartości będą takie same.
Interwały czasowe
Wszystkie klasy, które omówiliśmy wcześniej, działają jako punkty na osi czasu. Do reprezentowania przedziałów czasu potrzebne są dwie dodatkowe klasy wartości. Klasa
Duration reprezentuje czas mierzony w sekundach i nanosekundach. Na przykład „23,6 sekundy”. Klasa
Period reprezentuje okres mierzony w latach, miesiącach i dniach. Na przykład - „3 lata, 2 miesiące i 6 dni”. Przedziały te można dodawać lub odejmować od daty lub godziny:
Period sixMonths = Period.ofMonths(6); LocalDate date = LocalDate.now(); LocalDate future = date.plus(sixMonths);
Formatowanie i parsowanie
Cały pakiet jest przeznaczony do formatowania i wyświetlania dat i godzin -
java.time.format . Pakiet dotyczy klasy
DateTimeFormatter i jej fabryki
DateTimeFormatterBuilder . Najczęstsze sposoby tworzenia formatera to metody statyczne i stałe w
DateTimeFormatter , w tym:
Stałe dla popularnych formatów opisanych w ISO, takich jak ISO_LOCAL_DATE.
Wzorce identyfikowane literami, np. ofPattern("dd/MM/uuuu").
Zlokalizowane style, takie jak ofLocalizedDate(FormatStyle.MEDIUM).
Po utworzeniu formatera zwykle używa się go, przekazując go do odpowiedniej metody klasy date:
DateTimeFormatter f = DateTimeFormatter.ofPattern("dd/MM/uuuu"); LocalDate date = LocalDate.parse("24/06/2014", f); String str = date.format(f); W ten sposób kod odpowiedzialny za formatowanie danych wyjściowych jest izolowany w osobnej klasie. Jeśli chcesz osobno określić ustawienia regionalne dla formatowania daty, użyj metody formatowania
withLocale(Locale) . Klasy odpowiedzialne za kalendarz, strefę czasową i wprowadzanie/wyprowadzanie liczb ułamkowych mają podobne metody. Jeśli potrzebujesz więcej opcji dostrajania, zapoznaj się z dokumentacją klasy
DateTimeFormatterBuilder , która pozwala krok po kroku tworzyć złożone formatery. Umożliwia także ustawienie analizowania tekstu bez rozróżniania wielkości liter, ignorowanie niektórych błędów analizy, ustawianie przesunięć i elementów opcjonalnych.
Konkluzja
API java.time to nowy, kompleksowy model pracy z datą i czasem w
Java SE 8 . Przenosi pomysły i implementacje z
Joda-Time na wyższy poziom i wreszcie pozwala programistom uniknąć używania
java.util.Date i
Calendar . Teraz praca z datami i godzinami może być świetną zabawą!
GO TO FULL VERSION