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

Java: как проверить, находится ли дата в определенном диапазоне?

У меня есть ряд диапазонов с датами начала и датами окончания. Я хочу проверить, находится ли дата в этом диапазоне.

Date.before() и Date.after() кажутся немного неудобными в использовании. Мне действительно нужно что-то вроде этого псевдокода:

boolean isWithinRange(Date testDate) {
    return testDate >= startDate && testDate <= endDate;
}

Не уверен, что это актуально, но даты, которые я вытаскиваю из базы данных, имеют временные метки.

4b9b3361

Ответ 1

boolean isWithinRange(Date testDate) {
   return !(testDate.before(startDate) || testDate.after(endDate));
}

Мне кажется, что это неловко. Обратите внимание, что я написал это так, а не

return testDate.after(startDate) && testDate.before(endDate);

чтобы он работал, даже если testDate был точно равен одному из конечных случаев.

Ответ 2

ТЛ; др

ZoneId z = ZoneId.of( "America/Montreal" );  // A date only has meaning within a specific time zone. For any given moment, the date varies around the globe by zone.
LocalDate ld = 
    givenJavaUtilDate.toInstant()  // Convert from legacy class 'Date' to modern class 'Instant' using new methods added to old classes.
                     .atZone( z )  // Adjust into the time zone in order to determine date.
                     .toLocalDate();  // Extract date-only value.

LocalDate today = LocalDate.now( z );  // Get todays date for specific time zone.
LocalDate kwanzaaStart = today.withMonth( Month.DECEMBER ).withDayOfMonth( 26 );  // Kwanzaa starts on Boxing Day, day after Christmas.
LocalDate kwanzaaStop = kwanzaaStart.plusWeeks( 1 );  // Kwanzaa lasts one week.
Boolean isDateInKwanzaaThisYear = (
    ( ! today.isBefore( kwanzaaStart ) ) // Short way to say "is equal to or is after".
    &&
    today.isBefore( kwanzaaStop )  // Half-Open span of time, beginning inclusive, ending is *exclusive*.
)

Полуоткрытый

Работа с датой времени обычно использует подход "Half-Open" для определения промежутка времени. Начало включено, в то время как окончание является эксклюзивным. Таким образом, неделя, начинающаяся в понедельник, заканчивается, но не включает следующий понедельник.

java.time

Java 8 и более поздние версии поставляются с встроенной инфраструктурой java.time. Предоставляет старые неприятные классы, включая java.util.Date/.Calendar и SimpleDateFormat. Вдохновленный успешной библиотекой Joda-Time. Определено JSR 310. Расширено проектом ThreeTen-Extra.

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

Instant

Преобразуйте объекты java.util.Date в объекты Instant.

Instant start = myJUDateStart.toInstant();
Instant stop = …

Если вы получаете java.sql.Timestamp объекты через JDBC из базы данных, конвертируйте в java.time.Instant аналогичным образом. Java.sql.Timestamp уже в UTC, поэтому не нужно беспокоиться о часовых поясах.

Instant start = mySqlTimestamp.toInstant() ;
Instant stop = …

Получите текущий момент для сравнения.

Instant now = Instant.now();

Сравните с помощью методов isBefore, isAfter и равно.

Boolean containsNow = ( ! now.isBefore( start ) ) && ( now.isBefore( stop ) ) ;

LocalDate

Возможно, вы хотите работать только с датой, а не с течением времени.

Класс LocalDate представляет собой значение только для даты, без времени и без часового пояса.

LocalDate start = LocalDate.of( 2016 , 1 , 1 ) ;
LocalDate stop = LocalDate.of( 2016 , 1 , 23 ) ;

Чтобы получить текущую дату, укажите часовой пояс. В любой данный момент сегодняшняя дата зависит от часового пояса. Например, в Париже новый день предстает раньше, чем в Монреале.

LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );

Мы можем использовать isEqual, isBefore и isAfter для сравнения. В работе с датой мы обычно используем подход Half-Open, где начало промежутка времени включено, в то время как окончание является эксклюзивным.

Boolean containsToday = ( ! today.isBefore( start ) ) && ( today.isBefore( stop ) ) ;

Interval

Если вы решили добавить библиотеку ThreeTen-Extra в свой проект, вы можете использовать класс Interval для определения промежутка времени. Этот класс предлагает методы для проверки, содержит ли интервал, ущемляет, заключает или перекрывает другие даты-интервалы/интервалы.

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

Мы можем настроить LocalDate в определенный момент, в первый момент дня, указав часовой пояс, чтобы получить ZonedDateTime. Оттуда мы можем вернуться в UTC, извлекая Instant.

ZoneId z = ZoneId.of( "America/Montreal" );
Interval interval = 
    Interval.of( 
        start.atStartOfDay( z ).toInstant() , 
        stop.atStartOfDay( z ).toInstant() );
Instant now = Instant.now();
Boolean containsNow = interval.contains( now );

О java.time

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

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

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

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

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

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

Ответ 3

Это правильный путь. Календари работают одинаково. Лучшее, что я мог предложить вам (на основе вашего примера), следующее:

boolean isWithinRange(Date testDate) {
    return testDate.getTime() >= startDate.getTime() &&
             testDate.getTime() <= endDate.getTime();
}

Date.getTime() возвращает число миллисекунд с 01.01.1970 00:00:00 по Гринвичу и является длинным, поэтому оно легко сравнимо.

Ответ 4

