我需要比较两个Date
s(例如date1
和date2
),并得出在同一天boolean sameDay
这两个Date
s共享的true,否则返回false。
我怎样才能做到这一点?这里似乎有混乱的旋风……我想尽可能避免引入除JDK之外的其他依赖项。
需要说明的是:如果date1
并且date2
共享相同的年,月和日,sameDay
则为true,否则为false。我意识到这需要了解时区...传入时区会很好,但是只要我知道行为是什么,我就可以使用GMT或本地时间。
再次澄清:
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.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR) &&
cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR);
请注意,“同一天”并不是一个简单的概念,而是涉及不同时区时听起来很简单。上面的代码将针对两个日期计算相对于其所运行的计算机所使用的时区的日期。如果这不是您所需要的,则在Calendar.getInstance()
确定“同一天”的确切含义之后,您必须将相关的时区传递给呼叫。
是的,Joda TimeLocalDate
可以使整个过程变得更加整洁和轻松(尽管存在与时区相同的困难)。
怎么样:
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
您可以通过计算每个日期的儒略日编号,然后进行比较来避免使用日历的外部依赖性和性能损失。
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
验证两个日期时间是否在同一日期上的一种方法是将其转换为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 );
}
字符串表示
另一种方法是创建每个日期时间的日期部分的字符串表示形式,然后比较字符串。
同样,分配的时区至关重要。
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;
时间跨度
通用解决方案是定义时间跨度,然后询问该跨度是否包含您的目标。此示例代码在Joda-Time 2.4中。请注意,不建议使用“午夜”相关的类。而是使用该withTimeAtStartOfDay
方法。Joda-Time提供了三个类以各种方式表示时间跨度:“间隔”,“周期”和“持续时间”。
使用“半开放”方法,其中跨度的开始是包含端点的,结束是包含端点的。
目标的时区可以与间隔的时区不同。
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。同时,Joda-Time继续作为一个积极维护的项目。但是希望以后的工作只会在java.time和ThreeTen-Extra中发生,而不是在Joda-Time中发生。
概括地说,总结java.time……Instant
是UTC时间轴上的时刻。应用时区(ZoneId
)获取ZonedDateTime
对象。动销的时间表,以获得的日期时间的模糊不定主意,使用“本地”类:LocalDateTime
,LocalDate
,LocalTime
。
此答案的“乔达时间”部分中讨论的逻辑适用于java.time。
旧的java.util.Date类具有toInstant
用于转换为java.time的新方法。
Instant instant = yourJavaUtilDate.toInstant(); // Convert into java.time type.
确定日期需要一个时区。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
我们将该时区对象应用于Instant
以获得ZonedDateTime
。从中,我们提取仅日期的值(a LocalDate
),因为我们的目标是比较日期(而不是小时,分钟等)。
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
方法测试相同的日期值。
Boolean sameDate = localDate1.isEqual( localDate2 );
日期转换为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));
Java 8
如果您在项目中使用Java 8进行比较java.sql.Timestamp
,则可以使用以下LocalDate
类:
sameDate = date1.toLocalDateTime().toLocalDate().equals(date2.toLocalDateTime().toLocalDate());
如果您使用java.util.Date
,请查看不太模糊的Istvan答案。
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);
}
对于ANDROID用户:
您可以DateUtils.isToday(dateMilliseconds)
用来检查给定的日期是否是当前日期。
API参考:https://developer.android.com/reference/android/text/format/DateUtils.html#isToday(long)
对于Kotlin开发人员,这是具有比较格式化字符串方法的版本:
val sdf = SimpleDateFormat("yyMMdd")
if (sdf.format(date1) == sdf.format(date2)) {
// same day
}
这不是最好的方法,但它又短又有效。
除了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;
}
用法
isOnSameDay(date1,date2,date3 ...);
//or
isOnSameDay(mydates);
您可以应用与SimpleDateFormat解决方案相同的逻辑,而无需依赖SimpleDateFormat
date1.getFullYear()*10000 + date1.getMonth()*100 + date1.getDate() ==
date2.getFullYear()*10000 + date2.getMonth()*100 + date2.getDate()
文章标签:datetime , java
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!
评论已关闭!