2016-09-01 24 views
0

Я пытаюсь сохранить java.util.Date из приложения в базу данных SQL Server с помощью JDBC.Преобразование java.util.Date в java.sql.Date усекает временную часть

Когда я конвертирую java.util.Date в java.sql.Date, используя нижеприведенный метод, он обрезает часть времени.

java.sql.Date javaSqlExpiryDate = new java.sql.Date(javaUtilExpiryDate.getTime()); 
System.out.println("javaUtilExpiryDate: " + javaUtilExpiryDate.toString()); 
System.out.println("javaSqlExpiryDate: " + javaSqlExpiryDate.toString()); 

окно Console сообщает вывод, как:

javaUtilExpiryDate: Чт 1 сентября 18:19:08 IST 2016

javaSqlExpiryDate: 2016-09-01

Как мне заставить его сохранить часть времени?

+1

Вам действительно нужно его преобразовать, если потерять часть времени не то, что вы хотите? Почему бы не использовать java.util.Date прямо в вызове jdbc? – stenix

+0

@stenix Я проверил перегрузки метода 'PreparedStatement.setDate()', и ни один из них, похоже, не хочет 'java.util.Date'. Все они работают с типами 'java.sql. *'. –

+0

FYI, вы используете неприятные старые устаревшие классы времени. Теперь вытесняется классами [java.time] (http://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html). В JDBC 4.2 и более поздних версиях вы можете передавать/извлекать объекты java.time напрямую с помощью методов 'setObject' и' getObject', не переходя типов java.sql. Если нет, найдите новые методы преобразования, добавленные в старые классы. –

ответ

6

Да, это ожидаемое и документально поведение.

Quote from the JavaDocs

Для того, чтобы соответствовать определению SQL DATE, значение миллисекунды, завернутое экземпляром java.sql.Date должно быть «нормализовано» путем установки часов, минуты, секунды и миллисекунд до нуля в конкретном часовом поясе, с которым связан экземпляр.

Если вы хотите сохранить время, вам нужно использовать java.sql.Timestamp (особенно, если столбец в базе данных определяется как datetime).

+0

Спасибо. Я использую JDBC 'PreparedStatement' для параметризации SQL. Этот парень нуждается в 'java.sql.Date', так как я могу получить из java.sql.Timestamp' в' java.sql.Date'? –

+0

@ WaterCoolerv2 Вы не можете. У вас ** есть ** для использования 'java.sql.Timestamp' и' PreparedStatement.setTimestamp() ' –

+0

Да, спасибо. Я просто это видел. Еще 6 минут, прежде чем я могу отметить это как правильный ответ. –

0

Просто измените свой импорт из java.sql.Date TO java.sql.Timestamp

+0

Я думаю, вы сделали это наоборот. Мне нужно 'java.sql.Date' * от * a' java.util.Date'. –

+0

Извините, я получил ваш вопрос неправильно. См. Обновленный ответ – Amy

0

Т.Л., д-р

myPreparedObject.setObject(
    1 , 
    myJavaUtilDate.toInstant() // Convert legacy object to modern java.time object, `Instant`. 
) 

Подробности

Другие ответы правильны. Класс java.util.Date представляет дату и время в UTC. java.sql.Date представляет собой только дату, без времени суток. Ну, на самом деле, java.sql.Dateпретендует на то, что представляет только дату, но фактически, как плохо разработанный подкласс, подклассы класса java.util.Date и, следовательно, имеет время суток. Смешение? Да. Одна из многих причин избежать этих ужасных старых классов наследия.

Теперь у нас есть лучший способ - классы java.time.

java.time

В прежние времена вы бы преобразовать java.util.Date объект в java.sql.Timestamp.

Теперь с помощью JDBC driver, поддерживающего JDBC 4.2 и более поздние версии, вы можете отправлять свои объекты java.time непосредственно в/из базы данных. Не нужно ни для классов java.util, ни для java.sql, просто придерживайтесь классов java.time.

Если вам нужно связать старый код с помощью java.util.Date, конвертировать в java.time.Instant, используя новые методы, добавленные в старые классы.

Instant класса представляет момент на временной шкале в UTC с разрешением nanoseconds (до девяти (9) цифр десятичной дроби).

Instant instant = myJavaUtilDate.toInstant() ; 

обмениваются Instant с базой данных через PreparedStatement::setObject и ResultSet::getObject.

myPreparedStatement.setObject(… , instant) ; 

И ...

Instant instant = myResultSet.getObject(… , Instant.class) ; 

Чтобы увидеть этот момент через какой-то другой часовой пояс, чем UTC, применить ZoneId получить ZonedDateTime.

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

О java.time

java.time каркас встроен в Java 8 и более поздних версий. Эти классы вытесняют неприятные старые legacy классы времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Проект Joda-Time, в настоящее время в maintenance mode, советует перейти на классы java.time.

Чтобы узнать больше, см. Oracle Tutorial. И поиск Stack Overflow для многих примеров и объяснений. Спецификация: JSR 310.

Где получить классы java.time?

  • Java SE 8, Java SE 9, а затем
    • Встроенный.
    • Часть стандартного Java API с объединенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть функциональности java.time будет обратно портирован на Java 6 & 7 в ThreeTen-Backport.
  • Android

ThreeTen-Extra Проект расширяет java.time с дополнительными классами. Этот проект является доказательством возможных будущих дополнений к java.time.Здесь вы можете найти полезные классы, такие как Interval, YearWeek, YearQuarter и more.

Смежные вопросы