比较两个 java.util.Dates 看它们是否在同一天
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2517709/
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
Comparing two java.util.Dates to see if they are in the same day
提问by Jason S
I need to compare two Date
s (e.g. date1
and date2
) and come up with a boolean sameDay
which is true of the two Date
s share the same day, and false if they are not.
我需要比较两个Date
s(例如date1
和date2
)并得出boolean sameDay
两个Date
s 共享同一天的情况为真,如果不是,则为假。
How can I do this? There seems to be a whirlwind of confusion here... and I would like to avoid pulling in other dependencies beyond the JDK if at all possible.
我怎样才能做到这一点?这里似乎有一阵混乱……如果可能的话,我想避免引入 JDK 之外的其他依赖项。
to clarify:if date1
and date2
share the same year, month, and day, then sameDay
is true, otherwise it is false. I realize this requires knowledge of a timezone... it would be nice to pass in a timezone but I can live with either GMT or local time as long as I know what the behavior is.
澄清一下:如果date1
和date2
共享相同的年月日,sameDay
则为真,否则为假。我意识到这需要时区的知识......传入时区会很好,但只要我知道行为是什么,我就可以接受格林威治标准时间或当地时间。
again, to clarify:
再次澄清:
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
采纳答案by Michael Borgwardt
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);
Note that "same day" is not as simple a concept as it sounds when different time zones can be involved. The code above will for both dates compute the day relative to the time zone used by the computer it is running on. If this is not what you need, you have to pass the relevant time zone(s) to the Calendar.getInstance()
calls, after you have decided what exactly you mean with "the same day".
请注意,当涉及不同的时区时,“同一天”并不像听起来那么简单。上面的代码将为两个日期计算相对于它运行的计算机使用的时区的日期。如果这不是您所需要的,您必须在Calendar.getInstance()
确定“同一天”的确切含义后,将相关时区传递给调用。
And yes, Joda Time's LocalDate
would make the whole thing much cleaner and easier (though the same difficulties involving time zones would be present).
是的,Joda TimeLocalDate
会让整个事情变得更简洁、更容易(尽管会出现涉及时区的相同困难)。
回答by Brent Watson
I use the "apache commons lang" package to do this (namely org.apache.commons.lang.time.DateUtils)
我使用“apache commons lang”包来做到这一点(即org.apache.commons.lang.time.DateUtils)
boolean samedate = DateUtils.isSameDay(date1, date2); //Takes either Calendar or Date objects
回答by Binil Thomas
How about:
怎么样:
SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
return fmt.format(date1).equals(fmt.format(date2));
You can also set the timezone to the SimpleDateFormat, if needed.
如果需要,您还可以将时区设置为 SimpleDateFormat。
回答by AyeJay
You can avoid external dependencies and the performance hit of using Calendar by calculating the Julian Day Numberfor each of the dates and then comparing these:
您可以通过计算每个日期的儒略日数然后比较这些来避免外部依赖和使用 Calendar 的性能影响:
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;
}
回答by jawa
you can apply the same logic as the SimpleDateFormat solution without relying on SimpleDateFormat
您可以应用与 SimpleDateFormat 解决方案相同的逻辑,而无需依赖 SimpleDateFormat
date1.getFullYear()*10000 + date1.getMonth()*100 + date1.getDate() ==
date2.getFullYear()*10000 + date2.getMonth()*100 + date2.getDate()
回答by Fareed Alnamrouti
in addition to Binil Thomas solution
除了 Binil Thomas 解决方案
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;
}
usage
用法
isOnSameDay(date1,date2,date3 ...);
//or
isOnSameDay(mydates);
回答by Basil Bourque
Joda-Time
乔达时间
As for adding a dependency, I'm afraid the java.util.Date & .Calendar really are so bad that the first thing I do to any new project is add the Joda-Time library. In Java 8 you can use the new java.time package, inspired by Joda-Time.
至于添加依赖项,恐怕java.util.Date & .Calendar 真的很糟糕,我对任何新项目做的第一件事就是添加Joda-Time 库。在 Java 8 中,您可以使用受 Joda-Time 启发的新 java.time 包。
The core of Joda-Time is the DateTime
class. Unlike java.util.Date, it understands its assigned time zone (DateTimeZone
). When converting from j.u.Date, assign a zone.
Joda-Time 的核心是DateTime
类。与 java.util.Date 不同,它了解其分配的时区 ( DateTimeZone
)。从 juDate 转换时,分配一个区域。
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime dateTimeQuébec = new DateTime( date , zone );
LocalDate
LocalDate
One way to verify if two date-times land on the same date is to convert to LocalDate
objects.
验证两个日期时间是否落在同一日期的一种方法是转换为LocalDate
对象。
That conversion depends on the assigned time zone. To compare LocalDate
objects, they must have been converted with the same zone.
该转换取决于指定的时区。要比较LocalDate
对象,它们必须已转换为相同的区域。
Here is a little utility method.
这是一个小实用方法。
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;
}
Better would be another argument, specifying the time zone rather than assuming the first DateTime object's time zone should be used.
更好的是另一个参数,指定时区而不是假设应该使用第一个 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 );
}
String Representation
字符串表示
Another approach is to create a string representation of the date portion of each date-time, then compare strings.
另一种方法是创建每个日期时间的日期部分的字符串表示,然后比较字符串。
Again, the assigned time zone is crucial.
同样,分配的时区至关重要。
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;
Span of Time
时间跨度
The generalized solution is to define a span of time, then ask if the span contains your target. This example code is in Joda-Time 2.4. Note that the "midnight"-related classes are deprecated. Instead use the withTimeAtStartOfDay
method. Joda-Time offers three classes to represent a span of time in various ways: Interval, Period, and Duration.
通用的解决方案是定义一个时间跨度,然后询问该跨度是否包含您的目标。此示例代码位于 Joda-Time 2.4 中。请注意,不推荐使用“午夜”相关的类。而是使用该withTimeAtStartOfDay
方法。Joda-Time 提供三个类以各种方式表示时间跨度:Interval、Period 和 Duration。
Using the "Half-Open" approach where the beginning of the span is inclusive and the ending exclusive.
使用“半开”方法,其中跨度的开头是包含的,结尾是独占的。
The time zone of the target can be different than the time zone of the interval.
目标的时区可以不同于间隔的时区。
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 and later comes with the java.timeframework. Inspired by Joda-Time, defined by JSR 310, and extended by the ThreeTen-Extra project. See Tutorial.
Java 8 及更高版本带有java.time框架。受 Joda-Time 的启发,由 JSR 310 定义,并由 ThreeTen-Extra 项目扩展。请参阅教程。
The makers of Joda-Time have instructed us all to move to java.time as soon as is convenient. In the meantime Joda-Time continues as an actively maintained project. But expect future work to occur only in java.time and ThreeTen-Extra rather than Joda-Time.
Joda-Time 的开发者已经指示我们大家在方便时尽快迁移到 java.time。与此同时,Joda-Time 继续作为一个积极维护的项目。但预计未来的工作只会发生在 java.time 和 ThreeTen-Extra 而不是 Joda-Time。
To summarize java.time in a nutshell… An Instant
is a moment on the timeline in UTC. Apply a time zone (ZoneId
) to get a ZonedDateTime
object. To move off the timeline, to get the vague indefinite idea of a date-time, use the "local" classes: LocalDateTime
, LocalDate
, LocalTime
.
简而言之,java.timeInstant
是 UTC 时间线上的一个时刻。应用时区 ( ZoneId
) 以获取ZonedDateTime
对象。要脱离时间线,获得日期时间的模糊概念,请使用“本地”类:LocalDateTime
, LocalDate
, LocalTime
。
The logic discussed in the Joda-Time section of this Answer applies to java.time.
本答案的 Joda-Time 部分中讨论的逻辑适用于 java.time。
The old java.util.Date class has a new toInstant
method for conversion to java.time.
旧的 java.util.Date 类具有toInstant
转换为 java.time的新方法。
Instant instant = yourJavaUtilDate.toInstant(); // Convert into java.time type.
Determining a date requires a time zone.
确定日期需要时区。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
We apply that time zone object to the Instant
to obtain a ZonedDateTime
. From that we extract a date-only value (a LocalDate
) as our goal is to compare dates (not hours, minutes, etc.).
我们将该时区对象应用于Instant
以获取ZonedDateTime
. 我们从中提取一个仅限日期的值 (a LocalDate
),因为我们的目标是比较日期(而不是小时、分钟等)。
ZonedDateTime zdt1 = ZonedDateTime.ofInstant( instant , zoneId );
LocalDate localDate1 = LocalDate.from( zdt1 );
Do the same to the second java.util.Date
object we need for comparison. I'll just use the current moment instead.
对java.util.Date
我们需要比较的第二个对象执行相同操作。我只会使用当前时刻。
ZonedDateTime zdt2 = ZonedDateTime.now( zoneId );
LocalDate localDate2 = LocalDate.from( zdt2 );
Use the special isEqual
method to test for the same date value.
使用特殊isEqual
方法测试相同的日期值。
Boolean sameDate = localDate1.isEqual( localDate2 );
回答by amanteaux
Java 8
爪哇 8
If you are using Java 8 in your project and comparing java.sql.Timestamp
, you could use the LocalDate
class:
如果您在项目中使用 Java 8 并进行比较java.sql.Timestamp
,则可以使用LocalDate
该类:
sameDate = date1.toLocalDateTime().toLocalDate().equals(date2.toLocalDateTime().toLocalDate());
If you are using java.util.Date
, have a look at Istvan answer which is less ambiguous.
如果您正在使用java.util.Date
,请查看 Istvan 的答案,该答案不那么模棱两可。
回答by Istvan
Convert dates to Java 8 java.time.LocalDate as seen here.
日期转换为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));
回答by evya
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);
}