为什么GregorianCalendar.getTimeInMillis()返回错误的值?

时间:2016-03-02 07:46:41

标签: android android-calendar gregorian-calendar

我想以两个日期之间的天数形式计算时间差。所以我写了以下代码:

public static int calculateTimeGap(long start, long end) {
    GregorianCalendar calendar1 = new GregorianCalendar();
    calendar1.setTimeInMillis(start);
    System.out.println("calendar1:");
    showCalendar(calendar1);

    GregorianCalendar calendar2 = new GregorianCalendar();
    calendar2.setTimeInMillis(end);
    System.out.println("calendar2:");
    showCalendar(calendar2);

    int gap = (int) (end / 86400000 - start / 86400000);
    System.out.println("gap in days:" + gap);
    return gap;
}

以下是输出:

03-02 15:28:08.021 20814-20814/com.ywwynm.everythingdone I/System.out: calendar1:
03-02 15:28:08.021 20814-20814/com.ywwynm.everythingdone I/System.out: year: 2016
03-02 15:28:08.021 20814-20814/com.ywwynm.everythingdone I/System.out: month: 3
03-02 15:28:08.021 20814-20814/com.ywwynm.everythingdone I/System.out: day: 2
03-02 15:28:08.021 20814-20814/com.ywwynm.everythingdone I/System.out: week: 3
03-02 15:28:08.021 20814-20814/com.ywwynm.everythingdone I/System.out: hour: 15
03-02 15:28:08.021 20814-20814/com.ywwynm.everythingdone I/System.out: minute: 28
03-02 15:28:08.021 20814-20814/com.ywwynm.everythingdone I/System.out: second: 8
03-02 15:28:08.021 20814-20814/com.ywwynm.everythingdone I/System.out:  
03-02 15:28:08.021 20814-20814/com.ywwynm.everythingdone I/System.out: calendar2:
03-02 15:28:08.021 20814-20814/com.ywwynm.everythingdone I/System.out: year: 2016
03-02 15:28:08.021 20814-20814/com.ywwynm.everythingdone I/System.out: month: 3
03-02 15:28:08.022 20814-20814/com.ywwynm.everythingdone I/System.out: day: 3
03-02 15:28:08.022 20814-20814/com.ywwynm.everythingdone I/System.out: week: 4
03-02 15:28:08.022 20814-20814/com.ywwynm.everythingdone I/System.out: hour: 1
03-02 15:28:08.022 20814-20814/com.ywwynm.everythingdone I/System.out: minute: 0
03-02 15:28:08.022 20814-20814/com.ywwynm.everythingdone I/System.out: second: 0
03-02 15:28:08.022 20814-20814/com.ywwynm.everythingdone I/System.out:  
03-02 15:28:08.022 20814-20814/com.ywwynm.everythingdone I/System.out: gap in days:0

你可以看到两个GregorianCalendar呈现不同的日子,但最后我们得到一个等于0的差距。

此方法的参数startend来自以下代码:

GregorianCalendar curCalendar = new GregorianCalendar();
long start = curCalendar.getTimeInMillis(); // parameter start

GregorianCalendar calendar = new GregorianCalendar(2016, Calendar.MARCH, 3, 1, 0);
long end = calendar.getTimeInMillis(); // parameter end

所以行为很奇怪。我认为gregorianCalendar.getTimeInMillis()将始终返回正确且与时区无关的值,以便它可以用作计算和比较时间的稳定且值得信赖的标准。但是,如图所示的代码和输出,这是错误的。如果我考虑了我的时区(北京GMT + 8:00),请将Timezone.getDefault().getRawOffset()的偏移量添加到参数start或将其减去end,结果将是正确的。但这实际上很奇怪。

是什么让我得到错误的结果?

更新

public static void showCalendar(GregorianCalendar calendar) {
    System.out.println("year: "   +  calendar.get(Calendar.YEAR));
    System.out.println("month: "  + (calendar.get(Calendar.MONTH) + 1));
    System.out.println("day: "    +  calendar.get(Calendar.DATE));
    System.out.println("week: "   + (calendar.get(Calendar.DAY_OF_WEEK) - 1));
    System.out.println("hour: "   +  calendar.get(Calendar.HOUR_OF_DAY));
    System.out.println("minute: " +  calendar.get(Calendar.MINUTE));
    System.out.println("second: " +  calendar.get(Calendar.SECOND));
    System.out.println(" ");
}

2 个答案:

答案 0 :(得分:1)

  

你可以看到两个GregorianCalendars呈现不同的日子,但最后我们得到一个等于0的差距。

是的,那是完全合理的。您将3月2日15:28:08与3月3日01:00:00进行比较。他们在不同的日期,但相隔不到一天。这里没问题。

哎呀,你可以看到相同的两个值只是一毫秒 - 他们仍然可以在不同的日期。

请注意,就时区而言,默认情况下GregorianCalendar将使用您的系统默认时区。 getTimeInMillis返回的值将始终返回自Unix纪元以来的毫秒数,因此该时区是中性的 - 但是您在此处调用的构造函数:

new GregorianCalendar(2016, Calendar.MARCH, 3, 1, 0)

...正在说"我希望代表3月3日,凌晨1点当地时间"其中当地时间表示"在您的默认时区"。

计算日期之间的差异很困难 - 我非常强烈建议您完全抛弃CalendarDate,而不是java.time如果你&#39 ;重新使用Java 8,否则使用Joda Time。然后,您可以使用LocalDate来表示没有时间的日期,并轻松找到两个日期之间的差异。

答案 1 :(得分:0)

您所测量的不是天数的差距,正如您所定义的那样。您测量的是开始和结束之间的完整24小时的数量。

在您的示例中,您的结束时间实际上距离开始时间不到24小时。所以你24小时的距离是0。

如果要测量当前时区午夜定义的天数差异,即天数之间的界限,则应该比较两个日历对象的DAY_OF_YEARYEAR值。