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

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

Открыта

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)
Вычитает наносекунды

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


Комментарии (230)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Maxim TerletskySoftware Developer в RutiSoft Corporation
1 августа, 11:13
Снова учат гуглить. Что следовало бы дописать в лекции: 1. ZonedDateTime.of() - ручное создание даты/времени с часовым поясом
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class ZonedDateTimeExample {

    public static void main(String[] args) {
        ZoneId moscowZone = ZoneId.of("Europe/Moscow");

        ZonedDateTime moscowTime = ZonedDateTime.of(
                2026, 8, 1, 15, 30, 0, 0, moscowZone
        );
        System.out.println(moscowTime);

        ZonedDateTime moscowFromLocalDateTime = ZonedDateTime.of(
                LocalDateTime.of(2026, 8, 1, 15, 30),
                ZoneId.of("Europe/Moscow")
        );
        System.out.println(moscowFromLocalDateTime);

        ZonedDateTime moscowFromLocalDateAndLocalTime = ZonedDateTime.of(
                LocalDate.of(2026, 8, 1),
                LocalTime.of(15, 30),
                ZoneId.of("Europe/Moscow")
        );
        System.out.println(moscowFromLocalDateAndLocalTime);
    }
}
2. withZoneSameInstant() - конвертация времени между часовыми поясами
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;

public class ZonedDateTimeExample {

    public static void main(String[] args) {
        ZoneId moscowZone = ZoneId.of("Europe/Moscow");
        ZonedDateTime moscowTime = ZonedDateTime.of(
                2026, 8, 1, 15, 30, 0, 0, moscowZone
        );
        System.out.println(moscowTime);

        ZoneId newYorkZone = ZoneId.of("America/New_York");
        ZonedDateTime newYorkTime = moscowTime.withZoneSameInstant(newYorkZone);
        System.out.println(newYorkTime);

        long hoursDiff = ChronoUnit.HOURS.between(moscowTime, newYorkTime);
        System.out.println(hoursDiff);
    }
}
Grigoryvvv
Уровень 28
Expert
14 июля, 14:36
14.07.2026 / 17 уровень Получение ZonedDateTime из LocalDateTime + ZoneId: Есть два основных варианта. 1. Через atZone()
LocalDateTime localDateTime = LocalDateTime.of(2026, 8, 31, 14, 30);

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

ZonedDateTime zonedDateTime = localDateTime.atZone(zone);
Получим: 2026-08-31T14:30+03:00[Africa/Cairo] То есть: LocalDateTime + ZoneId ↓ atZone() ↓ ZonedDateTime 2. Через ZonedDateTime.of() Можно сразу передать три компонента:
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDate, localTime, zone);
Или:
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zone);
Elisbeth
Уровень 30
21 января, 15:05
Слишком уж сжатая лекция, не хватает базовой информации. Окей, методы для получения и изменения аналогичны LocalDateTime, но почему не упомянули о трёх вариациях метода of() конкретно класса ZonedDateTime? Вообще ни одной вариации не привели. Хотя в лекциях по другим классам это писали.
Виктор
Уровень 28
15 сентября 2025, 13:18
Нормальная тема).
Сергей Сак
Уровень 16
22 августа 2025, 17:25
System.out.println(ZoneId.getAvailableZoneIds().size()); // 603
Anonymous #3585174
Уровень 33
19 июля 2025, 13:44
Like
11 июня 2025, 17:57
Найдите мне составителя, руку пожать хочу(нет)
17 августа 2025, 11:56
Составителю не только руку пожать, но и лицо погладить можно🤬. Это нормально вообще, в ответе используются методы atZone и withZoneSameInstant, а в лекции о них ни слова!!!
25 апреля 2025, 13:52
Спасибо, что в лекции добавили полезную информацию про метод withZoneSameInstant() класса ZonedDateTime, который принимает в качестве аргумента ZoneId и возвращает копию даты и времени сохраняя момент. И пример использования:
ZonedDateTime time = ZonedDateTime.of(fromDateTime, fromZone);
ZonedDateTime newTime = time.withZoneSameInstant(toZone);
Podaytesigy
Уровень 20
29 июля 2025, 15:38
Крик души ХД
Riga Android Developer
22 апреля 2025, 09:32
А еще • ZonedDateTime.now используется для получения текущего времени. • ZonedDateTime.of используется для создания объекта ZonedDateTime с конкретными значениями.
Kekosina
Уровень 32
18 февраля 2025, 17:23
Ещё в 10 лекций засуньте табличку с методами getYear minusHour, я же не понял как они работают, а вот методы типа withZoneSameInstant описать в лекции ни к чему, сам загуглю. Мусор информационный
Be_Silent
Уровень 26
22 июня 2025, 07:16
Очевидно, что за несколько последних лекций авторы хотят приучить нас к тому, чтобы мы имели привычку залезать в документацию. И если бы вы не ленились сами туда залезть лишний раз, то поняли бы, что там очень часто существует достаточно длинный список методов. Причем в этой же документации все подробно и расписано. А в лекции дают самые основы. Вы сюда, по идее, не весело и задорно решать задачки пришли, а учиться, не? Так и учитесь тогда, ищите информацию, гуглите, пробуйте, мозг напрягайте. Какой смысл от учебы, если вы один раз повторили то, что в лекции написано было, и быстро побежали дальше?
4el0vek3
Уровень 40
20 июля 2025, 14:10
Проблема в том, что найдёшь решение в интернете, сделаешь задание правильно, а валидатор его не принимает. Приходится лезть в ответы, смотреть, как автор решал, и делать так же. А потом оказывается, что изначальное решение было верным (по крайней мере у меня такое периодически бывает)
Alexey
Уровень 51
3 сентября 2025, 10:48
Давай-давай, оправдывай их лень. Если бы я хотел учиться по документации, я бы не брал этот курс, а шерстил тексты oracle