差異處

這裏顯示兩個版本的差異處。

連向這個比對檢視

java:basic:dateformat [2017/08/19 23:33] (目前版本)
行 1: 行 1:
 +{{tag>​java}}
 +====== DateFormat ======
 +提供轉換Date輸出格式或將Date String轉回Date的功能。
 +===== SimpleDateFormat =====
 +SimpleDateFormat是最常使用的DateFormat子類別。我們以一個格式轉換的範例做說明:​將**2012-04-21T14:​08:​44.801Z**格式轉為UTC+8時區並以yyyy-MM-dd HH:​mm:​ss表示。\\
 +**2012-04-21T14:​08:​44.801Z**是RFC3999Date的規格,Z是UTC+0的意思,我們可以使用**yyyy-MM-dd'​T'​HH:​mm:​ss.SSS'​Z'​**來表示此字串格式(並非所有RFC3999Date格式通吃,如果要通吃可參考Resource[[http://​cokere.com/​RFC3339Date.txt|連結]]的做法)。其中T與Z使用單引號('​)括起,以避免被DateFormat誤判。
 +<code java>
 +DateFormat df = new SimpleDateFormat("​yyyy-MM-dd'​T'​HH:​mm:​ss.SSS'​Z'"​);​
 +df.setTimeZone(TimeZone.getTimeZone("​UTC"​));​ // or set GMT
 +Date date = df.parse("​2012-04-21T14:​08:​44.801Z"​);​
 +</​code>​
  
 +上述程式碼產生的日期輸出為Sat Apr 21 22:08:44 CST 2012。假如沒做setTimeZone,SimpleDateFormat預設會使用你機器上所設定的TimeZone,而從這時間轉成另一個TimeZone時間就會出問題(並非由UTC轉到UTC+8,而是Default TimeZone轉到UTC+8)。而TimeZone的部分可參考以下範例輸出對應,UTC與GMT時間差不了多一般都會被認為是一樣的時間,但TimeZone的getTimeZone只能認得**UTC**、*GMT*、**GMT+Offset**與時區名稱,如果輸入它不認得的名稱就會轉為GMT的TimeZone。
 +<code java>
 +System.out.println(TimeZone.getTimeZone("​UTC"​));​
 +>​sun.util.calendar.ZoneInfo[id="​UTC",​offset=0,​dstSavings=0,​useDaylight=false,​transitions=0,​lastRule=null]
 +
 +System.out.println(TimeZone.getTimeZone("​UTC+8"​));​
 +>​sun.util.calendar.ZoneInfo[id="​GMT",​offset=0,​dstSavings=0,​useDaylight=false,​transitions=0,​lastRule=null]
 +
 +System.out.println(TimeZone.getTimeZone("​ss"​));​
 +>​sun.util.calendar.ZoneInfo[id="​GMT",​offset=0,​dstSavings=0,​useDaylight=false,​transitions=0,​lastRule=null]
 +
 +System.out.println(TimeZone.getTimeZone("​GMT+8"​));​
 +>​sun.util.calendar.ZoneInfo[id="​GMT+08:​00",​offset=28800000,​dstSavings=0,​useDaylight=false,​transitions=0,​lastRule=null]
 +
 +System.out.println(TimeZone.getTimeZone("​GMT+8:​01"​));​
 +>​sun.util.calendar.ZoneInfo[id="​GMT+08:​01",​offset=28860000,​dstSavings=0,​useDaylight=false,​transitions=0,​lastRule=null]
 +
 +System.out.println(TimeZone.getTimeZone("​GMT+8.1"​));​
 +>​sun.util.calendar.ZoneInfo[id="​GMT",​offset=0,​dstSavings=0,​useDaylight=false,​transitions=0,​lastRule=null]
 +
 +System.out.println(TimeZone.getTimeZone("​America/​Los_Angeles"​));​
 +>​sun.util.calendar.ZoneInfo[id="​America/​Los_Angeles",​offset=-28800000,​dstSavings=3600000,​useDaylight=true,​transitions=185,​lastRule=java.util.SimpleTimeZone[id=America/​Los_Angeles,​offset=-28800000,​dstSavings=3600000,​useDaylight=true,​startYear=0,​startMode=3,​startMonth=2,​startDay=8,​startDayOfWeek=1,​startTime=7200000,​startTimeMode=0,​endMode=3,​endMonth=10,​endDay=1,​endDayOfWeek=1,​endTime=7200000,​endTimeMode=0]]
 +</​code>​
 +
 +因此如果我們要將某個時間轉成另外一個格式與時區,可以用下面這個做法:​
 +<code java>
 +df = new SimpleDateFormat("​yyyy-MM-dd HH:​mm:​ss"​);​
 +df.setTimeZone(TimeZone.getTimeZone("​GMT+08:​00"​));​
 +System.out.println(df.format(date));​
 +</​code>​
 +
 +總結一下:​
 +  * 使用DateFormat轉換時區時間時,必須注意source所要表達的時區為何,這樣parse後format才不會出問題。我想假如是一個多國使用的軟體,存到資料庫的時間應該會存GMT時區吧?​
 +  * TimeZone.getTimeZone操作以GMT為主較佳,如果有明確的地區當然更好,畢竟GMT+8的國家也不少。
 +  * 格式的詳細對照可以直接參考javadoc,我是每次寫每次查。
 +
 +我遇到有問題的格式是**yyyy-MM-dd'​T'​HH:​mm:​ss.SSSSSS'​Z'​**,這是使用svn info -xml所產生出來的date格式。但我在使用parse method後,會將SSSSSS的時間進位過去,這裡是我還不解的地方。畢竟S代表毫秒,1000毫秒為1秒,六個S不曉得是表達什麼? ​
 +
 +===== Resource =====
 +  * [[http://​docs.oracle.com/​javase/​6/​docs/​api/​java/​text/​DateFormat.html|DateFormat Javadoc]]
 +  * [[http://​docs.oracle.com/​javase/​6/​docs/​api/​java/​text/​SimpleDateFormat.html|SimpleDateFormat Javadoc]]
 +  * [[http://​www.ietf.org/​rfc/​rfc3339.txt|RFC 3339 Date Format]]
 +  * [[http://​cokere.com/​RFC3339Date.txt|RFC 3339 Date Parser]]
 +
 +=====    =====
 +----
 +\\
 +~~DISQUS~~