0

我有一个 TreeMap <DDate, Integer>

DDate 只包含月份和年份(月份为 0 索引,如在 Java 中,JAN = 0);

我的比较没有返回正确的东西:

@Override
public int compareTo(DDDate o) {

    Calendar cal1 = Calendar.getInstance();
    cal1.setTimeZone(TimeZone.getTimeZone("UTC"));
    cal1.set(year, month, 1); // year is 2012, month is 1

    Calendar cal2 = Calendar.getInstance();
    cal2.setTimeZone(TimeZone.getTimeZone("UTC"));
    cal2.set(o.getYear(), o.getMonth(), 1); // year is 2012, month is 1


    Log.log("COMPARING: " + format.format(cal1.getTime())); // COMPARING: 20120101
    Log.log("COMPARING: " + format.format(cal2.getTime())); // COMPARING: 20120101

    Log.log((cal1.getTime().getTime())); // 1325413927678
    Log.log((cal2.getTime().getTime())); // 1325413927679

    Log.log("WILL RETURN: " + cal1.getTime().compareTo(cal2.getTime())); // WILL RETURN: -1

    return cal1.getTime().compareTo(cal2.getTime());

}

为什么同一日期的两个日历对象存在差异?(1325413927678 与 1325413927679)

谢谢!

仅供参考:此方法工作一段时间,然后在某个点停止工作。

PS - 我知道这是矫枉过正,我可以有一个更简单的 compareTo,但请幽默。

编辑-修复

使用 JodaTime 的 LocalDate。

或者这样做:

Calendar cal1 = Calendar.getInstance();
cal1.setTimeZone(TimeZone.getTimeZone("UTC"));
cal1.clear();
cal1.set(year, month, 1); // year is 2012, month is 1
4

5 回答 5

6

您正在设置年、月和日 - 但这不会改变一天中的时间。内部时钟必须在两次调用之间滴答作响Calendar.getInstance,因此它们具有不同的“自 Unix 纪元以来的毫秒数”值。

就我个人而言,我建议使用Joda Time而不是java.util.Calendarand java.util.Date- 这样您就可以表示您真正感兴趣的内容,例如LocalDate.

于 2013-10-28T14:40:39.857 回答
2

因为你在两个不同的时间制作它们。

Calendar cal1 = Calendar.getInstance(); // time now 
cal1.setTimeZone(TimeZone.getTimeZone("UTC")); // time ticking
cal1.set(year, month, 1); // year is 2012, month is 1 // time ticking

Calendar cal2 = Calendar.getInstance(); // time two ticks later

你已经改变了年月日,但是小时分钟和秒保持不变,继续移动和变化。

正如这里提到的
http://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#set(int , int, int, int, int)
保留其他字段值,您应该使用 clear() 将它们设置为零。此外,正如乔恩推荐的那样,我会说使用 Joda 时间会好得多。

于 2013-10-28T14:41:26.983 回答
0

在设置日期之前尝试使用 clear() 方法:

final Calendar cal1 = Calendar.getInstance();
cal1.clear();
cal1.setTimeZone(TimeZone.getTimeZone("UTC"));
cal1.set(2012, 1, 1); // year is 2012, month is 1

final Calendar cal2 = Calendar.getInstance();
cal2.clear();
cal2.setTimeZone(TimeZone.getTimeZone("UTC"));
cal2.set(2012, 1, 1); // year is 2012, month is 1

cal1.getTime().compareTo(cal2.getTime()); // Returns 0
于 2013-10-28T14:57:55.723 回答
0

You should initialize the calendar properly to "no time" (0 ticks), this should fix the issue.

cal1.setTime(new Date(0));
cal1.set(year, month, 1);
于 2013-10-28T14:42:52.713 回答
0

Jon Skeet 的回答是正确的。

下面是一些示例代码,展示了如何使用Joda-Time进行日期比较。Joda-Time 比 Java 捆绑的 Date/Calendar 类要容易得多。只需要 3 行代码来实例化和比较。

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.

// Joda-Time - The popular alternative to Sun/Oracle's notoriously bad date, time, and calendar classes bundled with Java 7 and earlier.
// http://www.joda.org/joda-time/

// Joda-Time will become outmoded by the JSR 310 Date and Time API introduced in Java 8.
// JSR 310 was inspired by Joda-Time but is not directly based on it.
// http://jcp.org/en/jsr/detail?id=310

// By default, Joda-Time produces strings in the standard ISO 8601 format.
// https://en.wikipedia.org/wiki/ISO_8601

// New DateTime instance with default time zone. For specific zone, call "withZone()" method.
org.joda.time.DateTime dateTimeX = new org.joda.time.DateTime();
org.joda.time.DateTime dateTimeY = new org.joda.time.DateTime(2012, 1, 1, 0, 0); // First of January.

// To compare the date only while ignoring the time, set identical time component on both.
// Call withTimeAtStartOfDay() to set same time value.
Boolean isSameDate = dateTimeX.withTimeAtStartOfDay().isEqual(dateTimeY.withTimeAtStartOfDay());
于 2013-10-28T21:28:08.043 回答