比较两个java.util.Dates以查看它们是否在同一天

我需要比较两个Date (例如date1date2 ),并提出一个boolean sameDay是真实的两个Date共享同一天,如果不是。

我怎样才能做到这一点? 这里似乎有一个混乱的旋风……如果可能的话,我想避免在JDK以外的其他依赖。

澄清:如果date1date2共享同一年份,月份和date,则sameDay为true,否则为false。 我意识到这需要了解一个时区的知识……只要我知道行为是什么,那么通过一个时区将是很好的,但我可以住在格林尼治标准时间或当地时间。

再次澄清:

 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 
 Calendar cal1 = Calendar.getInstance(); Calendar cal2 = Calendar.getInstance(); cal1.setTime(date1); cal2.setTime(date2); boolean sameDay = cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR); 

请注意,“同一天”并不像在不同时区可能涉及时听起来那么简单。 上面的代码将在这两个date计算相对于它运行的计算机使用的时区的一天。 如果这不是你所需要的,那么在你决定了“同一天”的意思之后,你必须把相关的时区传递给Calendar.getInstance()调用。

是的,Joda时间的LocalDate会使整个事情变得更加简单和容易(虽然涉及时区的困难也会存在)。

怎么样:

 SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd"); return fmt.format(date1).equals(fmt.format(date2)); 

如果需要,您还可以将时区设置为SimpleDateFormat。

我使用“apache commons lang”包来做到这一点(即org.apache.commons.lang.time.DateUtils)

 boolean samedate = DateUtils.isSameDay(date1, date2); //Takes either Calendar or Date objects 

您可以通过计算每个date的Julian日数然后比较这些date来避免外部依赖性和使用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; } 

乔达时间

至于添加依赖项,恐怕java.util.Date&.Calendar真的太糟糕了,我对任何新项目做的第一件事就是添加Joda-Time库。 在Java 8中,您可以使用受Joda-Time启发的新的java.time包。

Joda-Time的核心是DateTime类。 与java.util.Date不同,它理解其分配的时区( DateTimeZone )。 从juDate转换时,分配一个区域。

 DateTimeZone zone = DateTimeZone.forID( "America/Montreal" ); DateTime dateTimeQuébec = new DateTime( date , zone ); 

LocalDate

validation两个date时间是否在同一date的一种方法是转换为LocalDate对象。

该转换取决于分配的时区。 要比较LocalDate对象,它们必须已经被转换为相同的区域。

这是一个小实用的方法。

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

更好的是另一个参数,指定时区,而不是假定应该使用第一个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表示

另一种方法是创build每个date时间的date部分的string表示,然后比较string。

同样,指定的时区是至关重要的。

 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; 

时间跨度

广义的解决scheme是定义一个时间跨度,然后询问跨度是否包含您的目标。 这个例子代码是Joda-Time 2.4。 请注意,“午夜”相关课程已被弃用。 而是使用withTimeAtStartOfDay方法。 Joda-Time提供了三种types来表示不同时间段的时间间隔,时间段和持续时间。

使用“半开放”的方法,其中跨度的开始是包容和结束排他。

目标的时区可能与区间的时区不同。

 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和更高版本带有java.time框架。 受JSR 310定义的Joda-Time的启发,并由ThreeTen-Extra项目扩展。 参见教程 。

Joda-Time的制造商已经指示我们尽快转移到java.time。 与此同时,乔达时代继续作为一个积极维护的项目。 但是,期待未来的工作只发生在java.time和ThreeTen-Extra而不是Joda-Time。

简要总结java.time … Instant是UTC中时间轴上的一个时刻。 应用时区( ZoneId )以获取ZonedDateTime对象。 要离开时间线,为了获得date时间的模糊的不确定的想法,使用“本地”类: LocalDateTimeLocalDateLocalTime

本答案的Joda-Time部分讨论的逻辑适用于java.time。

旧的java.util.Date类具有用于转换为java.time的新的toInstant方法。

 Instant instant = yourJavaUtilDate.toInstant(); // Convert into java.time type. 

确定一个date需要一个时区。

 ZoneId zoneId = ZoneId.of( "America/Montreal" ); 

我们将该时区对象应用于Instant以获取ZonedDateTime 。 从中我们提取仅限date的值( LocalDate ),因为我们的目标是比较date(而不是小时,分钟等)。

 ZonedDateTime zdt1 = ZonedDateTime.ofInstant( instant , zoneId ); LocalDate localDate1 = LocalDate.from( zdt1 ); 

对我们需要比较的第二个java.util.Date对象做同样的事情。 我只是使用当前的时刻。

 ZonedDateTime zdt2 = ZonedDateTime.now( zoneId ); LocalDate localDate2 = LocalDate.from( zdt2 ); 

使用特殊的isEqual方法来testing相同的date值。

 Boolean sameDate = localDate1.isEqual( localDate2 ); 
 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); } 

Java 8

如果您在项目中使用Java 8并比较java.sql.Timestamp ,则可以使用LocalDate类:

 sameDate = date1.toLocalDateTime().toLocalDate().equals(date2.toLocalDateTime().toLocalDate()); 

如果你正在使用java.util.Date ,看看Istvan的答案是不太模糊的。

将date转换为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)); 

除了Binil Thomas的解决scheme

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

用法

  isOnSameDay(date1,date2,date3 ...); //or isOnSameDay(mydates); 

对于Android用户:

您可以使用DateUtils.isToday(dateMilliseconds)来检查给定date是否为当天。

API参考: https : //developer.android.com/reference/android/text/format/DateUtils.html#isToday(long)

 public static boolean validSearchRange(String start, String end){ SimpleDateFormat dateFormat = new SimpleDateFormat(clientDateFormat); try { Date start_date = dateFormat.parse(start); Date end_date = dateFormat.parse(end); return !start_date.after(end_date); } catch (ParseException e) { e.printStackTrace(); } return false; } 

您可以应用与SimpleDateFormat解决scheme相同的逻辑,而不依赖于SimpleDateFormat

 date1.getFullYear()*10000 + date1.getMonth()*100 + date1.getDate() == date2.getFullYear()*10000 + date2.getMonth()*100 + date2.getDate()