JavaRush /Курси /Java Syntax Zero /Часові пояси

Часові пояси

Java Syntax Zero
Рівень 17 , Лекція 7
Відкрита

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)
Віднімає наносекунди

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


Коментарі (15)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
Aleksey Golovin Рівень 55
1 жовтня 2025
LocalDateTime localDateTime = cairoTime.toLocalDateTime(); !! це не поретворює час десь там на час на вашій машині, це лише відкидає зону, залишаючи час без змін. для цього потрібен метод withZoneSameInstant(toZone); toZone - це часова зона в які ви хочете отримати час
Aleksey Golovin Рівень 55
1 жовтня 2025
"А деякі країни міняють закони і скасовують перехід на літній час або знову вводять, або знову скасовують." І шо то за країни такі? ))
Кирило Рівень 43
24 серпня 2024
Це, насправді, круто що джавараш заставляє нас читати документацію, бо якщо розкладувати всі методи і статичні змінні в лекціях, то виділити найважливіше з них буде нереально, погано інше, те що постійно виникає проблема нерозуміння що робити з кодом, треба використовувати якісь вивчені метод, чи це можно зробити тільки не вивченими.
Olexandr Рівень 1
29 січня 2024
Останню задачу розв'язав майже легко. Ну як розв'язав, Chat GPT все придумав а я вже допиляв під валідатор. Можу сказати одне - то саме пресловуте гуглення для пошуку рішення - перетворилося на спитай ChatGpt та адаптуй відповідь під себе... Не знаю добре це чи ні, і куди це все йде...
Андрій Рівень 18
8 травня 2024
Те саме)
TimpoIngo Рівень 38
11 вересня 2023
Ви теж пишете багато рядків, а потім дивуєтеся наскільки можна було просто написати?🤭
Андрии Бумер Рівень 41
19 вересня 2024
О так)
unite Рівень 24 Expert
8 лютого 2023
навіть напрямок вирішення останньої задачі не вказанив в лекції де шукати withZoneSameInstant? . Так і не зрозумів чому знаючи час мі не можемо одразу визначити його в зоні 2? навіщо зона 1 ?
kalkulator¹ Рівень 51
24 листопада 2022
я зрозумів, що в коментах ніколи не побачу людину з левелом нижче ніж в мене(якщо не вертатися назад звісно)
Bandiu Band Рівень 25
27 вересня 2022
Методи atZone(ZoneId); withZoneSameInstant(ZoneId);
FAUST_ua Рівень 29
26 вересня 2022
Перша задача має бути після частини 2 лекції.
Pavlo Kezin Рівень 23
26 вересня 2023
приєднуюсь
Андрии Бумер Рівень 41
19 вересня 2024
аххах, мені сподобалось таке рішення. Я випадково прочитав другу частину і одразу побачив там відповідь на перше завдання, пощастило. Уже майже напрацьована звичка: якщо одразу не розумієш як зробити, то перед тим як гуглити почитай лекцію далі) яцщо і там рішення нема, тоді впередю Хоча з TreeSet одразу з завдання стало зрозуміло що читати треба саме його))
18 липня 2022
Як завжди методи необхідні для вирішення задачі у лекції не вказані. Мабуть це тренування на головний скіл програміста - пошук...
Roman Рівень 20 Expert
4 серпня 2022
Так, але це ж добре)