如何检查日期是否在某个范围内?

我有一系列的范围与开始日期和结束日期。我想看看日期是否在这个范围内。

Date. before ()和 Date. after ()使用起来似乎有点笨拙,我真正需要的是这样的伪代码:

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

不确定是否相关但我从数据库里提取的日期有时间戳。

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

对我来说没那么尴尬,注意我是这么写的

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

so it would work even if testDate was exactly equal to one of the end cases.

An easy way is to convert the dates into milliseconds after January 1, 1970 (use Date.getTime()) and then compare these values.

这是正确的方法。日历也是这样。基于你的例子,我能给你的最好建议是:

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

GetTime ()返回自1970年1月1日00:00:00 GMT 以来的毫秒数,这个值很长,所以很容易进行比较。

考虑使用 乔达时间。我喜欢这个库,并且希望它能够取代现有的 Java Date 和 Calendar 类。这是正确的日期处理。

编辑: 现在已经不是2009年了,Java8已经过时很久了。正如上面 Basil Bourque 提到的,使用基于 Joda Time 的 Java.Time 类构建的 Java8。在这种情况下,您需要使用 Period 类,下面是 甲骨文的教程关于如何使用它的介绍。

博士

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 8 and later comes with the java.time framework built-in. Supplants the old troublesome classes including java.util.Date/.Calendar and SimpleDateFormat. Inspired by the successful Joda-Time library. Defined by JSR 310. Extended by the ThreeTen-Extra project.

Instant协调世界时时间线上的一个瞬间,具有纳秒级的分辨率。

Instant

java.util.Date对象转换为 Instant 对象。

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

如果通过 JDBC 从数据库中获取 java.sql.Timestamp对象,则 转换为 java.time.Instant采用类似的方式。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" ) );

我们可以使用 isEqualisBeforeisAfter方法进行比较。在日期时间的工作,我们通常使用半开放的方法,其中开始的时间跨度是 包容性,而结束是 独家新闻

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

Interval

如果选择将 310-号外库添加到项目中,则可以使用 Interval类来定义时间跨度。该类提供方法来测试间隔 contains对接附件重叠是否还有其他日期-时间/间隔。

Interval类在 Instant对象上工作。Instant类代表了 协调世界时时间线上的一个时刻,其分辨率为 nanoseconds(最多为小数部分的9位数)。

我们可以调整 LocalDate到一个特定的时刻,一天的第一个时刻,通过指定一个时区得到一个 ZonedDateTime。从这里我们可以通过提取一个 Instant回到 UTC。

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 );

About java.time

java.time框架内置于 Java8及更高版本中。这些类取代了令人讨厌的旧的 遗产日期时间类,如 java.util.DateCalendarSimpleDateFormat

The Joda-Time project, now in 维修模式, advises migration to the java.time classes.

要了解更多,请参阅 Oracle 教程。并搜索堆栈溢出许多例子和解释。规范是 JSR 310

在哪里可以获得 java.time课程?

  • Java SE 8 SE9 及更高版本
  • 内置的。
  • 带有捆绑实现的标准 JavaAPI 的一部分。
  • Java9添加了一些次要的特性和修复。
  • Java SE 6 和 < a href = “ https://en.wikipedia.org/wiki/Java _ version _ history # Java _ SE _ 7”rel = “ noReferrer”> < strong > SE 7
  • < em > < strong > Three Ten-Backport 中,java.time的许多功能都被反向移植到 Java6和 Java7。
  • 仿生人
  • < em > Three TenABP 项目专门为 Android 调整了 ThreeTen-Backport(上面提到过)。
  • 参见 如何使用..

310-号外项目用其他类扩展了 java.time。这个项目是一个试验场的可能未来增加到 java.time。您可以在这里找到一些有用的类,比如 IntervalYearWeekYearQuartermore

不在乎哪个日期的界限是哪个。

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

你的逻辑没问题。正如您提到的,从数据库获取的日期位于时间戳中,您只需要首先将时间戳转换为日期,然后使用这个逻辑。

也不要忘记检查空日期。

here m sharing a bit to convert from Timestamp to date.

Public static Date ConvertTimeStamptoDate (String val)抛出异常{

    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;
}
}

你可以像这样使用

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

这对我来说更清楚,

// 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


}
  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;
}
}

For covering my case -> I've got a range start & end date, and dates list that can be as partly in provided range, as fully (overlapping).

测试覆盖的解决方案:

/**
* Check has any of quote work days in provided range.
*
* @param startDate inclusively
* @param endDate   inclusively
*
* @return true if any in provided range inclusively
*/
public boolean hasAnyWorkdaysInRange(LocalDate startDate, LocalDate endDate) {
if (CollectionUtils.isEmpty(workdays)) {
return false;
}


LocalDate firstWorkDay = getFirstWorkDay().getDate();
LocalDate lastWorkDay = getLastWorkDay().getDate();


return (firstWorkDay.isBefore(endDate) || firstWorkDay.equals(endDate))
&& (lastWorkDay.isAfter(startDate) || lastWorkDay.equals(startDate));
}

Java 8开始

注意: 除了一个以外,Date的所有构造函数都不推荐使用。Date的大多数方法都是不推荐的。参考文献: 日期: 废弃方法。除 Date::from(Instant)以外的所有静态方法都不推荐使用。

So, since java 8 consider using Instant (不可变的,线程安全的,闰秒感知的) type rather than Date. REF: 马上

  static final LocalTime MARKETS_OPEN = LocalTime.of(07, 00);
static final LocalTime MARKETS_CLOSE = LocalTime.of(20, 00);


// Instant utcTime = testDate.toInstant();
var bigAppleTime = ZonedDateTime.ofInstant(utcTime, ZoneId.of("America/New_York"));

包括:

    return !bigAppleTime.toLocalTime().isBefore(MARKETS_OPEN)
&& !bigAppleTime.toLocalTime().isAfter(MARKETS_CLOSE);

within the range EXCLUSIVE:

    return bigAppleTime.toLocalTime().isAfter(MARKETS_OPEN)
&& bigAppleTime.toLocalTime().isBefore(MARKETS_CLOSE);

如果您希望与 LocalDate进行包含性比较,请使用此代码。

LocalDate from = LocalDate.of(2021,8,1);
LocalDate to = LocalDate.of(2021,8,1);
LocalDate current = LocalDate.of(2021,8,1);


boolean isDateInRage = ( ! (current.isBefore(from.minusDays(1)) && current.isBefore(to.plusDays(1))) );

如果日期等于开始日期,则添加新的解决方案:

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

解决方案

return testDate.equals(startDate) || (testDate.after(startDate) &&
testDate.before(endDate)) || testDate.equals(endDate);
    public boolean isBetween(LocalDate target, LocalDate min, LocalDate max) {
if (target == null || min == null || max == null) {
throw new IllegalArgumentException("paramettres can't be null");
}


return target.compareTo(min) >= 0 && target.compareTo(max) <= 0;
}

谷歌番石榴

Range.closed(start, end)
.isConnected(Range.closed(now, now));

解决方案是用 之后之前方法检查日期。如果需要考虑包含性 endDate,那么当 testDate 和 endDate 是同一天时,之前(结束日期)返回 false,我们可以使用“ apache commons lang”包来验证这一点(org.apache.commons. lang.time)。日期工具)

import org.apache.commons.lang.time.DateUtils;


boolean isWithinRange(Date testDate) {
return   testDate.after(startDate) && (testDate.before(endDate) || DateUtils.isSameDay(testDate, endDate));
}