Преобразование даты Java в OffsetDateTime - PullRequest
0 голосов
/ 03 октября 2018

У меня есть значение eta, которое является OffsetDateTime, и у меня есть запланированная дата, которая является типом Date.Если эта дата не установлена, я хочу вернуться к дате.

Примером даты является Tue Jul 21 10:32:28 PDT 2020.Чтобы преобразовать это, я попытался сделать: OffsetDateTime.ofInstant(dto.getScheduledTime().ToInstant(), ZoneOffset.UTC) Такое ощущение, что смещение utc неверно, поскольку в Date уже есть PDT, но в то же время это также не timezoneId, как "America / Los_Angeles".

Я немного запутался, как справиться с этим.

1 Ответ

0 голосов
/ 04 октября 2018

tl; dr

OffsetDateTime target , eta ;   // Modern java.time class.
java.util.Date scheduledDate ;  // Terrible legacy class.


if( Objects.isNull( eta ) ) {   // If no eta, fall back to scheduledDate.
    target = scheduledDate.toInstant().atOffset( ZoneOffset.UTC ) ; // Never use legacy class `java.util.Date` -- when encountered, immediately convert to modern `java.time.Instant`. 
} else {  // Else not null.
    target = eta ;
}
return target ;

Лучше полностью избегать java.util.Date.При обнаружении немедленно преобразуйте в современный класс Instant и забудьте все об объекте Date.

OffsetDateTime target, eta, scheduled ;
scheduled = incomingJavaUtilDate.toInstant().atOffset( ZoneOffset.UTC ) ;

target = Objects.isNull( eta ) ? scheduledDate : eta ;  // Ternary operator. Short way of saying: If eta is null, go with scheduledDate, otherwise go with eta. 
return target ;

Date::toString ложь вам

Во-первых, поймите, что java.util.Dateпредставляет момент в UTC, всегда в UTC .Тем не менее, его метод toString имеет благие намерения, потому что ужасно запутывает анти-функцию динамического применения текущего часового пояса JVM по умолчанию.Это создает ложное впечатление, что Date имеет часовой пояс, когда на самом деле он не .

Избегайте устаревших классов даты и времени

Во-вторых, вам не нужнои трагически смешивать очень хорошие современные java.time классы (OffsetDateTime) с ужасно ужасными унаследованными классами даты и времени (Date).Не делайте этого.Избегайте старых классов полностью.Они были устаревшими в результате принятия JSR 310 еще в 2014 году.

table of date-time classes in Java, both legacy and modern

Использование java.time

Если вручен объект java.util.Date, немедленно преобразуйте в java.time .Вызовите новые методы преобразования, добавленные к старым классам.Класс Instant прямо заменяет Date как момент в UTC, но с более высоким разрешением наносекунд по сравнению с миллисекундами.

Instant instant = myJavaUtilDate.toInstant() ;  // Convert from legacy class to modern class.

Обычно вы должны отслеживать моменты в UTC.Вы можете сделать это как Instant или как OffsetDateTime со смещением, равным ZoneOffset.UTC константе.

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;  // Same moment, no change in meaning whatsoever. 

Специально для UTC здесь нет разницы между instant и odt в нашем коде.Они оба представляют момент в UTC.Разница в том, что OffsetDateTime (a) может содержать альтернативное значение смещения от UTC (часы-минуты-секунды), а (b) является более гибким, например генерировать текст в форматах, отличных от стандартного ISO 8601.

Поймите, что смещение от UTC - это просто количество часов, минут и секунд.Ничего более.A часовой пояс , напротив, на намного больше.Часовой пояс - это история прошлых, настоящих и будущих изменений в смещении, используемом людьми определенного региона.Например, люди в регионе, использующие America/Los_Angeles часовой пояс, меняют свое смещение от UTC два раза в год в глупой практике, известной как Летнее время (DST) , переходящей с -08: 00 на -07: 00 и обратно.

Так что обычно часовой пояс предпочтительнее простого смещения.Например, чтобы увидеть ваше Date, которое мы превратили в Instant через настенное время, используемое большинством людей на западном побережье США, примените часовой пояс America/Los_Angeles (ZoneId) к Instantчтобы получить ZonedDateTime.

ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

Вы можете вернуться в UTC, извлекая Instant.

Instant instant = zdt.toInstant() ;

И оттуда вернитесь к java.util.Date (если необходимо, иначе избегайте).

java.util.Date d = java.util.Date.from( instant ) ;

На самом деле,java.time.Date класс имеет часовой пояс, скрытый глубоко внутри.Не имея каких-либо методов доступа (получить / установить), он недоступен.Его поведение не имеет отношения к нашему обсуждению здесь.Смешение?Да.Еще одна из многих причин избегать ужасных устаревших классов даты и времени.

...