JSR 310:: System.currentTimeMillis() vs Instant.toEpochMilli():: TimeZone
Не могли бы вы пролить свет на то, как получить правильное время эпохи в миллисекундах для системного часового пояса по умолчанию и заданного часового пояса.
Учитывая
1. Часовой пояс: GMT + 3
2. Следующий фрагмент кода:
import java.time.*;
public class Main {
public static void main(String[] args) {
System.out.println(LocalDateTime
.now()
.atZone(ZoneOffset.UTC)
.toInstant()
.toEpochMilli()
);
System.out.println(LocalDateTime
.now()
.atZone(ZoneOffset.of("+3"))
.toInstant()
.toEpochMilli()
);
System.out.println(System.currentTimeMillis());
}
}
3. Выход:
1444158955508
1444148155508
1444148155508
4. JavaDoc для System.currentTimeMillis(), который сообщает, что возвращаемое значение будет разницей, измеренной в миллисекундах, между текущим временем и полночью, 1 января, 1970 UTC.
Итак, почему
- вывод
LocalDateTime
at GMT+3
такой же, как и для System.currentTimeMillis()
, хотя в документах для System.currentTimeMillis()
упоминается UTC
?
- вывод
LocalDateTime
at UTC
отличается от System.currentTimeMillis()
, хотя в документах для System.currentTimeMillis()
упоминается UTC
?
Ответы
Ответ 1
Оба System.currentTimeMillis()
и Instant.toEpochMilli()
возвращают число миллисекунд с эпохи Unix. Это не "в каком-либо конкретном часовом поясе", хотя эпоха Unix обычно выражается как "полночь 1 января 1970 года, UTC". Но мгновение - это всего лишь мгновение во времени и такое же, как в часовом поясе, в котором вы находитесь, - но это будет отражать другое местное время.
Вывод LocalDateTime.atZone(UTC)
отличается тем, что вы говорите "Возьмите локальную дату и время и преобразуйте его в одно мгновение, как если бы это было в часовом поясе UTC" - даже если вы создали этот LocalDateTime
, вы сделал это неявно в часовом поясе UTC + 3... почему он "неправильный".
LocalDateTime.now()
берет локальную дату и время в часовом поясе системы по умолчанию. Поэтому, если ваш часовой пояс UTC + 3, текущий момент времени равен 2015-10-06T16: 57: 00Z, то LocalDateTime.now()
вернется .2015-10-06T19:57:00
. Позвольте называть это localNow
...
So localNow.atZone(ZoneOffset.of("+3"))
вернет a ZonedDateTime
, представляющий 2015-10-06T19: 57: 00 + 03 - другими словами, ту же локальную дату/время, но "зная", что это на 3 часа раньше UTC.. поэтому toInstant()
вернет Instant
, представляющий 2015-10-06T16: 57: 00Z. Отлично - у нас все еще есть текущая дата/время.
Но localNow.atZone(ZoneOffset.UTC)
вернет ZonedDateTime
, представляющий 2015-10-06T19: 57: 00Z - другими словами, ту же локальную дату/время, но "думая", что это уже в UTC... так toInstant()
вернет Instant
, представляющий 2015-10-06T19: 57: 00Z.., который не является текущим временем (он через три часа).
Ответ 2
Краткая версия:
LocalDateTime → Instant
вычислить LocalDateTime → Instant
, вам нужно указать часовой пояс. С ZonedDateTime
вы получаете ZonedDateTime
и можете вычислять ZonedDateTime → Instant
Instant == System.currentTimeMillis()
если часовой пояс ZonedDateTime равен системному часовому поясу по умолчанию.
Длинная версия:
LocalDateTime - это время на ваших часах (плюс информация о дате). Этого недостаточно, если вы не сообщите нам, в каком часовом поясе вы находитесь. 13:00 часов в Токио не то же самое, как в 13:00 часов в Париже.
Когда вы добавите часовой пояс в свой LocalDateTime, вы получите ZonedDateTime, и мы сможем узнать, в какой момент времени вы на самом деле. Например, вы в 13:00 в Токио или в Париже?
Чтобы получить правильное мгновение, часовой пояс ZonedDateTime должен быть правильным. Если в Токио 13:00 часов, но вы утверждаете, что у вас 13:00 часов в Париже, вы получите неточное мгновение.
LocalDateTime:
Он не может представлять мгновение на временной линии без дополнительной информации, такой как смещение или временная зона.
ZonedDateTime:
Этот класс обрабатывает преобразование из локальной временной линии LocalDateTime в мгновенную линию Instant. Разница между двумя временными линиями - это смещение от UTC/Greenwich, представленное ZoneOffset.
Чтобы получить мгновенный доступ, вам необходимо сначала преобразовать LocalDateTime в ZonedDateTime. Если вы сделали это правильно (указав правильный часовой пояс), ваш Мгновенный будет согласен с System.currentTimeMillis().
System.currentTimeMillis():
разница, измеренная в миллисекундах, между текущим временем и полночью, 1 января 1970 г. UTC.
- вывод LocalDateTime в GMT + 3 такой же, как у System.currentTimeMillis(), хотя в документах для System.currentTimeMillis() упоминается UTC?
Если ваш часовой пояс GMT + 3, то ZonedDateTime.toInstant() предоставит вам правильный Мгновенный и, следовательно, согласен с System.currentTimeMillis()
- выход LocalDateTime в UTC отличается от System.currentTimeMillis(), хотя документы для System.currentTimeMillis() упоминают UTC?
Если ваш часовой пояс не UTC, тогда ZonedDateTime.toInstant() даст вам неправильный Мгновенный.