继续从堆栈溢出问题Java程序,以获得当前日期没有时间戳:

获得Date对象而不包含时间的最有效方法是什么?除了这两种,还有别的办法吗?

// Method 1
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date dateWithoutTime = sdf.parse(sdf.format(new Date()));

// Method 2
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
dateWithoutTime = cal.getTime();

更新:

我知道Joda-Time;我只是试图避免额外的库为这样一个简单的(我认为)任务。但根据目前的回答,Joda-Time似乎非常受欢迎,所以我可能会考虑一下。 通过高效,我的意思是我想避免像方法1所使用的那样创建临时对象字符串,同时方法2似乎是一种hack而不是解决方案。


当前回答

尽量不使用第三方库。我知道之前提到过这种方法,但这里有一种干净的方法:

  /*
    Return values:
    -1:    Date1 < Date2
     0:    Date1 == Date2
     1:    Date1 > Date2

    -2:    Error
*/
public int compareDates(Date date1, Date date2)
{
    SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyy");

    try
    {
        date1 = sdf.parse(sdf.format(date1));
        date2 = sdf.parse(sdf.format(date2));
    }
    catch (ParseException e) {
        e.printStackTrace();
        return -2;
    }

    Calendar cal1 = new GregorianCalendar();
    Calendar cal2 = new GregorianCalendar();

    cal1.setTime(date1);
    cal2.setTime(date2);

    if(cal1.equals(cal2))
    {
        return 0;
    }
    else if(cal1.after(cal2))
    {
        return 1;
    }
    else if(cal1.before(cal2))
    {
        return -1;
    }

    return -2;
}

好吧,不使用gregoricalendar可能是一种选择!

其他回答

尽量不使用第三方库。我知道之前提到过这种方法,但这里有一种干净的方法:

  /*
    Return values:
    -1:    Date1 < Date2
     0:    Date1 == Date2
     1:    Date1 > Date2

    -2:    Error
*/
public int compareDates(Date date1, Date date2)
{
    SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyy");

    try
    {
        date1 = sdf.parse(sdf.format(date1));
        date2 = sdf.parse(sdf.format(date2));
    }
    catch (ParseException e) {
        e.printStackTrace();
        return -2;
    }

    Calendar cal1 = new GregorianCalendar();
    Calendar cal2 = new GregorianCalendar();

    cal1.setTime(date1);
    cal2.setTime(date2);

    if(cal1.equals(cal2))
    {
        return 0;
    }
    else if(cal1.after(cal2))
    {
        return 1;
    }
    else if(cal1.before(cal2))
    {
        return -1;
    }

    return -2;
}

好吧,不使用gregoricalendar可能是一种选择!

如果你想要的只是看到像“YYYY-MM-DD”这样的日期,而没有其他乱七八糟的东西。“Thu May 21 12:08:18 EDT 2015”然后使用java.sql.Date。下面的例子获取当前日期:

new java.sql.Date(System.currentTimeMillis());

java.sql.Date也是java.util.Date的子类。

对于标准java运行时中的date例程,谈论没有时间戳的日期是没有意义的,因为它实际上映射到特定的毫秒而不是日期。所述毫秒本质上有一个时间附加到它,这使得它容易受到时区问题,如日光节约时间和其他日历调整。看看为什么这两次减去(1927年)会得到一个奇怪的结果?举个有趣的例子。

如果您希望使用日期而不是毫秒,则需要使用其他东西。对于Java 8,有一组新的方法可以提供您想要的东西。对于Java 7及更早版本,请使用http://www.joda.org/joda-time/

这是一个干净的解决方案,没有转换到字符串和返回,而且它不会重新计算时间几次,因为你重置时间的每个组件为零。它还使用%(模量)而不是除后乘,以避免重复操作。

它不需要第三方依赖,并且它尊重传入的calendar对象的TIMEZONE。此函数返回您传入的日期(Calendar)所在时区的上午12点的时间点。

public static Calendar date_only(Calendar datetime) {
    final long LENGTH_OF_DAY = 24*60*60*1000;
    long millis = datetime.getTimeInMillis();
    long offset = datetime.getTimeZone().getOffset(millis);
    millis = millis - ((millis + offset) % LENGTH_OF_DAY);
    datetime.setTimeInMillis(millis);
    return datetime;
}

你一定要使用java.util.Date吗?我强烈建议您使用Joda Time或java。Java 8的time包。特别是,虽然Date和Calendar总是表示时间上的某个特定时刻,没有“只是一个日期”这样的概念,但Joda time确实有一个类型表示它(LocalDate)。如果您能够使用代表您实际要做的事情的类型,那么您的代码将更加清晰。

使用Joda Time或java还有很多其他原因。时间而不是内置的java。util类型——它们通常是更好的api。如果你需要,你可以在你自己的代码边界上从java.util.Date转换到/从java.util.Date,例如为了数据库交互。