Разница между классом Date в пакете java.util и пакете java.sql - PullRequest
8 голосов
/ 14 марта 2011

В java оба пакета java.util и java.sql содержат класс Date. В чем разница между ними?

Если в Java присутствует один класс Date, то чтонужен другой класс Date?

Ответы [ 5 ]

16 голосов
/ 14 марта 2011

С JavaDoc java.sql.Date:

Тонкая оболочка вокруг значения в миллисекундах, позволяющая JDBC идентифицировать его как значение SQL DATE.Значение в миллисекундах представляет количество миллисекунд, прошедших с 1 января 1970 года 00: 00: 00.000 GMT.

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

Объяснение: A java.util.Date представляетдата и время дня, java.sql.Date представляет только дату (дополнение к java.sql.Date - java.sql.Time, которое представляет только время суток, но также расширяет java.util.Date).

4 голосов
/ 02 июня 2016

Эти ответы кажутся частично устаревшими.

Я только что прочитал небольшой API-код (Java версии 1.8.0_91) и нашел его в java.sql.Date:

/**
 * Creates a date which corresponds to the day determined by the supplied
 * milliseconds time value {@code theDate}.
 *
 * @param theDate
 *            a time value in milliseconds since the epoch - January 1 1970
 *            00:00:00 GMT. The time value (hours, minutes, seconds,
 *            milliseconds) stored in the {@code Date} object is adjusted to
 *            correspond to 00:00:00 GMT on the day determined by the supplied
 *            time value.
 */
public Date(long theDate) {
    super(normalizeTime(theDate));
}

/*
 * Private method which normalizes a Time value, removing all low
 * significance digits corresponding to milliseconds, seconds, minutes and
 * hours, so that the returned Time value corresponds to 00:00:00 GMT on a
 * particular day.
 */
private static long normalizeTime(long theTime) {
    return theTime;
}

Метод нормализации времени все еще существует, и даже в комментарии говорится, что время будет нормализовано до 00:00:00 по Гринвичу, но оно ничего не делает. По какой-то причине они удалили нормализацию, что означает, что java.sql.Date содержит точно так же, как java.util.Date только количество миллисекунд с 1.1.1970. Таким образом, есть компонент времени, но он не отображается снаружи.

Например код

java.util.Date utilDate = new java.util.Date();
java.sql.Date sqlDate = new java.sql.Date(Calendar.getInstance().getTimeInMillis())

System.out.println(utilDate);
System.out.println(sqlDate);

производит вывод

Thu Jun 02 13:17:35 CEST 2016
2016-06-02

Так что будьте осторожны с датами sql и не обрабатывайте их, как если бы они просто содержали дату и не содержали информацию о времени. Например:

java.sql.Date sqlDate1 = new java.sql.Date(Calendar.getInstance().getTimeInMillis());
java.sql.Date sqlDate2 = new java.sql.Date(Calendar.getInstance().getTimeInMillis());

System.out.println(sqlDate1);
System.out.println(sqlDate2);
System.out.println(sqlDate1.equals(sqlDate2));
System.out.println(sqlDate1.toString().equals(sqlDate2.toString()));

печать:

2016-06-02
2016-06-02
false
true
2 голосов
/ 14 марта 2011

Java.util.Date - это универсальный универсальный объект Date. Он хранит дату (как длинную) и позволяет отображать ее.

java.sql.Date расширяет java.util.Date. Основное отличие состоит в том, что java.sql.Date не имеет компонента времени.

1 голос
/ 20 июня 2016

Старый

java.util.Date

Класс java.util.Date является частью старых классов даты и времени, которые оказались плохо спроектированными, запутанными и неприятными. Цель состоит в том, чтобы представить момент ( дата и время дня ) на временной шкале.

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

java.sql.Date

java.sql.Date усугубляет плохую ситуацию, представляя значение только для даты (что подразумевается под «DATE» в мире баз данных SQL ) но сделал это как хак, расширив java.util.Date. Но вы должны притворяться, что это , а не подкласс, как указано в классе документа. Кроме того, у него есть время суток, но он делает вид, что не настраивается на первый момент дня в UTC . Запутанный беспорядок.

