Подтвердить что ты не робот

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?

4b9b3361

Ответ 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();