Java 8 #6: DateTime API – daty i czas

Nowe DateTime API

Nie rzadko w Twojej implementacji będziesz korzystał z danych, które będą wymagać przypisania do nich odpowiednich wartości dat czy czasu. Do JDK w wersji 7 programiści Java byli zmuszeni do korzystania z prostych i mało udanych implementacji zawartych w klasach Date i Calendar. Największe wyzwania jakie stały przed twórcami nowego DateTime API było:

  • stworzenie prostego, przyjaznego API do programisty
  • praca w środowisku wielowątkowym
  • programowanie systemów działających w wielu strefach czasowych

LocalDate vs LocalTime vs LocalDateTime

Wszystkie trzy nowe klasy działają bardzo podobnie. Główną różnicą jest to, że jak sama nazwa wskazuje, jedna z nich odnosi się tylko do daty, następna do czasu, a ostatnia pracuje na wartościach zawierających zarówno czas jak i datę.

Najpierw pokażę Ci co potrafi samo LocalDate.

IntStream stream = IntStream.range(1, 10);
stream.forEach(i -> {
	LocalDate date = LocalDate.of(2010 + i, Month.JANUARY, 1);
	System.out.println(date.getDayOfWeek());
});

Pierwszą ważną kwestią wartą wyjaśnienia jest nowy rodzaj strumieni, omawianych dokładniej w lekcji poprzedniej*. Klasa IntStream umożliwia w łatwy sposób tworzenie strumieni liczb całkowitych. W ten też sposób można wygodnie iterować unikając klasycznej pętli for. W samej pętli forEach, został utworzony obiekt date, który za pomocą metody of(), utworzy instancję klasy LocalDate w zależności od atrybutów, wypełnionych przez Ciebie w konstruktorze (są to odpowiednio: rok, miesiąc, dzień). W moim przypadku będzie to zawsze pierwszy dzień stycznia z zakresu lat 2010 – 2020. Na koniec wyświetlam dzień tygodnia, wykreowanej przeze mnie daty (oczywiście będzie to nazwa anglojęzyczna).

Efekt na konsoli:

SATURDAY
SUNDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SUNDAY
MONDAY
TUESDAY

Teraz pobawię się klasą LocalTime.

LocalTime localTime = LocalTime.now();
System.out.println("Actual time is: " + localTime + ", 10 hours before was: " + localTime.minusHours(10));

Korzystając z metody now() utworzyłem obiekt LocalDate, który reprezentuje aktualną datę w Twoim komputerze. API tej klasy, podobnie jak w poprzednim przykładzie udostępnia wiele przydatnych metod ułatwiających jej manipulację. W moim przykładzie skorzystałem z metody minusHours, aby wyświetlić datę o dziesięć godzin wcześniejszą. Tego typu metod jest o wiele więcej, ale z oczywistych względów nie będę ich wszystkich omawiał. Jeśli chcesz przejrzeć je wszystkie, jak zawsze polecam oficjalną dokumentację**.

Na koniec skorzystam z API LocalDateTime. Jest ono praktycznie takie samo jak w przypadku LocalTime, dlatego w tym przykładzie pokażę Ci inną ciekawą metodę query, dzięki której możesz wyciągać interesujące Cię fragmenty obiektu, poprzez użycie odpowiedniego zapytania.

LocalDateTime localDateTime = LocalDateTime.now();
System.out.println("Actual date is: " + localDateTime.query(TemporalQueries.localDate()));
System.out.println("Actual time is: " + localDateTime.query(TemporalQueries.localTime()));

W tym przypadku skorzystano z gotowych „zapytań” zawartych w klasie pomocniczej TemporalQueries.

ZonedDateTime

Czasami jednak potrzebujesz do pracy konstrukcji pozwalającej na łatwe przetwarzanie aktualnej daty z jednej strefy czasowej do innej. Bardzo sprawnie zadziała tu klasa ZonedDateTime. Pewnym problemem może być wskazanie odpowiedniej nazwy pożądanej strefy czasowej, używanej w konstruktorze. Wynika to z tego, że jak się domyślasz, jest ich naprawdę dużo. Dlatego też do pomocy wykorzystam obiekt ZoneId, za pomocą którego łatwo sprawdzić, które strefy czasowe w jaki sposób zostały nazwane.

ZoneId.getAvailableZoneIds().stream()
        .filter(name -> name.contains("Europe"))
        .map(id -> ZoneId.of(id))
        .forEach(x -> System.out.println(LocalDateTime.now().atZone(x)));

Powyższy kod wyświetli wszystkie strefy czasowe w Europie. Znając nazwy stref czasowych można utworzyć obiekt ZonedDateTime na kilka sposób. Pierwsza opcja to wpisanie danych daty i czasu manualnie, drugą możliwością jest użycie metody now podobnie jak w przypadku klasy LocalDate, trzecią skorzystanie z obiektu LocalDateTime. Ostatnia możliwość to sparsowanie Stringa, zawierającego odpowiednie dane. Jest to o tyle niewdzwięczne zadanie, że jedna literówka doprowadzi do wyrzucenia wyjątku DateTimeParseException.

ZonedDateTime zonedDateTime = ZonedDateTime.of(2021, 07, 31, 21, 31, 0, 0, ZoneId.of("Europe/Warsaw"));
ZonedDateTime zonedDateTimeNow = ZonedDateTime.now(ZoneId.of("Europe/Warsaw"));
ZonedDateTime zonedDateTimeFromLocal = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("Europe/Warsaw"));
ZonedDateTime zonedDateTimeParsed =  ZonedDateTime.parse("2021-07-31T21:31+02:00[Europe/Warsaw]");
		
System.out.println("ZonedDatetime created from of method " + zonedDateTime + 
	"\nzonedDateTimeused now method " + zonedDateTimeNow +
	"\nzonedDateTime created from from localDateTime " + zonedDateTimeFromLocal +
	"\nzonedDateTime parsed from String " + zonedDateTimeParsed);

Samo API ZonedDateTime jest bardzo podobne do API LocalDateTime, także nie będę się nad nim dłużej rozwodził.

Konwersja ze starego zapisu

Czasami niestety będziesz pracować z kodem zastanym, który będzie zawierać datę i kalendarz. Na szczęście konwersja poprzednich obiektów do DateTime API nie stanowi wielkiego problemu.

Calendar calendar = Calendar.getInstance();
Date date =  calendar.getTime();
System.out.println(LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()));
System.out.println(LocalDateTime.ofInstant(calendar.toInstant(), ZoneId.systemDefault()));

To wszystko jeśli chodzi o pracę z datą i czasem w Javie 8+. Co więcej jest to ostatnia lekcja z kursu Java 8. Jeśli tu udało Ci się dotrzeć, to gratuluję! Znasz już najpopularniejszą obecnie wersję JDK.

*Lekcja o Stream API: Java 8 #5: zastosowanie Stream API w przetwarzaniu danych

**Dokumentacja do nowego DateTime API:

https://docs.oracle.com/javase/8/docs/api/java/time/LocalTime.html

https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html

https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html

Kod do lekcji: https://github.com/developeronthego/java-jdk8/tree/master/src/main/java/java8/datetime

Stay in the Loop

Get the daily email from CryptoNews that makes reading the news actually enjoyable. Join our mailing list to stay in the loop to stay informed, for free.

Ostatnio dodane

- Advertisement - spot_img

Powiązane wpisy