И еще одна вещь ... класс java.sql.Date добавляет доли секунды с разрешением наносекунд . Это выходит за рамки разрешения миллисекунд , используемого java.util.Date. Многие базы данных поддерживают более точное разрешение, например микросекунда или наносекунда.

Таким образом, в этих старых классах даты и времени невозможно по-настоящему представить значение только для даты без времени суток и часового пояса.

Новый

На помощь приходит фреймворк java.time . Вдохновлен успешным проектом Joda-Time . Встроенный в Java 8 и позже. Back-портирован на Java 6 & 7 , а далее адаптирован под Android . См. Oracle Tutorial .

Instant

Класс Instant представляет момент на временной шкале в UTC с разрешением наносекунд. Ясно и просто.

Instant instant = Instant.now();

instant.toString () → 2016-06-19T02: 34: 55,564Z

Если для использования со старым кодом требуется java.util.Date, вы можете выполнить конвертацию. Смотрите новые методы, добавленные к старому классу: java.util.Date :: toInstant () и java.util.Date.from (Instant) .

Зонная

Чтобы настроить время настенных часов в некоторых населенных пунктах , примените offset-from-UTC (ZoneOffset), чтобы получить OffsetDateTime объект. Еще лучше, если вы знаете правильное название часового пояса, примените ZoneId, чтобы получить ZonedDateTime.

Например, America/Montreal на четыре часа меньше UTC летом под Летнее время (DST) , поэтому мы видим 22:00 (22:00) ) в предыдущую дату в коде ниже, а не в 2 часа ночи в примере выше. Возвращение на четыре часа перешло через полночь в предыдущую дату. Но и объект instant, показанный выше, и объект zdt, увиденный следующим , представляют один и тот же одновременный момент на временной шкале. Тот же момент в истории, но «завтра» в Париже, Калькутте и Окленде, а «вчера» в Монреале, Мехико и Гонолулу.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

zdt.toString () → 2016-06-18T22: 34: 55.564-04: 00 [Америка / Монреаль]

LocalDate

Для значения только на дату используйте класс LocalDate. Ни время суток, ни часовой пояс не сохраняются.

LocalDate localDate = zdt.toLocalDate();

Но учтите, что часовой пояс имеет решающее значение при определении даты , поскольку в любой данный момент дата может меняться по всему земному шару в зависимости от часового пояса. Таким образом, обсуждение выше об указании часового пояса. Например, посмотрите далее, как мы получаем 18 июня, а не 19th .

localDate.toString () → 2016-06-18

Если это различиемежду датами по часовому поясу имеет значение для вашего бизнеса, вы должны использовать значение даты и времени, хранящееся в столбце базы данных типа TIMESTAMP WITH TIME ZONE, а не DATE.

Переполнение стека поиска для получения дополнительной информации и множества примеров java.time (тег: java-time).

База данных

Для сохранения в базе данных используйте JDBC драйвер , соответствующий JDBC 4.2 spec (см. Guide * 1159) *). Вызовите setObject и getObject для PreparedStatement, чтобы напрямую использовать объекты java.time.

Если ваш драйвер JDBC еще не поддерживает такое прямое использование типов java.time, используйте новые методы , добавленные к старым классам , чтобы упростить преобразование. Но сведите к минимуму использование старых классов; немедленно преобразуйте в java.time и используйте только объекты java.time в своей бизнес-логике.

java.sql.Date mySqlDate = java.sql.Date.valueOf( localDate );

И другое направление.

LocalDate localDate = mySqlDate.toLocalDate();
0 голосов
/ 12 августа 2012

java.sql.Date принимает длинное целое число, которое представляет количество миллисекунд с 1 января 1970 года. Если данное число отрицательное, оно относится ко времени до 1 января 1970 года. Помните, что инкапсулированное значение внутри объекта представляет только дату как 1 января 1970 года, и информация о времени не сохраняется.

java.util.Date хранит как дату, так и информацию о времени. Он чаще используется, чем java.sql.Date.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...