1

我对 11 月 7 日感到愤怒。

我编写了一个方法来计算两个 Java Date 对象之间的天数(在它被提及之前,JodaTime 不是一个选项)——该方法在大多数情况下都有效,但是当开始 xor 结束日期发生在白天时节省时间,输出减少了一天。

日历是否有某种方式可以覆盖日期的时区?我不在乎日期实际在哪个时区,但它们必须是同一个时区!

下面的代码:

public int getDayRange() {

        //startDate = "Sat Nov 06 00:00:00 EDT 2010";
        //endDate = "Sun Nov 07 23:59:59 EST 2010";

    TimeZone tz = TimeZone.getTimeZone("UTC");

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

    cal1.setTime(startDate);
    cal2.setTime(endDate);

    long ms1 = cal1.getTime().getTime(); 
    long ms2 = cal2.getTime().getTime(); 
    long difMs = ms2-ms1; 
    long msPerDay = 1000*60*60*24; 

    double days = difMs / msPerDay;

    return (int) Math.floor(days)+1;
        //returns 3(!!!) days (wrong)
}
4

2 回答 2

5

永远不要尝试使用 1000*60*60*24 作为一天来计算天数。这完全是错误的。如果您出于某种原因确实需要自己实现计算,请使用日历上的 YEAR 和 DAY_OF_YEAR 字段来计算实际天数的差异。

您不能简单地“覆盖” a 的时区,java.util.Date因为它没有与之关联的时区信息。您需要知道它打算在哪个时区进行解释,并在将其转换为人类表示时使用该时区。正如您所发现的,任意使用 UTC 来解释它不会提供一致的结果!

  public int getDayRange() {

        //startDate = "Sat Nov 06 00:00:00 EDT 2010";
        //endDate = "Sun Nov 07 23:59:59 EST 2010";

    TimeZone tz1 = TimeZone.getTimeZone("EDT");
    TimeZone tz2 = TimeZone.getTimeZone("EST");

    GregorianCalendar cal1 = new GregorianCalendar(tz1); 
    GregorianCalendar cal2 = new GregorianCalendar(tz2); 

    cal1.setTime(startDate);
    cal2.setTime(endDate);

    if (cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR)) {
        return cal2.get(Calendar.DAY_OF_YEAR) - cal1.get(Calendar.DAY_OF_YEAR) + 1;
    } else {
        //this gets complicated, but you can see what to do, plenty of examples online
    }

  }
于 2012-11-27T21:43:41.370 回答
1

您的系统应该以 UTC 格式存储所有时间戳!
如果没有,您将永远无法正常工作!
那么差值计算就很简单了。

如果还需要显示 localTime,则必须将 TimeZone 与日期成对存储:示例:(long timeUtc, int timezoneOffSetToUtc)。timezoneOffSetToUtc 是在该对的创建日期有效的偏移量。

TimeZone 只能从 String 实例化,例如 ("Austria / Vienna")。

于 2012-11-27T22:06:29.907 回答