2014-09-19 111 views
1

將字符串轉換爲UTC數據,然後轉換爲各種時區時遇到問題。看起來我的程序行爲有所不同,具體取決於我是否轉換爲EST或PST。這裏是我的代碼:Java日期轉換 - UTC到本地 - 根據時區的不同而不同

SimpleDateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
    utcFormat.setTimeZone(java.util.TimeZone.getTimeZone("UTC")); 

    Date date = utcFormat.parse("2014-08-18 17:00:17"); 

    SimpleDateFormat localFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
    localFormat.setTimeZone(java.util.TimeZone.getTimeZone("PST")); 

    System.out.println(localFormat.format(date)); 

如果我運行上面的代碼,這裏是我的輸出:

2014-08-18 10:00:17 

這反映了7一小時內,所提供的UTC時間偏移:2014年8月18日17: 00:17。這是我所期望的。現在,如果我更改日期情節中字17點00分17秒(改變月份從八月至十一月),這裏是產生的輸出:

2014-11-18 09:00:17 

這也沒關係,只要我可以告訴。輸出反映了與UTC的8小時偏移量,我認爲這是由於11月不是在夏令時,而8月是。

我遇到的問題是,如果將時區從「PST」更改爲「EST」,上面的相同代碼的工作方式不同。無論我的日期是在八月還是十一月,當我更改爲EST時,我都可以得到相同的時間輸出。

在這裏是使用EST和2014年8月18日17時00分17秒

2014-08-18 12:00:17 

在這裏是使用EST和2014年11月18日17時00分17秒

2014-11-18 12:00:17 
的輸出的輸出

在這兩種情況下,輸出均表示與UTC有5小時的偏移量,僅在11月份有意義,而不是在8月份。

任何人都可以向我解釋我做錯了什麼?

回答

1

從文檔爲TimeZone

爲了與JDK 1.1.x的相容性,其他一些三字母時區ID(例如, 「PST」, 「CTT」, 「AST」)也支持。但是,由於多個時區經常使用相同的縮寫(例如,「CST」可能是美國「中央標準時間」和「中國標準時間」),因此它們的使用已被廢棄,並且Java平臺只能識別其中的一個他們。

而不是"EST","US/Eastern"將更清晰您的意圖。

這些是支持的美國別名。

  • 美國/阿拉斯加
  • 美國/阿留申
  • 美國/亞利桑那
  • 美國/中央
  • 美國/東印第安納
  • 美國/東部
  • 美國/夏威夷
  • 美國/印第安納州 - 斯塔克
  • 美國/密歇根
  • 美國/山
  • 美國/太平洋
  • 美國/太平洋 - 新
  • 美國/薩摩亞
-1

這是因爲ESTET以外的儲蓄和它的轉變是恆定的,它的夏令時補充區是EDT

您應該使用ET來獲得預期的行爲。 更多關於Wikipedia

3

而不是使用EST的,你應該使用America/New_YorkUS/Eastern(這些別名)。三個字母的時區縮寫是不明確的,你不能確定你得到了什麼。

+0

其實,'America/New_York'是官方名稱。 '美國/東部'是替代品或別名。請參閱[Wikipedia頁面列出適當的時區名稱](http://en.wikipedia.org/wiki/List_of_tz_database_time_zones)。大部分官方主要名稱是「Continent/CityOrRegion」。 – 2014-09-20 06:36:11

0

@Compass是正確的。 這裏是你的代碼將使用:

public static void main(String[] args) { 
    SimpleDateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
    utcFormat.setTimeZone(java.util.TimeZone.getTimeZone("UTC")); 

    Date date = null; 
    try { 
     date = utcFormat.parse("2014-08-18 17:00:17"); 
    } catch (ParseException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    SimpleDateFormat localFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
    localFormat.setTimeZone(java.util.TimeZone.getTimeZone("US/Eastern")); 

    System.out.println(localFormat.format(date)); 
} 
0

answer by Dave Morrissey是正確的。

任何人都可以向我解釋我做錯了什麼?

是。你正在使用一個可怕和令人困惑的日期時間庫。

避免java.util.Date

的java.util.Date和.Calendar類是出了名的麻煩,有缺陷的設計和實施。使用體面的圖書館。在Java中,這意味着Joda-TimeJava 8中的新java.time package(受Joda-Time的啓發,由JSR 310定義)。

時區

雖然j.u.Date沒有時區,在這兩個喬達時間和java.time日期時間對象確實知道自己的分配時區。使這項工作更容易,更明智。

時區名稱

使用proper time zone names。避免使用2,3或4個字母代碼,因爲它們既不標準也不唯一。大多數這些專有名稱是Continent/CityOrRegion

夏令時

你不應該擔心夏令時。讓日期 - 時間庫在那裏進行繁重的工作。所有你需要做的是確保你的圖書館正在使用新版本的時區數據庫。政客們喜歡重新定義DST。

ISO 8601

兩個喬達時間和java.time支持ISO 8601種格式,其默認的解析和日期時間值生成字符串表示。

喬達-時間實施例

以下是在約達時間2.4一些示例代碼。本例中的所有DateTime對象表示宇宙歷史記錄中的同一時刻,但調整爲顯示每個地區的人看到的wall-clock time

String inputRaw = "2014-08-18 17:00:17"; // Nearly in [ISO 8601][7] format. 
String input = inputRaw.replace(" ", "T"); 
DateTime dateTimeUtc = DateTime.parse(input, DateTimeZone.UTC); 
DateTime dateTimeLosAngeles = dateTimeUtc.withZone(DateTimeZone.forID("America/Los_Angeles")); 
DateTime dateTimeNewYork = dateTimeUtc.withZone(DateTimeZone.forID("America/New_York")); 
DateTime dateTimeMontréal = dateTimeUtc.withZone(DateTimeZone.forID("America/Montreal")); 
DateTime dateTimeKolkata = dateTimeUtc.withZone(DateTimeZone.forID("Asia/Kolkata"));