简体   繁体   English

比较两个 Java 日历时如何规范时区?

[英]How can I normalize timezones when comparing two Java Calendars?

I'm furious with the 7th of November.我对 11 月 7 日感到愤怒。

I've written a method to calculate the number of days between two Java Date objects (before it gets mentioned, JodaTime is not an option) -- the method works the majority of the time, but when the start xor end date occurs during daylight savings time, the output is off by a day.我已经编写了一个方法来计算两个 Java Date 对象之间的天数(在提到它之前,JodaTime 不是一个选项)——该方法大部分时间都有效,但是当开始异或结束日期发生在白天时节省时间,输出减少一天。

Do Calendars have some way of overriding the timezone of dates?日历是否有某种方法可以覆盖日期的时区? I don't care what timezone the dates are actually in, but they need to be the same one!我不在乎日期实际上在哪个时区,但它们必须是相同的!

Code below:代码如下:

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)
}

Never try to count days using 1000*60*60*24 as a day.永远不要尝试使用 1000*60*60*24 作为一天来计算天数。 It's just plain wrong.这完全是错误的。 If you really need to implement the calculation yourself for some reason, use the YEAR and DAY_OF_YEAR fields on the Calendar to count differences in actual days.如果您出于某种原因确实需要自己实施计算,请使用日历上的 YEAR 和 DAY_OF_YEAR 字段来计算实际天数的差异。

You cannot simply "override" the timezone of a java.util.Date because it has no timezone information associated with it.您不能简单地“覆盖” java.util.Date的时区,因为它没有与之关联的时区信息。 You need to know what timezone it was intended to be interpreted in, and use that timezone when converting it to a human representation.您需要知道它打算在哪个时区进行解释,并在将其转换为人类表示时使用该时区。 Arbitrarily using UTC to interpret it will, as you have discovered, not deliver consistent results!正如您所发现的那样,随意使用 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
    }

  }

Your system should store all timestamps in UTC!您的系统应以 UTC 格式存储所有时间戳!
If not you will never get that to work!否则,您将永远无法使用它!
Then the difference calculation is simple.那么差值计算就很简单了。

If you need to display localTime too, you have to store the TimeZone together with the date as a pair: Example: (long timeUtc, int timezoneOffSetToUtc).如果您还需要显示 localTime,则必须将 TimeZone 与日期一起存储为一对:示例:(long timeUtc, int timezoneOffSetToUtc)。 The timezoneOffSetToUtc is the offset valid at the creation date of the pair. timezoneOffSetToUtc 是在该对的创建日期有效的偏移量。

The TimeZone should only be instantiated from String like ("Austria / Vienna").时区应该只从像(“奥地利/维也纳”)这样的字符串实例化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM