java.util.Date::toString
применяет зону
Вероятно, вас смущает благонамеренное, но неудачное проектное решение метода java.util.Date::toString
для динамического применения текущего часового пояса JVM по умолчанию при создании строки для представлениязначение Date
, которое на самом деле всегда в UTC по определению.Одна из многих причин избежать этого ужасно неприятного старого класса.
Неправильный тип данных в базе данных
У меня есть поле в postgres, тип которого "отметка времени безчасовой пояс".Время UTC в базе данных, которое я хочу показать в ответе API.
Это противоречие в терминах.Стандартный столбец SQL TIMESTAMP WITHOUT TIME ZONE
не содержит значения UTC.В этом типе данных отсутствует понятие часового пояса или смещения от UTC.(Такие значения UTC должны были бы вместо этого быть сохранены в столбце типа TIMESTAMP WITH TIME ZONE
.)
Возможно, вы вставили значения, которые предназначались для UTC, но вы потеряли этот факт, когда-то сохранялись вбаза данных.
java.time
Избегать java.sql.Timestamp
Существует нет необходимо использовать java.sql.Timestamp
.Этого унаследованного класса следует избегать.Начиная с JDBC 4.2 и более поздних версий, мы можем напрямую обмениваться типами java.time с базой данных. Hibernate поддерживает java.time .
LocalDateTime
При отсутствии какой-либо зоны / смещения вы должны получить эти значения, используя LocalDateTime
класс.В этом классе также отсутствует понятие часового пояса или смещения от UTC.
LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;
OffsetDateTime
Если вы хотите предположить , что полученное значение представляет собоймомент в UTC, примените ZoneOffset
, чтобы получить OffsetDateTime
объект.В частности, для UTC мы можем использовать предопределенную константу ZoneOffset.UTC
.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;
Not ZonedDateTime
В то время как класс ZonedDateTime
будет технически работать здесь, вместо класса OffsetDateTime
, его использование неуместно.
Часовой пояс намного больше, чем смещение.Зона - это история прошлых, настоящих и будущих изменений в смещении, используемом людьми определенного региона.Напротив, смещение от UTC - это просто количество часов и минут, ни больше, ни меньше.
Таким образом, использование ZonedDateTime
в этом контексте UTC вводит в заблуждение и может привести к путанице.
Instant
Теперь в вашем OffsetDateTime
объекте у вас естьмомент в UTC.
Если вы знаете, что оттуда хотите работать только в UTC, извлеките Instant
.Instant
всегда в UTC по определению.Для представления моментов в UTC обычно используйте Instant
.Если вам нужна большая гибкость, например, при генерации строк в различных форматах, переключитесь на использование OffsetDateTime
.
Instant instant = odt.toInstant() ;
О java.time
Среда java.time встроена в Java 8и позже.Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
, & SimpleDateFormat
.
Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .
Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация: JSR 310 .
Вы можете обмениваться java.time объектами напрямую с вашей базой данных.Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии.Нет необходимости в строках, нет необходимости в java.sql.*
классах.
Где получить классы java.time?
ThreeTen-Extra Проект расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти некоторые полезные классы, такие как Interval
, YearWeek
, YearQuarter
и more .