Datest, смещения и часовые пояса в java

Я пытаюсь понять основную механику временных утилит.

Итак, я сделал следующий пример:

public class Test {
    public static void main(String[] args) {

        System.out.println(Instant.now().getEpochSecond());
        System.out.println(new Date().getTime());
        System.out.println(LocalDateTime.now().atZone(ZoneId.systemDefault()).toEpochSecond());
        System.out.println(LocalDateTime.now().toEpochSecond(ZoneOffset.UTC));

        System.out.println(ZoneId.systemDefault().toString());
    }
}

Выход:

1460651620
1460651620182
1460651620
1460662420
Europe/Helsinki

Мой текущий идентификатор зоны systemDefault: Европа/Хельсинки (+3 часа)
Когда мы создаем new Date(), он имеет отметку времени unix (UTC).

Это моя отправная точка для сравнения печатных результатов.

1. В моем третьем System.out у меня есть LocalDateTime с установленным часовым поясом systemDefault, но вывод на самом деле такой же. Я ожидал большего значения (+3 часа).

2. В четвертой строке вывода у меня есть запутанный результат. Я ожидал такого же значения с new Date().getTime()

Нужна помощь, чтобы понять вывод.


person Alex Silkovsky    schedule 14.04.2016    source источник


Ответы (2)


Любой метод типа getEpochSecond() и toEpochSecond() дает вам количество секунд, прошедших с эпохи 1970-01-01T00:00:00Z, время работает одинаково независимо от часового пояса, поэтому результат будет одинаковым независимо от выбранного часового пояса.

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

person Nicolas Filotto    schedule 14.04.2016

У меня есть LocalDateTime с установленным часовым поясом systemDefault

Нет, не знаешь. Вы начали с LocalDateTime, но затем превратили его в ZonedDateTime. ZonedDateTime фактически представляет собой LocalDateTime с ZoneId и смещением от UTC для устранения неоднозначности.

LocalDateTime не имеет метода toEpochSecond(), потому что он не представляет фиксированный момент времени. Он имеет toEpochSecond(ZoneOffset), потому что он «привязывает» локальную дату/время к фиксированному моменту времени, применяя смещение UTC.

Сравните это с ZonedDateTime, который действительно имеет метод toEpochSecond() без параметров, потому что он представляет фиксированный момент времени с дополнительным контекстом часового пояса. (Вы можете рассматривать ZonedDateTime как Instant с ZoneId, или LocalDateTime с ZoneId и ZoneOffset; они эквивалентны, но лично я предпочитаю последнее понятие.)

Обратите внимание, что ваш код может дать вам другой результат, если вы были в периоде, когда LocalDateTime.now() было неоднозначным из-за перевода часов назад (обычно в конце летнего времени). В этом случае LocalDateTime.atZone выбирает более раннее вхождение этого LocalDateTime, тогда как на самом деле вы можете столкнуться с более поздним вхождением. В этом разница между LocalDateTime.now().atZone(zone) и ZonedDateTime.now(zone) - последний всегда будет правильно "знать" смещение.

person Jon Skeet    schedule 14.04.2016