Сравните только часть времени двух дат, игнорируя часть даты - PullRequest
31 голосов
/ 06 октября 2011

Какой хороший метод, учитывая два объекта Date, сравнивать разницу только по их временной части, полностью игнорируя год, месяц и день?

Это полная противоположность этого вопроса .

ОБНОВЛЕНИЕ: Вот окончательный код для дальнейшего использования:

private long differenceBetween(Date currentTime, Date timeToRun)
{
    Calendar currentCal = Calendar.getInstance();
    currentCal.setTime(currentTime);

    Calendar runCal = Calendar.getInstance();
    runCal.setTime(timeToRun);
    runCal.set(Calendar.DAY_OF_MONTH, currentCal.get(Calendar.DAY_OF_MONTH));
    runCal.set(Calendar.MONTH, currentCal.get(Calendar.MONTH));
    runCal.set(Calendar.YEAR, currentCal.get(Calendar.YEAR));

    return currentCal.getTimeInMillis() - runCal.getTimeInMillis();
}

Ответы [ 8 ]

31 голосов
/ 06 октября 2011

Если вы хотите сравнить базовые двоичные (long int) значения дат, вы можете сделать это:

public int compareTimes(Date d1, Date d2)
{
    int     t1;
    int     t2;

    t1 = (int) (d1.getTime() % (24*60*60*1000L));
    t2 = (int) (d2.getTime() % (24*60*60*1000L));
    return (t1 - t2);
}

Приложение 1

Этот метод обладает преимуществом скорости, потому что он использует базовое значение long объектов Date напрямую, вместо преобразования между тиками и компонентами календаря (что довольно дорого и медленно). Это также намного проще, чем возиться с Calendar объектами.

Приложение 2

Приведенный выше код возвращает разницу во времени как int, которая будет корректна для любой пары раз, поскольку он полностью игнорирует части даты в году / месяце / дне, а разница между любыми двумя разами не равна более 86 400 000 мс (= 1000 мс / с & times; 60 с / мин & times; 60 мин / ч & times; 24 ч / день).

19 голосов
/ 06 октября 2011

Вы можете рассмотреть возможность использования Joda time's DateTimeComparator.getTimeOnlyInstance() для сравнения, который будет сравнивать две даты Joda на основе только времени.

Например:

DateTimeComparator comparator = DateTimeComparator.getTimeOnlyInstance();
comparator.compare(date1, date2);

См. http://joda -time.sourceforge.net / апи-релиз / орг / Joda / время / DateTimeComparator.html # getTimeOnlyInstance ()

5 голосов
/ 06 октября 2011

Взгляните на класс Calendar.Он поддерживает извлечение часов, минут и секунд из заданных Date х

1006 *.
3 голосов
/ 28 октября 2018

ТЛ; др

Используйте современные java.time классы.

Помните, что запрошенное вами сравнение может не иметь смысла, поскольку определенное время суток может иметь разное значение для разных дат в разных зонах.

Duration                                  // Span of time, with resolution of nanoseconds.
.between(                                 // Calculate elapsed time.
    LocalTime.now(                        // Get current time-of-day…
        ZoneId.of( "Pacific/Auckland" )   // … as seen in a particular time zone.
    )                                     // Returns a `LocalTime` object.
    ,
    myJavaUtilDate                        // Avoid terrible legacy date-time classes such as `java.util.Date`.
    .toInstant()                          // Convert from `java.util.Date` to `java.time.Instant`, both representing a moment in UTC.
    .atZone(                              // Adjust from UTC to a particular time zone. Same moment, same point on the timeline, different wall-clock time.
        ZoneId.of( "Pacific/Auckland" )   // Specify time zone by proper naming in `Continent/Region` format, never 2-4 letter pseudo-zones such as `PST`, `CEST`, `CST`, `IST`, etc.
    )                                     // Returns a `ZonedDateTime` object.
    .toLocalTime()                        // Extract the time-of-day without the date and without a time zone.
)                                         // Returns a `Duration` object.
.toMillis()                               // Calculate entire span-of-time in milliseconds. Beware of data-loss as `Instant` uses a finer resolution the milliseconds, and may carry microseconds or nanoseconds.

Я предлагаю обойти типобезопасный и не требующий пояснений объект Duration вместо простого целого числа миллисекунд.

java.time

