Как мне проверить, находится ли дата в определенном диапазоне?
У меня есть ряд диапазонов с датами начала и окончания. Я хочу проверить, находится ли дата в этом диапазоне.
Date.before() и Date.after() кажутся немного неудобными в использовании. Что мне действительно нужно, так это что-то вроде этого псевдокода:
boolean isWithinRange(Date testDate) {
return testDate >= startDate && testDate <= endDate;
}
Не уверен, что это актуально, но даты, которые я извлекаю из базы данных, имеют временные метки.
Переведено автоматически
Ответ 1
boolean isWithinRange(Date testDate) {
return !(testDate.before(startDate) || testDate.after(endDate));
}
Мне это не кажется таким уж неудобным. Обратите внимание, что я написал это таким образом, а не
return testDate.after(startDate) && testDate.before(endDate);
таким образом, это сработало бы, даже если TestDate был точно равен одному из конечных значений.
Ответ 2
tl; dr
ZoneId z = ZoneId.of( "America/Montreal" ); // A date only has meaning within a specific time zone. At 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 today’s 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*.
)
Полуоткрыто
При работе с датой и временем обычно используется "полуоткрытый" подход к определению промежутка времени. Начало является включающим, а окончание - исключающим. Таким образом, неделя, начинающаяся с понедельника, длится до следующего понедельника, но не включает его.
java.time
Java 8 и более поздних версий поставляется со встроенным java.time
фреймворком. Заменяет старые проблемные классы, включая java.util.Date/.Calendar
и SimpleDateFormat
. Вдохновлен успешной библиотекой Joda-Time. Определено в JSR 310. Расширено проектом ThreeTen-Extra.
An Instant
- это момент на временной шкале в UTC с разрешением в наносекунду.
Instant
Преобразуйте ваши java.util.Date
объекты в Instant objects.
Instant start = myJUDateStart.toInstant();
Instant stop = …
При получении java.sql.Timestamp
объектов через JDBC из базы данных, преобразуйте в java.time.Instant аналогичным образом. A java.sql.Timestamp
уже находится в UTC, поэтому не нужно беспокоиться о часовых поясах.
Instant start = mySqlTimestamp.toInstant() ;
Instant stop = …
Получить текущий момент для сравнения.
Instant now = Instant.now();
Сравните, используя методы isBefore, isAfter и equals.
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
для сравнения. При работе с датой и временем мы обычно используем полуоткрытый подход, при котором начало промежутка времени является включительным, а окончание - исключительным.
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. И найдите в Stack Overflow множество примеров и пояснений. Спецификация - 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
- Проект ThreeTenABP адаптирует 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() возвращает количество миллисекунд, прошедших с 1/1/1970 00:00:00 GMT, и является длительным, поэтому его легко сопоставить.
Ответ 4
Рассмотрите возможность использования Joda Time. Мне нравится эта библиотека, и я бы хотел, чтобы она заменила текущий ужасный беспорядок, который представляют собой существующие классы даты и календаря Java. Обработка даты выполнена правильно.
РЕДАКТИРОВАТЬ: сейчас уже не 2009 год, а Java 8 давно отсутствует. Используйте классы Java 8, встроенные в java.time, которые основаны на времени Joda, как упоминал Бэзил Бурк выше. В этом случае вам понадобится класс Period, и вот руководство Oracle по его использованию.