1. Клас ZonedDateTime

Є ще один дуже цікавий клас у Date Time API — клас ZonedDateTime. Його основне призначення — зручна робота з датами в різних часових поясах.

LocalDate чудово підходить для опису дат, як-от дня народження: мій день народження — 15 березня, незалежно від того, де я перебуваю. Це приклад дати.

LocalTime чудово підходить для опису часу, наприклад, будильника: я завів будильник на 5 ранку, і не має значення, де я перебуваю. 5 ранку — це 5 ранку. Це приклад роботи з часом.

А тепер припустімо, що ми пишемо програму, яка бронює авіаквитки. Літаки злітають і сідають за місцевим часом, літак летить протягом фіксованого часу, але часові пояси змінюються.

Часові зони

До речі, з часовими зонами (часовими поясами) у світі — справжній безлад. Ба більше, якщо ви думаєте, що часових поясів 24, ви дуже помиляєтеся.

Наприклад, час в Індії відрізняється від часу за Гринвічем на 5 із половиною годин: GMT+5:30. Одні країни переходять на літній час, інші — ні. Причому різні країни переходять на літній час за різними графіками.

А деякі країни міняють закони і скасовують перехід на літній час або знову вводять, або знову скасовують.

Загалом, у світі є часові зони, і всередині кожної зони — свій час. Час у різних зонах у певні періоди року може збігатися, а в інші періоди відрізнятися. Назви зон зазвичай походять від назв великих міст, які в них розташовані: Europe/Monaco, Asia/Singapore, хоча є й винятки — US/Pacific.

Усього на даний момент офіційно відомо 599 часових зон. Вдумайтеся. 599. Це зовсім не 24. Ласкаво просимо в глобальний світ!

Для зберігання часової зони в Java використовується клас ZoneId із пакету java.time.

До речі, цей клас має статичний метод getAvailableZoneIds(), який повертає множину всіх відомих на поточний момент часових зон. Щоб отримати список усіх зон, слід написати такий код:

Код Виведення на екран (частина)
for (String s: ZoneId.getAvailableZoneIds())
   System.out.println(s);
Asia/Aden
America/Cuiaba
Etc/GMT+9
Etc/GMT+8

Щоб отримати об'єкт ZoneId за його іменем, слід скористатися статичним методом of();

Код Примітка
ZoneId zone = ZoneId.of("Africa/Cairo");
Каїр


2. Створення об'єкта ZonedDateTime

Під час створення об'єкта ZonedDateTime потрібно викликати для нього статичний метод now() й передати в нього об'єкт ZoneId.

Код Виведення на екран
ZoneId zone = ZoneId.of("Africa/Cairo");
ZonedDateTime time = ZonedDateTime.now(zone);
System.out.println(time);


2019-02-22T11:37:58.074816+02:00[Africa/Cairo]

Якщо в метод now() не передати об'єкт ZoneId (а так можна), часову зону буде визначено автоматично: на основі настройок комп'ютера, на якому виконується програма.

Приклад:

Код Виведення на екран
ZonedDateTime time = ZonedDateTime.now();
System.out.println(time);

2019-02-22T13:39:05.70842+02:00[Europe/Helsinki]

Перетворення глобальної дати на локальну

Однією з цікавих особливостей ZonedDateTime є можливість його перетворення на локальні дату й час. Приклад:

ZoneId zone = ZoneId.of("Africa/Cairo");
ZonedDateTime cairoTime = ZonedDateTime.now(zone);

LocalDate localDate = cairoTime.toLocalDate();
LocalTime localTime = cairoTime.toLocalTime();
LocalDateTime localDateTime = cairoTime.toLocalDateTime();

3. Робота з часом

Як і клас LocalDateTime, клас ZonedDateTime має багато способів (методів) отримання окремих фрагментів дати й часу. Наводимо список цих методів:

int getYear()
Повертає рік із конкретної дати
Month getMonth()
Повертає місяць дати: одну зі спеціальних констант JANUARY, FEBRUARY, …;
int getMonthValue()
Повертає номер місяця з дати. Січень == 1
int getDayOfMonth()
Повертає номер дня в місяці
DayOfWeek getDayOfWeek()
Повертає день тижня: одну зі спеціальних констант MONDAY, TUESDAY, …;
int getDayOfYear()
Повертає номер дня в році
int getHour()
Повертає години
int getMinute()
Повертає хвилини
int getSecond()
Повертає секунди
int getNano()
Повертає наносекунди

Усі методи повністю аналогічні методам LocalDateTime. І, звичайно, клас ZonedDateTime має методи, що дають змогу працювати з датою й часом. Причому об'єкт, для якого викликають методи, не змінюється — натомість методи повертають новий об'єкт ZonedDateTime:

Методи Опис
plusYears(int)
Додає роки до дати
plusMonths(int)
Додає місяці до дати
plusDays(int)
Додає дні до дати
plusHours(int)
Додає години
plusMinutes(int)
Додає хвилини
plusSeconds(int)
Додає секунди
plusNanos(int)
Додає наносекунди
minusYears(int)
Віднімає роки від дати
minusMonths(int)
Віднімає місяці від дати
minusDays(int)
Віднімає дні від дати
minusHours(int)
Віднімає години
minusMinutes(int)
Віднімає хвилини
minusSeconds(int)
Віднімає секунди
minusNanos(int)
Віднімає наносекунди

Приклади не наводимо: на нашу думку, тут і без того все зрозуміло за аналогією до щойно розглянутих класів.