簡體   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