我想有一个compareTo方法来忽略java.util.Date的时间部分。我想有很多方法可以解决这个问题。最简单的方法是什么?


当前回答

更新:虽然Joda Time在当时是一个很好的建议,使用java。在可能的情况下,从Java 8+替代时间库。


我倾向于使用Joda Time,这让这变得非常简单:

DateTime first = ...;
DateTime second = ...;

LocalDate firstDate = first.toLocalDate();
LocalDate secondDate = second.toLocalDate();

return firstDate.compareTo(secondDate);

编辑:正如评论中提到的,如果你使用DateTimeComparator.getDateOnlyInstance(),它甚至更简单:)

// TODO: consider extracting the comparator to a field.
return DateTimeComparator.getDateOnlyInstance().compare(first, second);

(“使用Joda Time”是几乎所有SO问题的基础,这些问题询问java.util.Date或java.util.Calendar。这是一个非常优秀的API。如果你要用日期/时间做任何重要的事情,你应该尽可能地使用它。)

如果必须使用内置API,则应该使用适当的日期和时区创建Calendar实例。然后,您可以将每个日历中的每个字段(小时、分钟、秒和毫秒)设置为0,并比较结果时间。与Joda解决方案相比,确实很讨厌:)

时区部分很重要:java.util.Date总是基于UTC。在大多数情况下,我对一个日期感兴趣,那是一个特定时区的日期。这本身将迫使您使用Calendar或Joda Time(除非您想自己考虑时区,我不建议这样做)。

android开发人员的快速参考

//Add joda library dependency to your build.gradle file
dependencies {
     ...
     implementation 'joda-time:joda-time:2.9.9'
}

示例代码(示例)

DateTimeComparator dateTimeComparator = DateTimeComparator.getDateOnlyInstance();

Date myDateOne = ...;
Date myDateTwo = ...;

int retVal = dateTimeComparator.compare(myDateOne, myDateTwo);

if(retVal == 0)
   //both dates are equal
else if(retVal < 0)
   //myDateOne is before myDateTwo
else if(retVal > 0)
   //myDateOne is after myDateTwo

其他回答

如果你真的想使用java.util。约会时,你会这样做:

public class TimeIgnoringComparator implements Comparator<Date> {
  public int compare(Date d1, Date d2) {
    if (d1.getYear() != d2.getYear()) 
        return d1.getYear() - d2.getYear();
    if (d1.getMonth() != d2.getMonth()) 
        return d1.getMonth() - d2.getMonth();
    return d1.getDate() - d2.getDate();
  }
}

或者,使用Calendar代替(首选,因为getYear()等已弃用)

public class TimeIgnoringComparator implements Comparator<Calendar> {
  public int compare(Calendar c1, Calendar c2) {
    if (c1.get(Calendar.YEAR) != c2.get(Calendar.YEAR)) 
        return c1.get(Calendar.YEAR) - c2.get(Calendar.YEAR);
    if (c1.get(Calendar.MONTH) != c2.get(Calendar.MONTH)) 
        return c1.get(Calendar.MONTH) - c2.get(Calendar.MONTH);
    return c1.get(Calendar.DAY_OF_MONTH) - c2.get(Calendar.DAY_OF_MONTH);
  }
}

首先,请注意该操作取决于时区。所以你可以选择使用国际标准时间(UTC)、计算机时区、你自己喜欢的时区或其他地方。如果你还不相信这很重要,请参阅下面我的例子。

由于您的问题不是很清楚这一点,我假设您有一个类,它具有一个实例字段,表示时间点并实现Comparable,并且您希望对象的自然顺序是根据该字段的日期而不是时间。例如:

public class ArnesClass implements Comparable<ArnesClass> {

    private static final ZoneId arnesTimeZone = ZoneId.systemDefault();

    private Instant when;

    @Override
    public int compareTo(ArnesClass o) {
        // question is what to put here
    }

}

Java 8 Java。时间类

我已经自由地将实例字段的类型从Date更改为Instant,这是Java 8中对应的类。我保证会继续下面对Date的处理。我还添加了一个时区常数。您可以将其设置为ZoneOffset。UTC或ZoneId.of("Europe/Stockholm")或您认为合适的名称(将其设置为ZoneOffset是有效的,因为ZoneOffset是ZoneId的子类)。

