Сравнивая два java.util.Dates, чтобы узнать, находятся ли они в тот же день

Мне нужно сравнить два Date (например, date1 и date2) и придумать boolean sameDay, который является истинным для двух Date share в тот же день, и false, если они не являются.

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

, чтобы уточнить:, если date1 и date2 используют один и тот же год, месяц и день, тогда sameDay - true, иначе это значение false. Я понимаю, что это требует знания часового пояса... было бы неплохо пройти в часовой пояс, но я могу жить с GMT или по местному времени, пока я знаю, что такое поведение.

, чтобы уточнить:

date1 = 2008 Jun 03 12:56:03
date2 = 2008 Jun 03 12:59:44
  => sameDate = true

date1 = 2009 Jun 03 12:56:03
date2 = 2008 Jun 03 12:59:44
  => sameDate = false

date1 = 2008 Aug 03 12:00:00
date2 = 2008 Jun 03 12:00:00
  => sameDate = false

Ответ 1

Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal1.setTime(date1);
cal2.setTime(date2);
boolean sameDay = cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR) &&
                  cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR);

Обратите внимание, что "тот же день" не так проста, как звучит, когда могут быть задействованы разные часовые пояса. Приведенный выше код для обеих дат вычисляет день относительно часового пояса, используемого компьютером, на котором он работает. Если это не то, что вам нужно, вы должны передать соответствующий часовой пояс на вызовы Calendar.getInstance(), после того как вы решили, что именно вы имеете в виду под "в тот же день".

И да, Joda Time LocalDate сделает все это намного чище и проще (хотя будут присутствовать те же трудности с часовыми поясами).

Ответ 2

Как насчет:

SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
return fmt.format(date1).equals(fmt.format(date2));

Вы также можете установить часовой пояс для SimpleDateFormat, если это необходимо.

Ответ 3

Для этого я использую пакет "apache commons lang" (а именно org.apache.commons.lang.time.DateUtils)

boolean samedate = DateUtils.isSameDay(date1, date2);  //Takes either Calendar or Date objects

Ответ 4

Вы можете избежать внешних зависимостей и производительности при использовании Календаря, вычислив Юлийский номер дня для каждой из дат, а затем сравнив их:

public static boolean isSameDay(Date date1, Date date2) {

    // Strip out the time part of each date.
    long julianDayNumber1 = date1.getTime() / MILLIS_PER_DAY;
    long julianDayNumber2 = date2.getTime() / MILLIS_PER_DAY;

    // If they now are equal then it is the same day.
    return julianDayNumber1 == julianDayNumber2;
}

Ответ 5

Joda времени

Что касается добавления зависимости, я боюсь, что java.util.Date и .Calendar действительно настолько плохи, что первое, что я делаю с любым новым проектом, - добавить библиотеку Joda-Time. В Java 8 вы можете использовать новый пакет java.time, вдохновленный Joda-Time.

Ядром Joda-Time является класс DateTime. В отличие от java.util.Date, он понимает свой назначенный часовой пояс (DateTimeZone). При преобразовании из j.u.Date назначьте зону.

DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime dateTimeQuébec = new DateTime( date , zone );

LocalDate

Один из способов проверить, если две даты-времени земли на ту же дату, чтобы конвертировать в LocalDate объекты.

Это преобразование зависит от назначенного часового пояса. Чтобы сравнить объекты LocalDate, они должны были быть преобразованы в одну и ту же зону.

Вот небольшой полезный метод.

static public Boolean sameDate ( DateTime dt1 , DateTime dt2 )
{
    LocalDate ld1 = new LocalDate( dt1 );
    // LocalDate determination depends on the time zone.
    // So be sure the date-time values are adjusted to the same time zone.
    LocalDate ld2 = new LocalDate( dt2.withZone( dt1.getZone() ) );
    Boolean match = ld1.equals( ld2 );
    return match;
}

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

static public Boolean sameDate ( DateTimeZone zone , DateTime dt1 , DateTime dt2 )
{
    LocalDate ld1 = new LocalDate( dt1.withZone( zone ) );
    // LocalDate determination depends on the time zone.
    // So be sure the date-time values are adjusted to the same time zone.
    LocalDate ld2 = new LocalDate( dt2.withZone( zone ) );
    return ld1.equals( ld2 );
}

Представление строки

Другим подходом является создание строкового представления части даты каждой даты-времени, а затем сравнение строк.

Опять же, назначенный часовой пояс имеет решающее значение.

DateTimeFormatter formatter = ISODateTimeFormat.date();  // Static method.
String s1 = formatter.print( dateTime1 );
String s2 = formatter.print( dateTime2.withZone( dt1.getZone() )  );
Boolean match = s1.equals( s2 );
return match;

Период времени

