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

Сравнить объект Date с TimeStamp в Java

Когда я тестирую этот код:

java.util.Date date = new java.util.Date();
java.util.Date stamp = new java.sql.Timestamp(date.getTime());

assertTrue(date.equals(stamp));
assertTrue(date.compareTo(stamp) == 0);
assertTrue(stamp.compareTo(date) == 0);
assertTrue(stamp.equals(date));

Я буду ожидать истинного, истинного, истинного, ложного. Из-за этого:

В javadoc для java.sql.Timestamp указано:

Примечание. Этот тип является составной частью java.util.Date и отдельной наносекунды. Только целые секунды хранятся в компонент java.util.Date. Дробные секунды - нано - являются отдельный. Метод Timestamp.equals(Object) никогда не возвращает true, если передал значение типа java.util.Date, потому что компонент нано дата неизвестна. В результате метод Timestamp.equals(Object) не симметричный относительно java.util.Date.equals(Object) метод. Кроме того, метод hashcode использует базовый java.util.Date и поэтому не включает нано вычисление.

Из-за различий между классом Timestamp и java.util.Date, упомянутый выше, рекомендуется, чтобы код не просмотреть значения метки времени в качестве экземпляра java.util.Date. Отношение наследования между меткой времени и java.util.Date на самом деле означает наследование реализации, а не наследование типов.

Но вместо этого я получу истинное, ложное, истинное, ложное. Любые идеи?

EDIT: эта проблема возникает, когда я проверял два дата с помощью метода equals, но один из объектов Date исходил из класса Hibernate и отладки, я вижу, что объект содержит TimeStamp. Таким образом, метод equals оценивается как false, тогда я нашел это: http://mattfleming.com/node/141

Но когда я пытаюсь использовать код, я получаю разные результаты... если я не могу использовать ни равные, ни сравнивать, что я должен использовать, чтобы проверить, совпадают ли 2 Даты?!?!

4b9b3361

Ответ 1

Никан объяснил часть equals, о compareTo:

  • Timestamp имеет метод compareTo(Date), который преобразует его в Timestamp внутри
  • Date выполняется сравнение путем downcasting (поскольку Timestamp является его подклассом); но поскольку javadoc заявляет: "Отношение наследования между Timestamp и java.util.Date действительно означает наследование реализации, а не наследование типов"

Это, конечно, ужасная идея, на мой взгляд.

Ответ 2

Старые классы с датой и временем плохо разработаны

Проще говоря, классы java.sql.Timestamp/.Date/.Time - это взлом, плохой взлом. Как java.util.Date/.Calendar, они являются результатом плохого выбора дизайна.

Типы java.sql должны использоваться как можно короче, используются только для передачи данных в/из базы данных. Не используйте для бизнес-логики и дальнейшей работы.

java.time

Предыдущие классы времени были заменены рамкой java.time, встроенной в Java 8 и более поздних версий. Эти новые классы определяются JSR 310, вдохновленные очень успешной библиотекой Joda-Time и расширены проектом ThreeTen-Extra.

В конце концов мы должны увидеть, что драйверы JDBC обновлены для работы непосредственно с этими типами java.time. Но до этого дня нам нужно преобразовать в/из типов java.sql. Для таких преобразований вызовите новые методы, добавленные в старые классы.

An Instant - это момент на временной шкале в UTC с разрешением наносекунды.

Instant instant = myJavaSqlTimestamp.toInstant();

Чтобы перейти в другое направление:

java.sql.Timestamp ts = java.sql.Timestamp.valueOf( instant );

Примените часовой пояс, чтобы получить время настенных часов.

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

У классов java.time есть чистый, разумно выбранный класс. Поэтому вы можете использовать equals и compareTo, как и ожидалось. Обратите внимание, что классы со смещением-от-UTC или часовым поясом также предлагают методы isEqual, isBefore и isAfter. Эти методы сравниваются, рассматривая моменты на временной шкале, их хронологический порядок. Методы equals и compareTo также учитывают смещение или временную зону.

Сведение к минимуму использования java.sql при максимальном использовании java.time делает проблемы вопросов спорными.

В Hibernate используйте конвертеры для java.time.

Поиск для многих других примеров и обсуждений.

Ответ 3

  • date.equals(штамп) return true AND stamp equals (date) возвращает false. REASON: дата игнорирует наносекундную часть метки времени, а остальные части оказываются равными, поэтому результат равен. Дробные секунды - nanos - являются отдельными. Метод Timestamp.equals(Object) никогда не возвращает true, когда передается значение типа java.util.Date, потому что компонент nanos даты неизвестен. Подробнее см. здесь.

    • date.compareTo(stamp) == 0 возвращает false AND stamp.compareTo(date) == 0 возвращает true. ПРИЧИНА. В соответствии с этой функцией bug функция compareTo будет вести себя так, как она есть.

