比较两个 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 08:43:58  来源:igfitidea点击:

Comparing two java.util.Dates to see if they are in the same day

javadatetime

提问by Jason S

I need to compare two Dates (e.g. date1and date2) and come up with a boolean sameDaywhich is true of the two Dates share the same day, and false if they are not.

我需要比较两个Dates(例如date1date2)并得出boolean sameDay两个Dates 共享同一天的情况为真,如果不是,则为假。

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 date1and date2share the same year, month, and day, then sameDayis 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.

澄清一下如果date1date2共享相同的年月日,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 LocalDatewould 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 DateTimeclass. 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 LocalDateobjects.

验证两个日期时间是否落在同一日期的一种方法是转换为LocalDate对象。

That conversion depends on the assigned time zone. To compare LocalDateobjects, 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 withTimeAtStartOfDaymethod. 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 Instantis a moment on the timeline in UTC. Apply a time zone (ZoneId) to get a ZonedDateTimeobject. 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 toInstantmethod 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 Instantto 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.Dateobject 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 isEqualmethod 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 LocalDateclass:

如果您在项目中使用 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);
    }