Попробуйте использовать Joda Time. Я люблю эту библиотеку и хочу, чтобы она заменила текущий ужасный беспорядок в существующих классах Java Date и Calendar. Это дата сделана правильно.

ОБНОВЛЕНИЕ: Это не 2009 больше, а Java 8 вышла на веки. Используйте Java 8, встроенные в классы java.time, основанные на Joda Time, как упомянуто выше Василием Бурке. В этом случае вам понадобится класс Period, а здесь учебник Oracle о том, как его использовать.

Ответ 5

Простым способом является преобразование дат в миллисекунды после 1 января 1970 года (используйте Date.getTime()), а затем сравните эти значения.

Ответ 6

Не заботьтесь о том, какая дата-граница есть.

Math.abs(date1.getTime() - date2.getTime()) == 
    Math.abs(date1.getTime() - dateBetween.getTime()) + Math.abs(dateBetween.getTime() - date2.getTime());

Ответ 7

вы можете использовать это как

Interval interval = new Interval(date1.getTime(),date2.getTime());
Interval interval2 = new Interval(date3.getTime(), date4.getTime());
Interval overlap = interval.overlap(interval2);
boolean isOverlap = overlap == null ? false : true

Ответ 8

Это было яснее для меня,

// declare calendar outside the scope of isWithinRange() so that we initialize it only once
private Calendar calendar = Calendar.getInstance();

public boolean isWithinRange(Date date, Date startDate, Date endDate) {

    calendar.setTime(startDate);
    int startDayOfYear = calendar.get(Calendar.DAY_OF_YEAR); // first day is 1, last day is 365
    int startYear = calendar.get(Calendar.YEAR);

    calendar.setTime(endDate);
    int endDayOfYear = calendar.get(Calendar.DAY_OF_YEAR);
    int endYear = calendar.get(Calendar.YEAR);

    calendar.setTime(date);
    int dayOfYear = calendar.get(Calendar.DAY_OF_YEAR);
    int year = calendar.get(Calendar.YEAR);

    return (year > startYear && year < endYear) // year is within the range
            || (year == startYear && dayOfYear >= startDayOfYear) // year is same as start year, check day as well
            || (year == endYear && dayOfYear < endDayOfYear); // year is same as end year, check day as well

}

Ответ 9

Я не вижу причины для этого в java, когда вы можете сделать это с помощью простого оператора sql.

Как в этом вопросе/ответе:

Запрос Postgresql между диапазонами дат

SELECT
  user_id
FROM
 user_logs
WHERE
      login_date >= '2014-02-01'
  AND login_date <  '2014-03-01'

Просто приспосабливайтесь к вашим потребностям и закончите. Что-то вроде:

 SELECT 
   testdate
 FROM 
   dates
 WHERE 
  testdate BETWEEN startdate AND duedate

Ответ 10

  public class TestDate {

    public static void main(String[] args) {
    // TODO Auto-generated method stub

    String fromDate = "18-FEB-2018";
    String toDate = "20-FEB-2018";

    String requestDate = "19/02/2018";  
    System.out.println(checkBetween(requestDate,fromDate, toDate));
}

public static boolean checkBetween(String dateToCheck, String startDate, String endDate) {
    boolean res = false;
    SimpleDateFormat fmt1 = new SimpleDateFormat("dd-MMM-yyyy"); //22-05-2013
    SimpleDateFormat fmt2 = new SimpleDateFormat("dd/MM/yyyy"); //22-05-2013
    try {
     Date requestDate = fmt2.parse(dateToCheck);
     Date fromDate = fmt1.parse(startDate);
     Date toDate = fmt1.parse(endDate);
     res = requestDate.compareTo(fromDate) >= 0 && requestDate.compareTo(toDate) <=0;
    }catch(ParseException pex){
        pex.printStackTrace();
    }
    return res;
   }
 }

Ответ 11

Я сделал это так и работал хорошо (без библиотек):

public static boolean isDateBetween(Date myDate, Date initialDate, Date finalDate) { // Comparing dates
        Calendar calInitial = setZeroHour(initialDate);
        Calendar calFinal = setLastHout(finalDate);
        Calendar calToday = Calendar.getInstance();
        calToday.setTime(myDate);

        return (calToday.getTime().getTime() >= calInitial.getTime().getTime()) &&
                (calToday.getTime().getTime() <= calFinal.getTime().getTime());

    }

    public static Calendar setZeroHour(Date date) { // Initial date got 00:00:00 hours
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.SECOND,0);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.HOUR_OF_DAY,0);
        return calendar;
    }

    public static Calendar setLastHout(Date date) { // Final date got 23:59:59 hours
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.SECOND,59);
        calendar.set(Calendar.MINUTE,59);
        calendar.set(Calendar.HOUR_OF_DAY,23);
        return calendar;
    }

Надеюсь, поможет! :)

Ответ 12

Чтобы быть в безопасности, я бы посмотрел на null:

if (testDate == null){
        return true; // or false depending on your specs
    }
return ( startDate == null || testDate.after(startDate) ) &&
            ( endDate == null || endDate.before(startDate) );

Ответ 13

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

Также не забудьте проверить нулевые даты.

здесь m разделить бит для преобразования с отметки времени до даты.

public static Date convertTimeStamptoDate (String val) throws Exception {

    DateFormat df = null;
    Date date = null;

    try {
        df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        date = df.parse(val);
        // System.out.println("Date Converted..");
        return date;
    } catch (Exception ex) {
        System.out.println(ex);
        return convertDate2(val);
    } finally {
        df = null;
        date = null;
    }
}