Ответ Оле В.В. правильный. Добавлю несколько мыслей и диаграмму.
Никогда не используйте java.util.Date
Ваш код:
Date now = getTrueNowTimeInGMT ();
Посмотрите, обновлена ли ваша библиотека для java .time . Класс java.util.Date
был вытеснен годами a go с принятием JSR 310 . Вместо этого следует использовать класс java.time.Instant
.
Instant
представляет момент в UT C
После получения объекта Date
немедленно конвертируйте из устаревшего класса в современный класс. Используйте новые методы преобразования, добавленные к старым классам.
Instant instant = myJavaUtilDate.toInstant() ;
Вы сказали:
Я что-то упустил? Я читал в одном сообщении, что метод toInstant () не заботится о часовом поясе.
java.time.Instant
не заботится о часовом поясе, поскольку он всегда представляет момент времени, как видно в UT C, по определению.
- Захват текущего момента через
Instant.now
всегда будет виден в перспективе UT C. - Добавление / вычитание диапазона -время через
Instant::plus
и Instant::minus
всегда будет в UT C и будет включать общие c 24-часовые дни UT C времени, которые не встречаются с аномалиями политического времени, такими как Летнее время (DST) .
Отсчет от эталона эпохи
Оба этих класса, устаревшие и современные, представляют момент в UT C. Оба внутренне ведут счет времени с первого момента 1970 года в UT C, 1970-01-01T00: 00Z. Instant
использует более точное разрешение наносекунд в своем отсчете по сравнению с миллисекундами в Date
.
Очевидно, вам нужно подсчет миллисекунд с 1970-01-01T00: 00Z.
long millisSinceEpoch = instant.toEpochMilli() ;
И снова.
Instant instant = Instant.ofEpochMilli( millisSinceEpoch ) ;
Я не рекомендую отслеживать время как счет. Такой подсчет по своей сути неоднозначен для человеческого читателя и может быть ошибочным или неверным. Я настоятельно рекомендую вместо этого использовать стандартные строки ISO 8601 для передачи значения даты и времени.
String output = instant.toString() ;
И снова.
Instant instant = Instant.parse( input ) ;
![Table of all date-time types in Java, both modern and legacy](https://i.stack.imgur.com/WyAl2.png)
ZonedDateTime
You said:
How can I get the milliseconds from the specific time zone I pointed out in ZonedDateTime?
A ZonedDateTime
object represents a moment as seen through the wall-clock time used by people of a particular region. Imagine two people talking on a long-distance phone call, one on the west coast of US, and one in Tunis Tunisia.
Capture the moment when their call started.
Instant callStartedUtc = Instant.now() ;
When the person in US glanced at a clock on their wall as they dialed their phone, what time did they see?
ZonedDateTime zdtLosAngeles = callStartedUtc.atZone( ZoneId.of( "America/Los_Angeles" ) ) ;
When the person in Tunisia glanced at a clock hanging on their wall as they picked up their phone to answer, what time did they see?
ZonedDateTime zdtTunis = callStartedUtc.atZone( ZoneId.of( "Africa/Tunis" ) ) ;
Three objects all representing the very same simultaneous moment. You can extract a Instant
object from both ZonedDateTime
objects.
Instant instant = zdtLosAngeles.toInstant() ;
These will all be equal. In this example code, eq
will be true
.
boolean eq =
callStartedUtc.equals( zdtLosAngeles.toInstant() )
&&
callStartedUtc.equals( zdtTunis.toInstant() )
;
All three internally have the very same count from epoch reference.
UTC as The One True Time
Tip: Learn to think in terms of UTC while on the job programming or doing sysadmin work. Think of UTC as the One True Time, with time zones being mere variations.
Do not translate back-and-forth in your head, just stick with UTC. Like learning a foreign language, constant translation in your head will drive you batty.
Exchanging date-time values between programs or systems, logging, debugging, and such should all be done in UTC. I suggest keeping a 2nd clock on your desk set to UTC.
LocalDateTime
is not a moment
You said:
// I like to use LocalDateTime
, so I am converting Date
to LocalDateTime
:
LocalDateTime ldtOfSystem = LocalDateTime.ofInstant(now.toInstant(), ZoneId.systemDefault());
You should not "like" LocalDateTime
. That class cannot represent a moment. It holds a date and a time-of-day, but lacks the context of a time zone or offse-from-UTC. So it may say "noon on the 23rd of January 2021" but we have no idea if that means noon in Tokyo Japan, noon in Toulouse France, or noon in Toledo Ohio US — all very different moments, several hours apart.
Whenever you are tracking a moment, a specific point on the timeline, you cannot use LocalDateTime
. Instead use Instant
(for UTC), OffsetDateTime
(for an offset-from-UTC, a number hours-minutes-seconds), or ZonedDateTime
(for a time zone, in Continent/Region
name, such as Europe/Paris
).
When in doubt, do not use LocalDateTime
. I find most of the time in business apps, we are tracking a specific moment. The big exception is when booking future events, such as appointments, where LocalDateTime
is needed.
Search to learn more as this has been covered many many times already on Stack Overflow. For example, Что такое разница между Instant и LocalDateTime? .
Сервер времени
Вы сказали:
Уточнение. Почему мне нужно время UT C?
Полагаю, вы действительно хотели сказать: «Почему мне нужно получать текущий момент от доверенного удаленного сервера времени? ". Если да, я прошу вас отредактировать свой вопрос для ясности.
Это законная потребность. Если локальным часам нельзя доверять и у вас должно быть значение, близкое к текущему моменту, вы действительно должны обращаться к доверенному серверу времени, если он доступен.
Термин UTC
на самом деле не является актуально здесь. Сервер времени, скорее всего, вернет значение в единицах UT C. Но нахождение в UT C не имеет ничего общего с локальным или удаленным источником времени.
GMT по сравнению с UT C
Вы сказали:
Мне нужно преобразовать эту дату, которая является GMT, в UT C
Нет, почти наверняка вы этого не сделаете.
Точные определения GMT и различных видов UT C является длинным, сложным, академическим c и спорным практически для всех программистов.
С точки зрения обычных бизнес-приложений, таких как бухгалтерский учет и рабочий процесс, вы можете рассмотреть GMT и UT C быть синонимами. Разница буквально меньше секунды. И часы по умолчанию, используемые Java, действительно игнорируют эту разницу.
Если вы не работаете с ракетной телеметрией, спутниками GPS / Galileo или часами atomi c, вам действительно не нужно заботиться о GMT и UT C.
Более того, в вашем случае использования удаленного сервера времени, GMT по сравнению с UT C еще менее применимо, так как полученное значение теряет значительное время при прохождении по сети (сетям).