Обобщенное решение состоит в том, чтобы определить промежуток времени, а затем спросить, содержит ли пролет цель. Этот примерный код находится в Joda-Time 2.4. Обратите внимание, что классы с "полуночью" устарели. Вместо этого используйте метод withTimeAtStartOfDay. Joda-Time предлагает три класса для представления промежутка времени различными способами: Интервал, Период и Продолжительность.

Использование подхода "Half-Open", в котором начало диапазона является включительным и конечным исключением.

Часовой пояс объекта может отличаться от часового пояса интервала.

DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime target = new DateTime( 2012, 3, 4, 5, 6, 7, timeZone );
DateTime start = DateTime.now( timeZone ).withTimeAtStartOfDay();
DateTime stop = start.plusDays( 1 ).withTimeAtStartOfDay();
Interval interval = new Interval( start, stop );
boolean containsTarget = interval.contains( target );

java.time

Java 8 и более поздние версии поставляются с java.time. Вдохновленный Joda-Time, определенный JSR 310 и расширенный проектом ThreeTen-Extra. См. Tutorial.

Создатели Joda-Time поручили всем нам перейти на java.time, как только это будет удобно. Тем временем Joda-Time продолжает активно поддерживаться проектом. Но ожидайте, что будущая работа произойдет только в java.time и ThreeTen-Extra, а не в Joda-Time.

Суммировать java.time в двух словах... Instant - момент на временной шкале в UTC. Примените часовой пояс (ZoneId), чтобы получить объект ZonedDateTime. Чтобы перейти от временной шкалы, чтобы получить неопределенное неопределенное представление о дате-времени, используйте "локальные" классы: LocalDateTime, LocalDate, LocalTime.

Логика, обсуждаемая в разделе Joda-Time этого ответа, относится к java.time.

В старом классе java.util.Date появился новый метод toInstant для преобразования в java.time.

Instant instant = yourJavaUtilDate.toInstant(); // Convert into java.time type.

Для определения даты требуется часовой пояс.

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

Мы применяем этот объект часового пояса к Instant для получения a ZonedDateTime. Из этого мы извлекаем значение только для даты (a LocalDate), поскольку наша цель - сравнивать даты (не часы, минуты и т.д.).

ZonedDateTime zdt1 = ZonedDateTime.ofInstant( instant , zoneId );
LocalDate localDate1 = LocalDate.from( zdt1 );

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

ZonedDateTime zdt2 = ZonedDateTime.now( zoneId );
LocalDate localDate2 = LocalDate.from( zdt2 );

Используйте специальный метод isEqual для проверки того же значения даты.

Boolean sameDate = localDate1.isEqual( localDate2 );

Ответ 6

Преобразование дат в Java 8 java.time.LocalDate как показано здесь.

LocalDate localDate1 = date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate localDate2 = date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

// compare dates
assertTrue("Not on the same day", localDate1.equals(localDate2));

Ответ 7

private boolean isSameDay(Date date1, Date date2) {
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTime(date1);
        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTime(date2);
        boolean sameYear = calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR);
        boolean sameMonth = calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH);
        boolean sameDay = calendar1.get(Calendar.DAY_OF_MONTH) == calendar2.get(Calendar.DAY_OF_MONTH);
        return (sameDay && sameMonth && sameYear);
    }

Ответ 9

Java 8

Если вы используете Java 8 в своем проекте и сравниваете java.sql.Timestamp, вы можете использовать класс LocalDate:

sameDate = date1.toLocalDateTime().toLocalDate().equals(date2.toLocalDateTime().toLocalDate());

Если вы используете java.util.Date, посмотрите на ответ Иштвана, который менее двусмыслен.

Ответ 10

в дополнение к решению Бинила Томаса

public static boolean isOnSameDay(Timestamp... dates) {
    SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
    String date1 = fmt.format(dates[0]);
    for (Timestamp date : dates) {
        if (!fmt.format(date).equals(date1)) {
            return false;
        }
    }
    return true;
}

Использование

    isOnSameDay(date1,date2,date3 ...);
//or 
    isOnSameDay(mydates);

Ответ 11

public static boolean validSearchRange(String start, String end){
    SimpleDateFormat dateFormat = new SimpleDateFormat(clientDateFormat);
    try {
        Date start_date = dateFormat.parse(start);
        Date end_date = dateFormat.parse(end);
        return !start_date.after(end_date);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return false;
}

Ответ 12

Для разработчиков Kotlin это версия со сравнением форматированных строк:

val sdf = SimpleDateFormat("yyMMdd")
if (sdf.format(date1) == sdf.format(date2)) {
    // same day
}

Это не лучший способ, но он короткий и рабочий.

Ответ 13

вы можете применить ту же логику, что и решение SimpleDateFormat, не полагаясь на SimpleDateFormat

date1.getFullYear()*10000 + date1.getMonth()*100 + date1.getDate() == 
date2.getFullYear()*10000 + date2.getMonth()*100 + date2.getDate()