时区不同,“日历分钟”的设置也不同



我发现JAVA日历类有一个奇怪的行为。当我将分钟设置为0时,根据所使用的时区,结果会有所不同。

有人知道为什么吗?

示例代码

import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class CalendarTest {
    public static void main(String[] args) {
        Date date = new Timestamp(1477780200000L);
        System.out.println(date); // 2016-10-30 00:30:00.0
        testMethod(date, Calendar.getInstance(TimeZone.getTimeZone("CET"))); // Sun Oct 30 02:00:00 CET 2016
        testMethod(date, Calendar.getInstance(TimeZone.getTimeZone("GMT+1"))); // Sun Oct 30 02:00:00 CEST 2016
    }
    private static void testMethod(Date date, Calendar c) {
        c.setTime(date);
        c.add(Calendar.HOUR_OF_DAY, 2);
        c.set(Calendar.MINUTE, 0);
        System.out.println(c.getTime());
    }
}




编辑(使我的问题更容易理解):
改变testMethod

Sun Oct 30 02:30:00 CEST 2016.

private static void testMethod(Date date, Calendar c) {
    c.setTime(date);
    c.add(Calendar.HOUR_OF_DAY, 2);
    System.out.println(c.getTime());
}

您可以在下面的示例代码中看到,显示的日期与实时(以毫秒为单位)非常不同。问题是Sun Oct 30 02:00:00 CET 2016同时存在于CETCEST时区。当切换CEST => CET时,您将返回一个小时(产生小时重叠)。对于Calendar对象,这是非常棘手的,因为您要在所选时区中表示时间变化。当您想在这个非常特定的时区重置分钟时,Calendar必须发现您在哪个时区表示更改。

我不是100% Calendar是如何处理这个,但在第一个例子CET中,你特别建议你要使用CET。因此,当重叠发生时,Calendar可以选择您的建议(CET)。当您使用GMT来表示它时,Calendar必须选择CETCEST时区之一,并选择CEST

public static void main(String[] args) {
    Date date = new Timestamp(1477780200000L);
    System.out.println(date); // 2016-10-30 00:30:00.0
    Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("CET"));
    calendar.setTime(date);
    print(1, calendar); // 1: Sun Oct 30 00:30:00 CEST 2016 | 1477780200000
    calendar.add(Calendar.HOUR_OF_DAY, 2);
    print(2, calendar); // 2: Sun Oct 30 02:30:00 CEST 2016 | 1477787400000
    calendar.set(Calendar.MINUTE, 0); // minutes expressed in CET
    print(3, calendar); // 3: Sun Oct 30 02:00:00 CET 2016 | 1477789200000
    System.out.println("--");
    calendar = Calendar.getInstance(TimeZone.getTimeZone("CET"));
    calendar.setTime(date);
    print(4, calendar); // 4: Sun Oct 30 00:30:00 CEST 2016 | 1477780200000
    calendar.add(Calendar.HOUR_OF_DAY, 2);
    print(5, calendar); // 5: Sun Oct 30 02:30:00 CEST 2016 | 1477787400000
    calendar.set(Calendar.MINUTE, 0); // minutes expressed in CET
    print(6, calendar); // 6: Sun Oct 30 02:00:00 CET 2016 | 1477789200000
    System.out.println("--");
    calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+1"));
    calendar.setTime(date);
    print(4, calendar); // 4: Sun Oct 30 00:30:00 CEST 2016 | 1477780200000
    calendar.add(Calendar.HOUR_OF_DAY, 2);
    print(5, calendar); // 5: Sun Oct 30 02:30:00 CEST 2016 | 1477787400000
    calendar.set(Calendar.MINUTE, 0); // minutes expressed in GMT
    print(6, calendar); // 6: Sun Oct 30 02:00:00 CEST 2016 | 1477785600000
}
private static void print(int prefix, Calendar calendar) {
    System.out.println(prefix + ": " + calendar.getTime() + " | " + calendar.getTimeInMillis());
}

更新更有趣的是Calendar方法getTimeInMillis:
public long getTimeInMillis() {
    if (!isTimeSet) {
        updateTime();
    }
    return time;
}

正如你所看到的,时间是更新的,当你得到它!每次使用set方法(如calendar.set(Calendar.MINUTE, 0))时,有一个标志isTimeSet被设置为false。这意味着您的时间在正确的时区/纪元等方面变得无效。这个方法只是将给定的日历字段设置为给定的值,仅此而已。此外,如果您的设置有效,此方法不会进行任何额外的检查。另一方面,add方法尊重日历规则并优雅地移动日期。

总结。您将分钟设置为0,这将强制日历重新计算日期。你是对的,set是有问题的。

相关内容

  • 没有找到相关文章

最新更新