Современный подход использует классы java.time , которые вытеснили ужасные унаследованные классы, такие как Date, Calendar, SimpleDateFormat.

Преобразуйте ваше java.util.Date (мгновение в UTC) в Instant. Используйте новые методы преобразования, добавленные к старым классам.

Instant instant = myJavaUtilDate.toInstant() ;

Это представляет момент в UTC. Для определения даты и времени суток требуется часовой пояс . В любой момент дата и время варьируются по всему земному шару в зависимости от зоны. Например, через несколько минут после полуночи в Париж Франция - это новый день, а еще "вчера" - в Монреаль Квебек .

Если часовой пояс не указан, JVM неявно применяет свой текущий часовой пояс по умолчанию. Это значение по умолчанию может меняться в любой момент во время выполнения (!), Поэтому ваши результаты могут отличаться. Лучше указать в качестве аргумента [желаемый / ожидаемый часовой пояс] [2].

Укажите собственное имя часового пояса в формате continent/region, например America/Montreal, Africa/Casablanca или Pacific/Auckland. Никогда не используйте 2-4 буквенные сокращения, такие как EST или IST, так как они не истинные часовые пояса, не стандартизированы и даже не уникальны (!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;  

Если вы хотите использовать текущий часовой пояс JVM по умолчанию, запросите его и передайте в качестве аргумента. Если опущено, текущее значение по умолчанию JVM применяется неявно. Лучше быть явным, поскольку значение по умолчанию может быть изменено в любой момент во время выполнения любым кодом в любом потоке любого приложения в JVM.

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

Назначьте ZoneId на Instant, чтобы создать ZonedDateTime объект.

ZonedDateTime zdt = instant.atZone( z ) ;

Извлечение части времени суток без даты и без часового пояса.

LocalTime lt = zdt.toLocalTime() ;

Сравнить. Рассчитайте прошедшее время с помощью Duration.

Duration d = Duration.between( ltStart , ltStop ) ;

Имейте в виду, что это несправедливое сравнение . Дни не всегда продолжительностью 24 часа, и не все значения времени суток действительны для всех дней во всех зонах. Например, в Соединенных Штатах во время перехода на летнее время может не быть часа 2 часа вообще. Таким образом, с 1 до 4 часов утра может быть 3 часа в одну дату, но только 2 часа в другую дату.


О java.time

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

Проект Joda-Time , теперь в режиме обслуживания , рекомендует выполнить переход на классы java.time .

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

Вы можете обмениваться java.time объектами напрямую с вашей базой данных. Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.* классах.

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

  • Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11 и более поздние версии - часть стандартного Java API с связанной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большинство функций java.time перенесены на Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии реализаций комплекта Android java.time классов.
    • Для более ранних версий Android (<26)проект <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP адаптируется ThreeTen-Backport (упомянуто выше).См. Как использовать ThreeTenABP… .

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

1 голос
/ 06 октября 2011

Если JODA не вариант, один из самых коротких подходов, вероятно, состоит в том, чтобы преобразовать время в строки и затем сравнить их.

DateFormat df = new SimpleDateFormat("HHmmssSZ");
df.format(date1).equals(df.format(date2));
1 голос
/ 06 октября 2011

Если вы не можете использовать JODA,

создать 2 календарных объекта, установить год, месяц и день равными 0.

Сравните их ....

0 голосов
/ 27 февраля 2016

если вы просто хотите сравнить временную часть дат, то это даст вам правильный результат -

public long compareTimes(Date d1, Date d2)
    {
        long     t1;
        long     t2;
        t1 = d1.getHours()*60*60+d1.getMinutes()*60+d1.getSeconds();
        t2 = d2.getHours()*60*60+d2.getMinutes()*60+d2.getSeconds();
        long diff = t1-t2;
        System.out.println("t1 - "+t1+", t2 - "+t2+",  diff - "+diff);

        return diff;
    }
0 голосов
/ 24 августа 2013

Не знаю, насколько это хорошо отработано или эффективно, но я написал простую функцию с использованием объекта Date, который служит моим целям. Возвращает true или false, если первое значение даты больше второго. Входами d1 && d2 являются объекты Date.

function CompareTimes(d1, d2) {
             if (d1.getHours() < d2.getHours()) {
                 return false;
             }
             if (d1.getHours() > d2.getHours()) {
                 return true;

             } else {
                 return (d1.getMinutes() > d2.getMinutes());
             }
};
...