我想比较两个Calendar对象,看看它们是否都包含相同的日期。我不关心天数以下的任何价值。
我已经实现了这一点,我无法考虑它应该失败的任何情况:
private static boolean areEqualDays(Calendar c1, Calendar c2) {
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
return (sdf.format(c1.getTime()).equals(sdf.format(c2.getTime())));
}
这种方法是正确的还是我应该逐个字段地比较c1和c2?
答案 0 :(得分:50)
尝试 compareTo
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
c1.compareTo(c2);
<强>返回强>:
如果参数表示的时间等于此Calendar表示的时间,则值为0;如果此Calendar的时间早于参数表示的时间,则小于0的值;如果此日历的时间在参数表示的时间之后,则值大于0。
修改强>
import org.apache.commons.lang3.time.DateUtils;
您可以使用DateUtils.isSameDay
检查是否在同一天。
boolean isSameDay = DateUtils.isSameDay(c1, c2);
2002年3月28日13:45和2002年3月28日06:01会回归真实。 2002年3月28日13:45和2002年3月12日13:45将返回虚假。
答案 1 :(得分:17)
我已经实现了这一点,我无法考虑它应该失败的任何情况
如果两个日历位于不同的时区,它将会失败 - 它们可能代表完全相同的毫秒,但该瞬间可能会根据时区落入不同的日期。
如果两个日历代表不同的日历系统,它也可能会失败 - 即使它们代表相同的“日期”,如果两个日历以不同的方式代表那一天,你可以说它应该失败。
就个人而言,我强烈建议您使用Joda Time类型的{{3}}来代表日期 - 这样可以摆脱时区问题,但是不日历系统问题。如果你总是可以假设你使用相同的日历系统,那就没关系。
(另外,仅仅为了比较而执行字符串操作很难看 - 我只是直接检查LocalDate
等。)
答案 2 :(得分:9)
您可以使用DateUtils
之类的内容public boolean isSameDay(Calendar cal1, Calendar cal2) {
if (cal1 == null || cal2 == null)
return false;
return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA)
&& cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR)
&& cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
}
答案 3 :(得分:1)
Calendar类有一个方法compareTo。你为什么不直接打电话呢?
答案 4 :(得分:1)
要比较特定字段的两个日期,首先使用Calendar.set(int field,int value)将该字段下面的所有字段设置为最低值(取决于字段为0或1),然后比较。 要比较cal1和cal2之间的天数差异,在调用cal1.compare(cal2)之前,将两个对象上的MINUTE,SECOND和MILLISECOND设置为0.
答案 5 :(得分:1)
( ( GregorianCalendar ) c1 )
.toZonedDateTime()
.toLocalDate()
.isEqual(
( ( GregorianCalendar ) c2 )
.toZonedDateTime()
.toLocalDate()
)
Answer by Jon Skeet是正确的。但是它使用 Joda-Time 的建议已过时。
与最早的Java版本捆绑在一起的日期时间类简直太糟糕了。例如,Date
和Calendar
及其通常的具体类GregorianCalendar
。 JSR 310年的采用将这些类替换为现代的 java.time 类。 JSR 310由发明 Joda-Time 的人Stephen Colebourne领导。
Calendar
➙GregorianCalendar
➙ZonedDateTime
➙LocalDate
如果通过Calendar
将ZonedDateTime
转换为GregorianCalendar
。
if( myCal instanceOf GregorianCalendar ) {
GregorianCalendar gc = ( GregorianCalendar ) myCal ;
}
然后将其转换为替换项ZonedDateTime
。
ZonedDateTime zdt = gc.toZonedDateTime() ;
GregorianCalendar
和ZonedDateTime
都代表时刻,是时间轴上的特定点。通过两个不同时区(例如日本东京和美国俄亥俄州托莱多)观察的那一刻可能落在两个不同的日期。
要表示仅日期,没有日期,没有时区或UTC偏移量,请使用LocalDate
类。
LocalDate ld = zdt.toLocalDate() ;
您可以比较一对LocalDate
对象。
boolean isBefore = localDateX.isEqual( localDateY ) ;
在考虑日期之前,您可能需要将两个ZonedDateTime
对象调整为相同的时区。
ZoneId zNewYork = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdtXNewYork = zdtX.withZoneSameInstant( zNewYork ) ;
LocalDate localDateX = zdtXNewYork.toLocalDate() ;
java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和SimpleDateFormat
。
要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
目前位于Joda-Time的maintenance mode项目建议迁移到java.time类。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
在哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval
,YearWeek
,YearQuarter
和more。