JavaRush /Курсы /Java Syntax Pro /Часовые пояса

Часовые пояса

Java Syntax Pro
16 уровень , 6 лекция
Открыта

1. Класс ZonedDateTime

Есть еще один очень интересный класс в Date Time API — класс ZonedDateTime. Основное его назначение — удобно работать с датами в разных часовых поясах.

LocalDate отлично подходит для описания дат. Например, дня рождения: у меня день рождения 15 марта независимо от того, где я нахожусь. Это пример даты.

LocalTime отлично подходит для описания времени, например, будильника: я завел будильник на 5 утра и все равно, где я нахожусь. 5 утра — это 5 утра. Это пример работы с временем.

А теперь допустим, что мы пишем приложение, которое бронирует авиабилеты. Самолеты взлетают и прилетают по местному времени, самолет летит фиксированное время, но часовые пояса меняются.

Временные зоны

Кстати, с временными зонами (часовыми поясами) в мире настоящий бардак. Более того, если вы думаете, что часовых поясов 24, вы сильно ошибаетесь.

Например, время в Индии отличается от Гринвича на 5 c половиной часов: 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)
Вычитает наносекунды

Примеры приводить не будем: думаем, тут и так все понятно по аналогии с только что рассмотренными классами.


Комментарии (232)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Виктор Уровень 21
15 сентября 2025
Нормальная тема).
Сергей Сак Уровень 16
22 августа 2025

System.out.println(ZoneId.getAvailableZoneIds().size()); // 603
Anonymous #3585174 Уровень 33
19 июля 2025
Like
Рафиль Касимов Уровень 26
11 июня 2025
Найдите мне составителя, руку пожать хочу(нет)
17 августа 2025
Составителю не только руку пожать, но и лицо погладить можно🤬. Это нормально вообще, в ответе используются методы atZone и withZoneSameInstant, а в лекции о них ни слова!!!
25 апреля 2025
Спасибо, что в лекции добавили полезную информацию про метод withZoneSameInstant() класса ZonedDateTime, который принимает в качестве аргумента ZoneId и возвращает копию даты и времени сохраняя момент. И пример использования:

ZonedDateTime time = ZonedDateTime.of(fromDateTime, fromZone);
ZonedDateTime newTime = time.withZoneSameInstant(toZone);
Podaytesigy Уровень 20
29 июля 2025
Крик души ХД
Riga Уровень 17
22 апреля 2025
А еще • ZonedDateTime.now используется для получения текущего времени. • ZonedDateTime.of используется для создания объекта ZonedDateTime с конкретными значениями.
Kekosina Уровень 21
18 февраля 2025
Ещё в 10 лекций засуньте табличку с методами getYear minusHour, я же не понял как они работают, а вот методы типа withZoneSameInstant описать в лекции ни к чему, сам загуглю. Мусор информационный
Be_Silent Уровень 26
22 июня 2025
Очевидно, что за несколько последних лекций авторы хотят приучить нас к тому, чтобы мы имели привычку залезать в документацию. И если бы вы не ленились сами туда залезть лишний раз, то поняли бы, что там очень часто существует достаточно длинный список методов. Причем в этой же документации все подробно и расписано. А в лекции дают самые основы. Вы сюда, по идее, не весело и задорно решать задачки пришли, а учиться, не? Так и учитесь тогда, ищите информацию, гуглите, пробуйте, мозг напрягайте. Какой смысл от учебы, если вы один раз повторили то, что в лекции написано было, и быстро побежали дальше?
4el0vek3 Уровень 36
20 июля 2025
Проблема в том, что найдёшь решение в интернете, сделаешь задание правильно, а валидатор его не принимает. Приходится лезть в ответы, смотреть, как автор решал, и делать так же. А потом оказывается, что изначальное решение было верным (по крайней мере у меня такое периодически бывает)
Alexey Уровень 28
3 сентября 2025
Давай-давай, оправдывай их лень. Если бы я хотел учиться по документации, я бы не брал этот курс, а шерстил тексты oracle
Денис Кокшаров Уровень 32
10 февраля 2025
известных зон уже 603
Lizzka Уровень 24
3 февраля 2025
Перевод времени из одной таймзоны в другую - withZoneSameInstant(zoneId)
Максим Антонов Уровень 27
8 января 2025
ребятки как вам ошибка ZoneRulesException