我选择使用Java 8类来展示解决方案。你要的是最简单的方法,对吧?:-)这是你要求的compareTo方法:

public int compareTo(ArnesClass o) {
    LocalDate dateWithoutTime = when.atZone(arnesTimeZone).toLocalDate();
    LocalDate otherDateWithoutTime = o.when.atZone(arnesTimeZone).toLocalDate();
    return dateWithoutTime.compareTo(otherDateWithoutTime);
}

如果您永远不需要when的时间部分,那么声明when为LocalDate并跳过所有转换当然更容易。那我们也不用担心时区的问题了。

现在假设由于某种原因,您不能将您的when字段声明为Instant,或者希望将其保留为老式的Date。如果你仍然可以使用Java 8,只需将其转换为Instant,然后像以前那样做:

    LocalDate dateWithoutTime = when.toInstant().atZone(arnesTimeZone).toLocalDate();

与o.when类似。

没有Java 8?

如果你不能使用java 8,有两个选项:

使用一个旧类(Calendar或SimpleDateFormat)来解决这个问题。 使用Java 8日期和时间类的后端口到Java 6和7,然后执行上述操作。我在底部附上了一个链接。不要使用JodaTime。JodaTime可能是一个很好的建议,当答案推荐它编写;但是JodaTime现在处于维护模式,所以ThreeTen后端口是一个更好的、更适合未来的选择。

传统的方式

Adamski的回答向您展示了如何使用Calendar类从Date中剥离时间部分。我建议您使用getInstance(TimeZone)来获取所需时区的Calendar实例。作为替代,你可以使用Jorn回答的后半部分的想法。

使用SimpleDateFormat实际上是使用Calendar的一种间接方式,因为SimpleDateFormat包含一个Calendar对象。然而,你可能会发现它比直接使用Calendar麻烦得多:

private static final TimeZone arnesTimeZone = TimeZone.getTimeZone("Europe/Stockholm");
private static final DateFormat formatter = new SimpleDateFormat("yyyyMMdd");
static {
    formatter.setTimeZone(arnesTimeZone);
}

private Date when;

@Override
public int compareTo(ArnesClass o) {
    return formatter.format(when).compareTo(formatter.format(o.when));
}

这是受到了罗伯的回答的启发。

时区依赖性

Why do we have to pick a specific time zone? Say that we want to compare two times that in UTC are March 24 0:00 (midnight) and 12:00 (noon). If you do that in CET (say, Europe/Paris), they are 1 am and 1 pm on March 24, that is, the same date. In New York (Eastern Daylight Time), they are 20:00 on March 23 and 8:00 on March 24, that is, not the same date. So it makes a difference which time zone you pick. If you just rely on the computer’s default, you may be in for surprises when someone tries to run your code on a computer in another place in this globalized world.

Link

链接到ThreeTen Backport, Java 8日期和时间类到Java 6和7的后端口:http://www.threeten.org/threetenbp/。

只需结合YEAR属性检查DAY_OF_YEAR

boolean isSameDay = 
firstCal.get(Calendar.YEAR) == secondCal.get(Calendar.YEAR) &&
firstCal.get(Calendar.DAY_OF_YEAR) == secondCal.get(Calendar.DAY_OF_YEAR)

编辑:

现在我们可以使用Kotlin扩展函数的强大功能

fun Calendar.isSameDay(second: Calendar): Boolean {

    return this[Calendar.YEAR] == second[Calendar.YEAR] && this[Calendar.DAY_OF_YEAR] == second[Calendar.DAY_OF_YEAR]
}

fun Calendar.compareDatesOnly(other: Calendar): Int {

    return when {
        isSameDay(other) -> 0
        before(other) -> -1
        else -> 1
    }
}

如果你使用的是Java 8,你应该使用Java .time。*类来比较日期-它优先于各种java.util。*类

如;https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html

LocalDate date1 = LocalDate.of(2016, 2, 14);
LocalDate date2 = LocalDate.of(2015, 5, 23);
date1.isAfter(date2);

`

SimpleDateFormat sdf= new SimpleDateFormat("MM/dd/yyyy")

   Date date1=sdf.parse("03/25/2015");



  Date currentDate= sdf.parse(sdf.format(new Date()));

   return date1.compareTo(currentDate);

`