繁体   English   中英

将Java日历对象设置为午夜时的行为不一致

[英]Inconsistent behavior with setting Java calendar object to midnight

我有一个Java程序,需要将Calendar对象设置为午夜,因此我按照另一篇文章的说明进行操作,该方法说明如何创建今天午夜和明天午夜的Java Date对象 ,其中将字段设置为0,例如所以:

calStart.set(Calendar.HOUR_OF_DAY, 0);
calStart.set(Calendar.MINUTE, 0);
calStart.set(Calendar.SECOND, 0);
calStart.set(Calendar.MILLISECOND, 0);

但是,使用Java 1.7.0_51时得到的结果不一致。 (请不要对使用Jodatime提出任何建议,因为我只想使用基本库。)

这是我的测试程序:

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;

public class MidnightTester {

    public static void runTestMidnight1() {

        System.out.printf("runTestMidnight1() called\n");

        TimeZone tz = TimeZone.getTimeZone("UTC");
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(1437004800000L);
        cal.setTimeZone(tz);

        System.out.printf("Original timestamp:\n");
        printCalendarWithTimeZone(cal, tz);

        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);

        System.out.printf("Timestamp after setting to midnight:\n");
        printCalendarWithTimeZone(cal, tz);
    }

    public static void runTestMidnight2() {

        System.out.printf("runTestMidnight2() called\n");

        TimeZone tz = TimeZone.getTimeZone("UTC");
        Calendar cal = Calendar.getInstance();
        cal.setTimeZone(tz);
        cal.setTimeInMillis(1437004800000L);

        System.out.printf("Original timestamp:\n");
        printCalendarWithTimeZone(cal, tz);

        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);

        System.out.printf("Timestamp after setting to midnight:\n");
        printCalendarWithTimeZone(cal, tz);
    }

    public static void printCalendarWithTimeZone(Calendar cal, TimeZone tz) {
        SimpleDateFormat sdf = new SimpleDateFormat("EEEE, MMMM dd, yyyy, hh:mm:ss aaa");
        sdf.setTimeZone(tz);
        System.out.printf("%d= %s\n", cal.getTimeInMillis(), sdf.format(cal.getTime()));
    }

    public static void main(String argv[]) {

        runTestMidnight1();
        runTestMidnight2();
    }
}

这是输出:

runTestMidnight1() called
Original timestamp:
1437004800000= Thursday, July 16, 2015, 12:00:00 AM
Timestamp after setting to midnight:
1436918400000= Wednesday, July 15, 2015, 12:00:00 AM

runTestMidnight2() called
Original timestamp:
1437004800000= Thursday, July 16, 2015, 12:00:00 AM
Timestamp after setting to midnight:
1437004800000= Thursday, July 16, 2015, 12:00:00 AM

如您所见,在runTestMidnight1()中, 将时间设置为午夜后日期从7月16日更改为7月15日! 我不明白

更奇怪的是,在runTestMidnight2()中,我只交换了两行,而正确的日期在7月16日保持不变。

cal.setTimeZone(tz);
cal.setTimeInMillis(1437004800000L);

如果有问题,我现在在美国/太平洋时间。

有人可以帮我了解发生了什么吗?

编辑:更好的解释

当我们调用setTimeInMillis()时,假定传递的long值位于UTC中。 并使用用户的时区或日历对象是否已有可用的时区来计算日历对象时间中的时间。

如果没有经过任何时区,则会在日历对象上设置用户的时区。 因此,被认为在PST时区中的值“ 1437004800000L”,并且使用PST时区来计算时间。 以毫秒为单位设置时间后调用setTimeZone()会更改Calendar对象中的时区。 因此,日历对象时间已移至UTC。 这是runTestMidnight1()的情况。 这就是为什么我们看到日期发生变化的原因,因为原始时间在PST中。

在第二种方法中,时区首先由setTimeZone()设置为UTC。 因此,时间值为“ 1437004800000L”,并且所考虑的时区为UTC,计算出的时间将为UTC。 而且您仅获得UTC时间。

并且仅当用户所在的时区位于UTC时区之后,才会重现此问题。

希望它能澄清。

暂无
暂无

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

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