Ответ 4

У меня была та же проблема в тесте, где я хотел сравнить объекты java.util.Date и java.sql.Timestamp.

Я преобразовал их в LocalDate, и это сработало:

import org.apache.commons.lang.ObjectUtils;

// date1 and date2 can be java.util.Date or java.sql.Timestamp
boolean datesAreEqual = ObjectUtils.equals(toLocalDate(date1), toLocalDate(date2));

где toLocalDate:

import org.joda.time.LocalDate;
import java.util.Date;

public static void LocalDate toLocalDate(Date date)
{
    return date != null ? LocalDate.fromDateFields(date) : null;
}

Ответ 5

Timestamp Нанозначение не является числом наносекунд - это число миллисекунд с разрешением в миллисекундах (т.е. дробные секунды). Таким образом, в конструкторе Timestamp он устанавливает время на супер, которое должно быть без миллисекунд. Поэтому Timestamp всегда будет иметь меньшее значение для члена fastTime (используемого в Date compareTo()), чем соответствующий Date (если, конечно, он не имеет дробных секунд).

Отметьте источник для отметки времени в строке 110.

Ответ 6

Попробуйте воссоздать дату объекта, используя "Строки", подобные этому

Date date = new Date();
Date stamp = Timestamp(date.getTime());

SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String date1String = ft.format(date);
String date2String = ft.format(stamp);

Date date1 = ft.parse(date1String);
Date date2 = ft.parse(date2String);


assertTrue(date1.equals(date2)); // true
assertTrue(date1.compareTo(date2) == 0); //true
assertTrue(date2.compareTo(date1) == 0); //true
assertTrue(date2.equals(date1)); // true

Ответ 7

Я решил преобразовать Date и TimeStamp в объект Calendar, а затем сравнил свойства Календаря:

Calendar date = Calendar.getInstance();
date.setTimeInMillis(dateObject.getTime());
Calendar timestamp = Calendar.getInstance();
timestamp.setTimeInMillis(timestampObject.getTime());
if (effettoAppendice.get(Calendar.DAY_OF_MONTH) == timestamp.get(Calendar.DAY_OF_MONTH) &&
    effettoAppendice.get(Calendar.MONTH) == timestamp.get(Calendar.MONTH) &&
    effettoAppendice.get(Calendar.YEAR) == timestamp.get(Calendar.YEAR)) {
    System.out.println("Date and Timestamp are the same");
} else {
    System.out.println("Date and Timestamp are NOT the same");
}

Надеюсь, что это поможет.

Ответ 8

Взгляните на метод сравнения исходного кода для отметки времени:

public boolean equals(java.lang.Object ts) {
  if (ts instanceof Timestamp) {
    return this.equals((Timestamp)ts);
  } else {
    return false;
  }
}

http://www.docjar.com/html/api/java/sql/Timestamp.java.html

Он будет возвращать true только тогда, когда объект сравнения является меткой времени. Кроме того, вот исходный код Date: http://www.docjar.com/html/api/java/util/Date.java.html, и поскольку Timestamp наследует Date, он может сравнить его.

Ответ 9

К сожалению, класс Timestamp перегружает метод equals(Object) с помощью equals(Timestamp), поэтому сравнивать с отметками времени очень сложно.

В equals(Object) javadocs говорит:

Проверяет, является ли этот объект Timestamp равный данному объекту. Эта версия метода равна добавлено для исправления неправильной подписи Timestamp.equals(отметка времени) и сохранить обратную совместимость с существующими файлами классов. Примечание. Этот метод не является симметричным относительно равных (Object) метод в базовом классе.

Мое эмпирическое правило никогда не сравнивает временные метки для равенства (что в любом случае бесполезно), но если вам нужно проверить равенство, сравните их, используя результат getTime() (количество миллисекунд с 1 января 1970, 00:00).

Ответ 10

Небольшая заметка о наследовании реализации и наследовании типа.

"Класс объекта определяет, как реализуется объект. Напротив, тип объекта относится только к его интерфейсу. Наследование класса (наследование реализации) определяет реализацию объекта в терминах реализации другого объекта. Наследование типа описывает, когда объект может использоваться вместо другого".

Временные метки и даты имеют наследование реализации, как сказал JAVADOC.