Java:如何检查日期是否在一定范围内?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/494180/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: how do I check if a Date is within a certain range?
提问by Mike Sickler
I have a series of ranges with start dates and end dates. I want to check to see if a date is within that range.
我有一系列包含开始日期和结束日期的范围。我想检查日期是否在该范围内。
Date.before() and Date.after() seem to be a little awkward to use. What I really need is something like this pseudocode:
Date.before() 和 Date.after() 使用起来好像有点别扭。我真正需要的是这样的伪代码:
boolean isWithinRange(Date testDate) {
return testDate >= startDate && testDate <= endDate;
}
Not sure if it's relevant, but the dates I'm pulling from the database have timestamps.
不确定它是否相关,但我从数据库中提取的日期有时间戳。
采纳答案by Paul Tomblin
boolean isWithinRange(Date testDate) {
return !(testDate.before(startDate) || testDate.after(endDate));
}
Doesn't seem that awkward to me. Note that I wrote it that way instead of
对我来说似乎没有那么尴尬。请注意,我是这样写的,而不是
return testDate.after(startDate) && testDate.before(endDate);
so it would work even if testDate was exactly equal to one of the end cases.
所以即使 testDate 完全等于最终情况之一,它也会起作用。
回答by Rahul
An easy way is to convert the dates into milliseconds after January 1, 1970 (use Date.getTime()) and then compare these values.
一种简单的方法是将日期转换为 1970 年 1 月 1 日之后的毫秒数(使用 Date.getTime()),然后比较这些值。
回答by MBCook
That's the correct way. Calendars work the same way. The best I could offer you (based on your example) is this:
这是正确的方法。日历的工作方式相同。我可以为您提供的最好的(根据您的示例)是这样的:
boolean isWithinRange(Date testDate) {
return testDate.getTime() >= startDate.getTime() &&
testDate.getTime() <= endDate.getTime();
}
Date.getTime() returns the number of milliseconds since 1/1/1970 00:00:00 GMT, and is a long so it's easily comparable.
Date.getTime() 返回自 1/1/1970 00:00:00 GMT 以来的毫秒数,并且很长,因此很容易进行比较。
回答by Ben Hardy
Consider using Joda Time. I love this library and wish it would replace the current horrible mess that are the existing Java Date and Calendar classes. It's date handling done right.
考虑使用Joda Time。我喜欢这个库,并希望它能够取代现有的 Java Date 和 Calendar 类当前可怕的混乱。这是正确的日期处理。
EDIT: It's not 2009 any more, and Java 8's been out for ages. Use Java 8's built in java.time classes which are based on Joda Time, as Basil Bourque mentions above. In this case you'll want the Period class, and here's Oracle's tutorialon how to use it.
编辑:现在已经不是 2009 年了,Java 8 已经发布多年了。使用基于 Joda Time 的 Java 8 内置 java.time 类,如 Basil Bourque 上面提到的。在这种情况下,您将需要 Period 类,这里是Oracle关于如何使用它的教程。
回答by Basil Bourque
tl;dr
tl;博士
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 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*.
)
Half-Open
半开
Date-time work commonly employs the "Half-Open" approach to defining a span of time. The beginning is inclusivewhile the ending is exclusive. So a week starting on a Monday runs up to, but does not include, the following Monday.
日期时间工作通常采用“半开”方法来定义时间跨度。开始是包容的,而结束是排他的。因此,从星期一开始的一周会持续到但不包括下一个星期一。
java.time
时间
Java 8 and later comes with the java.timeframework 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.
Java 8 及更高版本带有内置的java.time框架。补充了旧的麻烦类,包括 java.util.Date/.Calendar 和 SimpleDateFormat。受到成功的 Joda-Time 库的启发。由 JSR 310 定义。由 ThreeTen-Extra 项目扩展。
An Instant
is a moment on the timeline in UTCwith nanosecond resolution.
AnInstant
是UTC时间线上的一个时刻,分辨率为纳秒。
Instant
Instant
Convert your java.util.Date objects to Instant objects.
将您的 java.util.Date 对象转换为 Instant 对象。
Instant start = myJUDateStart.toInstant();
Instant stop = …
If getting java.sql.Timestamp objects through JDBC from a database, convert to java.time.Instantin a similar way. A java.sql.Timestamp is already in UTC so no need to worry about time zones.
如果通过 JDBC 从数据库中获取 java.sql.Timestamp 对象,以类似的方式转换为 java.time.Instant。java.sql.Timestamp 已经在 UTC 中,因此无需担心时区。
Instant start = mySqlTimestamp.toInstant() ;
Instant stop = …
Get the current moment for comparison.
获取当前时刻进行比较。
Instant now = Instant.now();
Compare using the methods isBefore, isAfter, and equals.
使用方法 isBefore、isAfter 和 equals 进行比较。
Boolean containsNow = ( ! now.isBefore( start ) ) && ( now.isBefore( stop ) ) ;
LocalDate
LocalDate
Perhaps you want to work with only the date, not the time-of-day.
也许您只想使用日期,而不是一天中的时间。
The LocalDate
class represents a date-only value, without time-of-day and without time zone.
该LocalDate
级表示日期,只值,没有时间的天,没有时区。
LocalDate start = LocalDate.of( 2016 , 1 , 1 ) ;
LocalDate stop = LocalDate.of( 2016 , 1 , 23 ) ;
To get the current date, specify a time zone. For any given moment, today's date varies by time zone. For example, a new day dawns earlier in Paris than in Montréal.
要获取当前日期,请指定时区。对于任何给定时刻,今天的日期因时区而异。例如,新的一天在巴黎比在蒙特利尔早。
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
We can use the isEqual
, isBefore
, and isAfter
methods to compare. In date-time work we commonly use the Half-Open approach where the beginning of a span of time is inclusivewhile the ending is exclusive.
我们可以使用isEqual
,isBefore
和isAfter
方法比较。在日期时间工作中,我们通常使用半开方法,其中时间跨度的开始是包含的,而结束是不包含的。
Boolean containsToday = ( ! today.isBefore( start ) ) && ( today.isBefore( stop ) ) ;
Interval
Interval
If you chose to add the ThreeTen-Extralibrary to your project, you could use the Interval
class to define a span of time. That class offers methods to test if the interval contains, abuts, encloses, or overlapsother date-times/intervals.
如果您选择将ThreeTen-Extra库添加到您的项目中,您可以使用Interval
该类来定义时间跨度。该类提供了测试间隔是否包含、邻接、包围或重叠其他日期时间/间隔的方法。
The Interval
class works on Instant
objects. The Instant
class represents a moment on the timeline in UTCwith a resolution of nanoseconds(up to nine (9) digits of a decimal fraction).
本Interval
类适用于Instant
对象。该Instant
级表示时间轴上的时刻UTC,分辨率为纳秒(最多小数的9个位数)。
We can adjust the LocalDate
into a specific moment, the first moment of the day, by specifying a time zone to get a ZonedDateTime
. From there we can get back to UTC by extracting a Instant
.
我们可以LocalDate
通过指定时区来将ZonedDateTime
. 从那里我们可以通过提取一个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 );
About java.time
关于 java.time
The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
该java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date
, Calendar
, & SimpleDateFormat
。
The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310。
Where to obtain the java.time classes?
从哪里获得 java.time 类?
- Java SE 8and SE 9and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6and SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- The ThreeTenABPproject adapts ThreeTen-Backport(mentioned above) for Android specifically.
- See How to use….
- Java SE 8和SE 9及更高版本
- 内置。
- 具有捆绑实现的标准 Java API 的一部分。
- Java 9 添加了一些小功能和修复。
- Java SE 6和SE 7
- 多的java.time功能后移植到Java 6和7在ThreeTen-反向移植。
- 安卓
- 所述ThreeTenABP项目适应ThreeTen-反向移植(上述)为Android特异性。
- 请参阅如何使用......。
The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.
该ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如Interval
,YearWeek
,YearQuarter
,和更多。
回答by Radu
Doesnn't care which date boundry is which.
不在乎哪个日期边界是哪个。
Math.abs(date1.getTime() - date2.getTime()) ==
Math.abs(date1.getTime() - dateBetween.getTime()) + Math.abs(dateBetween.getTime() - date2.getTime());
回答by Naveen Yadav
your logic would work fine . As u mentioned the dates ur getting from the database are in timestamp , You just need to convert timestamp to date first and then use this logic.
你的逻辑会正常工作。正如您提到的,您从数据库中获取的日期在时间戳中,您只需要先将时间戳转换为日期,然后使用此逻辑。
Also dont forget to check for null dates.
也不要忘记检查空日期。
here m sharing a bit to convert from Timestamp to date.
在这里分享一点从时间戳转换为日期。
public static Date convertTimeStamptoDate(String val) throws Exception {
公共静态日期 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;
}
}
回答by Koray Peker
you can use like this
你可以这样使用
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
回答by Dhunju_likes_to_Learn
This was clearer to me,
这对我来说更清楚,
// 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
}
回答by rashedmedisys
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;
}
}