仅比较两个日期的时间部分,忽略日期部分

时间:2011-10-06 14:52:12

标签: java datetime date time

给定两个Date对象,比较它们的时间部分之间的差异,完全忽略年,月和日,有什么好方法?

这与this question完全相反。

更新:以下是未来参考的最终代码:

private long differenceBetween(Date currentTime, Date timeToRun)
{
    Calendar currentCal = Calendar.getInstance();
    currentCal.setTime(currentTime);

    Calendar runCal = Calendar.getInstance();
    runCal.setTime(timeToRun);
    runCal.set(Calendar.DAY_OF_MONTH, currentCal.get(Calendar.DAY_OF_MONTH));
    runCal.set(Calendar.MONTH, currentCal.get(Calendar.MONTH));
    runCal.set(Calendar.YEAR, currentCal.get(Calendar.YEAR));

    return currentCal.getTimeInMillis() - runCal.getTimeInMillis();
}

8 个答案:

答案 0 :(得分:31)

如果要比较日期的基础二进制(long int)值,可以执行以下操作:

public int compareTimes(Date d1, Date d2)
{
    int     t1;
    int     t2;

    t1 = (int) (d1.getTime() % (24*60*60*1000L));
    t2 = (int) (d2.getTime() % (24*60*60*1000L));
    return (t1 - t2);
}

附录1

此技术具有速度优势,因为它直接使用long对象的基础Date值,而不是在刻度和日历组件之间进行转换(这相当昂贵且速度慢)。它比弄乱Calendar个对象要简单得多。

附录2

上面的代码将时间差作为int返回,这对于任何一对都是正确的,因为它完全忽略日期的年/月/日部分,以及任何两次之间的差异不超过86,400,000 ms(= 1000 ms / sec×60 sec / min×60 min / hr×24 hr / day)。

答案 1 :(得分:19)

您可以考虑使用Joda时间的DateTimeComparator.getTimeOnlyInstance()作为比较器,该比较器仅根据时间比较两个Joda日期。

例如:

DateTimeComparator comparator = DateTimeComparator.getTimeOnlyInstance();
comparator.compare(date1, date2);

请参阅http://joda-time.sourceforge.net/api-release/org/joda/time/DateTimeComparator.html#getTimeOnlyInstance()

答案 2 :(得分:5)

看一下Calendar课程。它支持从给定的Date中提取小时,分钟和秒。

Calendar calendar = Calendar.getInstance();
calendar.setTime(yourDateObject);
int hour = calendar.get(Calendar.HOUR);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);

答案 3 :(得分:2)

tl; dr

使用现代的 java.time 类。

请注意,您要求的比较可能没有意义,因为特定的一天在不同区域的不同日期可能具有不同的含义。

Duration                                  // Span of time, with resolution of nanoseconds.
.between(                                 // Calculate elapsed time.
    LocalTime.now(                        // Get current time-of-day…
        ZoneId.of( "Pacific/Auckland" )   // … as seen in a particular time zone.
    )                                     // Returns a `LocalTime` object.
    ,
    myJavaUtilDate                        // Avoid terrible legacy date-time classes such as `java.util.Date`.
    .toInstant()                          // Convert from `java.util.Date` to `java.time.Instant`, both representing a moment in UTC.
    .atZone(                              // Adjust from UTC to a particular time zone. Same moment, same point on the timeline, different wall-clock time.
        ZoneId.of( "Pacific/Auckland" )   // Specify time zone by proper naming in `Continent/Region` format, never 2-4 letter pseudo-zones such as `PST`, `CEST`, `CST`, `IST`, etc.
    )                                     // Returns a `ZonedDateTime` object.
    .toLocalTime()                        // Extract the time-of-day without the date and without a time zone.
)                                         // Returns a `Duration` object.
.toMillis()                               // Calculate entire span-of-time in milliseconds. Beware of data-loss as `Instant` uses a finer resolution the milliseconds, and may carry microseconds or nanoseconds.

我建议绕过类型安全且易于解释的Duration对象,而不是仅仅整数毫秒。

java.time

现代方法使用 java.time 类代替了可怕的旧类,例如DateCalendarSimpleDateFormat

将您的java.util.Date(以UTC表示的时间)转换为Instant。使用添加到旧类中的新转换方法。

Instant instant = myJavaUtilDate.toInstant() ;

这代表UTC的时刻。确定日期和时间需要time zone。在任何给定的时刻,日期和时间在全球范围内都会有所不同。例如,Paris France午夜之后的几分钟是新的一天,而Montréal Québec仍然是“昨天”。

如果未指定时区,则JVM隐式应用其当前的默认时区。该默认值可能在运行时(!)期间change at any moment,因此您的结果可能会有所不同。最好将您的[期望/期望时区] [2]明确指定为参数。

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用2-4个字母的缩写,例如ESTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

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

如果要使用JVM的当前默认时区,请提出要求并作为参数传递。如果省略,则会隐式应用JVM的当前默认值。最好明确一点,因为默认值可能会在运行时的任何时候被JVM中任何应用程序的任何线程中的任何代码更改。

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

ZoneId分配给Instant以产生ZonedDateTime对象。

ZonedDateTime zdt = instant.atZone( z ) ;

提取时间部分,不包含日期和时区。

LocalTime lt = zdt.toLocalTime() ;

比较。用Duration计算经过的时间。

Duration d = Duration.between( ltStart , ltStop ) ;

请注意,这是不公平的比较。日期并非总是24小时长,并且并非所有时间值在所有区域的所有日期都有效。例如,在美国的夏令时转换中,可能根本没有凌晨2点。因此,凌晨1点到凌晨4点可能是一个日期3个小时,而另一个日期只有2个小时。


关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

目前位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

答案 4 :(得分:1)

如果你不能使用JODA,

创建2个日历对象,将年,月和日设置为0。

比较他们......

答案 5 :(得分:1)

如果JODA不是一个选项,最短的方法之一可能是将时间转换为字符串然后进行比较。

DateFormat df = new SimpleDateFormat("HHmmssSZ");
df.format(date1).equals(df.format(date2));

答案 6 :(得分:0)

不知道这个练习有多好或有效,但是我使用Date对象编写了一个简单的函数,用于我的目的。它返回true或false是第一个日期值大于第二个日期值。输入d1&& d2是Date对象。

function CompareTimes(d1, d2) {
             if (d1.getHours() < d2.getHours()) {
                 return false;
             }
             if (d1.getHours() > d2.getHours()) {
                 return true;

             } else {
                 return (d1.getMinutes() > d2.getMinutes());
             }
};

答案 7 :(得分:0)

如果您只想比较日期的时间部分,那么这将为您提供正确的结果 -

#welcome_text_div {
    background-color:red;
    width:800px;
    height:300px;
    display:flex;
    align-items:center;
    justify-content:center;
}

#welcome_text {
    color: white;
    font-family: sans-serif;
    text-transform: uppercase;
    font-weight: bold;
    font-size: 55px;
}