UnsupportedOperationException - Почему вы не можете вызвать toInstant() в java.sql.Date?
Класс java.util.Date
имеет метод под названием toInstant()
, который преобразует экземпляр Date
в java.time.Instant
.
Класс java.sql.Date
расширяет класс java.util.Date
, но когда я пытаюсь вызвать toInstant()
на java.sql.Date
, я получаю UnsupportedOperationException
.
Почему toInstant()
неподдерживаемая операция на java.sql.Date
?
И каков "правильный" способ преобразования java.sql.Date
в java.time.Instant
?
Ответы
Ответ 1
Проверьте JavaDoc
Поскольку sql.Date
не имеет компонента времени, нет возможности преобразовать его в time.Instant
Этот метод всегда выдает исключение UnsupportedOperationException и должен не используются, поскольку значения SQL Date не имеют компонента времени.
Ответ 2
Правильное отображение между java.sql.Date
и java.time
равно LocalDate
:
LocalDate date = sqlDate.toLocalDate();
Если вам действительно нужно, вы можете получить Instant
, хотя дополнительная информация (время) будет произвольной. Например:
Instant i = date.atStartOfDay(ZoneOffset.UTC).toInstant();
Ответ 3
java.sql.Date поддерживает только дату, месяц и год. Он не поддерживает информацию о времени.
Вот почему java.sql.Date.toInstant() выдает исключение UnsupportedOperationException. Java 8 Instant содержит информацию о дате/времени.
java.util.Date содержит информацию о дате и времени, поэтому java.util.Date.toInstant() работает!
Вы можете сделать следующее:
new java.util.Date(sqlDate.getTime()).toInstant()
Обновлено:
Instant.ofEpochMilli(sqlDate.getTime());
// OR
new java.util.Date(sqlDate.getTime()).toInstant();
Вернет тот же результат, потому что toInstant() вызывает Instant.ofEpochMilli(getTime()) внутри.
public Instant toInstant() {
return Instant.ofEpochMilli(getTime());
}
Ответ 4
В ответах, которые даны до сих пор, сосредоточиться на деталях, в которых java.sql.Date
нет информации о времени. Это правильно, но не реальная или достаточная причина, почему этот тип не может предложить прямое преобразование в Instant
. К сожалению, документация Java-8 делает ту же ошибку, что позволяет пользователям думать, что проблема связана только с отсутствием информации о времени.
Концептуально тип java.sql.Date
представляет локальный тип. Он моделирует календарную дату, которая может быть различной в любом регионе нашего мира. Но Instant
на нашем земном шаре одинаково. Таким образом, пользователям требуется часовой пояс или смещение часового пояса для преобразования.
Трагически, тип java.sql.Date
наследует от java.util.Date
, который является глобальным типом (мгновенным). Однако это наследование действительно означает наследование реализации, а не наследование типов. Еще одна причина для рассмотрения дизайна этих старых классов JDBC. Поэтому действительно можно использовать хак, чтобы обернуть java.sql.Date
с помощью его метода getTime()
внутри экземпляра java.util.Date
, который, наконец, позволяет прямое преобразование в одно мгновение. Но: Это преобразование неявно использует часовой пояс по умолчанию для системы.
Итак, как правильно преобразовать педантичным способом? Рассмотрим снова документацию Java-8, которая здесь указывает на правильное направление:
java.sql.Date sqlDate = ...;
LocalDate calendarDate = sqlDate.toLocalDate();
ZonedDateTime zdt = calendarDate.atStartOfDay(ZoneId.of("Europe/Paris"));
Instant instant = zdt.toInstant();