Как перевести время в другой часовой пояс
Короткий ответ
Привяжите время к поясу через atZone(), затем withZoneSameInstant() покажет тот же момент в другом поясе:
void main() {
var berlin = LocalDateTime.of(2026, 3, 8, 15, 0).atZone(ZoneId.of("Europe/Berlin"));
var tokyo = berlin.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
IO.println(berlin);
IO.println(tokyo);
}Результат:
2026-03-08T15:00+01:00[Europe/Berlin]
2026-03-08T23:00+09:00[Asia/Tokyo]Из UTC
Время с сервера часто хранится как Instant в UTC. Покажите его пользователю в его поясе:
void main() {
Instant stored = Instant.parse("2026-07-01T12:00:00Z");
var local = stored.atZone(ZoneId.of("America/New_York"));
IO.println(local.toLocalDateTime());
}Результат:
2026-07-01T08:00Летнее время
ZoneId знает о переходах на летнее время. Одинаковое время суток в разные даты даёт разное смещение:
void main() {
var zone = ZoneId.of("Europe/London");
IO.println(LocalDateTime.of(2026, 1, 15, 12, 0).atZone(zone).getOffset());
IO.println(LocalDateTime.of(2026, 7, 15, 12, 0).atZone(zone).getOffset());
}Результат:
Z
+01:00Z означает нулевое смещение от UTC: зимой Лондон живёт по UTC, а летом — на час впереди.
Частая ошибка
Использовать withZoneSameLocal() вместо withZoneSameInstant(). Он оставляет часы как есть и меняет только пояс — получается другой момент времени:
void main() {
var berlin = LocalDateTime.of(2026, 3, 8, 15, 0).atZone(ZoneId.of("Europe/Berlin"));
IO.println(berlin.withZoneSameLocal(ZoneId.of("Asia/Tokyo")));
IO.println(berlin.withZoneSameInstant(ZoneId.of("Asia/Tokyo")));
}Результат:
2026-03-08T15:00+09:00[Asia/Tokyo]
2026-03-08T23:00+09:00[Asia/Tokyo]Функции из этого ответа
- ZonedDateTime — Дата и время в конкретном часовом поясе — с учётом летнего времени.
- Instant — Точный момент времени на временной шкале UTC — для логов, меток времени и замеров.