簡體   English   中英

java.util.Date - 測試轉換US < - > UK

[英]java.util.Date - Test Conversion US <-> UK

我在下面有這個測試代碼。

行/// 1 ///和/// 2 ///是備選方案。

如果我使用第///2行///輸出看起來有點兒,似乎沒有考慮到美國波士頓和英國倫敦在全年沒有相差5小時的事實。 如果我使用行/// 1 ///它看起來沒問題,似乎它解釋了這個事實。 為什么這樣? 概念差異在哪里? 為什么將這兩個日期改為1天(我的意思是在/// 2 ///中)是不正確的?

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

public class TimeZoneExample02 {

    // private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    public static void main(String[] args) {

        Calendar bostonTime = Calendar.getInstance(TimeZone.getTimeZone("America/New_York"));

        Calendar londonTime = new GregorianCalendar(TimeZone.getTimeZone("Europe/London"));
        londonTime.setTimeInMillis(bostonTime.getTimeInMillis());

        bostonTime.getTime();
        londonTime.getTime();

        for (int i=0; i>=-500; i--){
            bostonTime.add(Calendar.DATE, -1);
            // londonTime.setTimeInMillis(bostonTime.getTimeInMillis()); /// 1 ///
            londonTime.add(Calendar.DATE, -1); /// 2 ///

            bostonTime.getTime();
            londonTime.getTime();

            System.out.printf("Boston time: %s", getString(bostonTime));
            System.out.print(" /// ");
            System.out.printf("London time: %s\n", getString(londonTime));
        }
    }


    private static String getString(Calendar c){
        StringBuilder sb = new StringBuilder();
        sb.append(c.get(Calendar.YEAR));
        sb.append("-");
        sb.append(String.format("%02d", c.get(Calendar.MONTH) + 1));
        sb.append("-");
        sb.append(String.format("%02d", c.get(Calendar.DAY_OF_MONTH)));
        sb.append(" ");
        sb.append(String.format("%02d", c.get(Calendar.HOUR_OF_DAY)));
        sb.append(":");
        sb.append(String.format("%02d", c.get(Calendar.MINUTE)));
        sb.append(":");
        sb.append(String.format("%02d", c.get(Calendar.SECOND)));
        sb.append(".");
        return sb.toString();
    }

}

輸出1:

波士頓時間:2013-10-30 18:51:12 ///倫敦時間:2013-10-30 22:51:12
波士頓時間:2013-10-29 18:51:12 ///倫敦時間:2013-10-29 22:51:12
波士頓時間:2013-10-28 18:51:12 ///倫敦時間:2013-10-28 22:51:12
波士頓時間:2013-10-27 18:51:12 ///倫敦時間:2013-10-27 22:51:12
波士頓時間:2013-10-26 18:51:12 ///倫敦時間:2013-10-26 23:51:12
波士頓時間:2013-10-25 18:51:12 ///倫敦時間:2013-10-25 23:51:12
波士頓時間:2013-10-24 18:51:12 ///倫敦時間:2013-10-24 23:51:12

輸出2:

波士頓時間:2013-10-30 18:50:53 ///倫敦時間:2013-10-30 23:50:53
波士頓時間:2013-10-29 18:50:53 ///倫敦時間:2013-10-29 23:50:53
波士頓時間:2013-10-28 18:50:53 ///倫敦時間:2013-10-28 23:50:53
波士頓時間:2013-10-27 18:50:53 ///倫敦時間:2013-10-27 23:50:53
波士頓時間:2013-10-26 18:50:53 ///倫敦時間:2013-10-26 23:50:53
波士頓時間:2013-10-25 18:50:53 ///倫敦時間:2013-10-25 23:50:53
波士頓時間:2013-10-24 18:50:53 ///倫敦時間:2013-10-24 23:50:53

倫敦夏令時

倫敦時間隨着夏令時(DST)在2013-10-27 結束時凌晨2點凌晨1點(再次)結束。

功能,而不是錯誤

java.util.Calendar文檔在其頂部的討論中解釋了unlike set(), add() forces an immediate recomputation of the calendar's milliseconds and all fields.

此外, add方法上java.util.GregorianCalendar文檔指出不調整較小的時間單位。 該文檔特別指出, HOURDAY_OF_MONTH的較小字段,因此不進行調整。 這意味着你從23小時開始,所以你最終得到23小時,毫秒 - 自 - epoch根據需要重新計算。

您在setadd方法中看到的行為都是正確的。 功能,而不是錯誤。

間接答案

捆綁的java.util.Date ,java.util.Calendar和java.text.SimpleDateFormat是眾所周知的麻煩,令人困惑和棘手。 它們在設計和實施方面都存在缺陷。

我理解您對“使用Java的內置功能”的興趣。 雖然這種興趣通常值得稱贊,但在Java的這個特定角落,這是浪費時間。 甚至Sun和Oracle都放棄了這些課程。 Java 8帶來了一個全新的java.time。*包,由JSR 310定義,受Joda-Time的啟發,並取代舊的捆綁類。

如果您還不能轉到Java 8,請使用Joda-Time Joda-Time可以在多個版本的Java中運行,並且在Java 8中繼續工作,因為它是主動維護的。

示例代碼

使用Joda-Time 2.3的一些示例代碼可以幫助您前進。

一些筆記......

Joda-Time DateTime實際上知道自己的時區。 相比之下,java.util.Date沒有時區,但其toString方法應用JVM的默認時區,這不會產生混淆。

請注意,在此示例中, dateTime_BostondateTime_London具有相同的毫秒數 - 自 - 紀元。

Joda-Time默認使用標准的ISO 8601格式進行字符串輸出,如2014-02-13T10:32:28.131+05:30

最后的+-標記與UTC / GMT偏移的時區。 不要看這是一個公式中的操作數。 閱讀此標簽,例如,“印度的時區偏移為+05:30,因此顯示的日期時間比UTC / GMT提前了五個半小時”。

  • PLUS SIGN(“+”)表示在UTC / GMT之前
  • HYPHEN-MINUS(“ - ”)意味着落后於UTC / GMT

最后的Z發音為“Zulu”,是+00:00簡寫。 這意味着UTC / GMT時區,即沒有時區偏移。

// Specify a time zone rather than rely on default.
DateTimeZone timeZone_Boston = DateTimeZone.forID( "America/New_York" );
DateTimeZone timeZone_London = DateTimeZone.forID( "Europe/London" );

DateTime dateTime_Boston = new DateTime( 2013, 10, 27, 22, 51, 12, timeZone_Boston );
DateTime dateTime_London = dateTime_Boston.toDateTime( timeZone_London ); 
DateTime earlier_London = dateTime_London.minusDays( 2 ); // Use '2' to get us before DST change.
DateTime earlier_UtcGmt = earlier_London.toDateTime( DateTimeZone.UTC );

轉儲到控制台......

System.out.println( "dateTime_Boston " + dateTime_Boston );
System.out.println( "dateTime_London " + dateTime_London );
System.out.println( "earlier_London " + earlier_London );
System.out.println( "earlier_UtcGmt " + earlier_UtcGmt );

跑的時候......

dateTime_Boston 2013-10-27T22:51:12.000-04:00
dateTime_London 2013-10-28T02:51:12.000Z
earlier_London 2013-10-26T02:51:12.000+01:00
earlier_UtcGmt 2013-10-26T01:51:12.000Z

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM