2016-04-29 43 views
1

我試圖從java.sql.timestamp轉換爲OffsetDateTime,這樣我就可以在我的rest api中返回ISO8601標準字符串。我使用這個代碼轉換從timestampOffsetDateTimeZoneOffset的ID無效ID

public static OffsetDateTime sqlTimetampeToOffsetDateTime(Timestamp ts, String timeZone) 
{ 
    if (ts == null) 
    { 
     return null; 
    } 

    Calendar cal = Calendar.getInstance(); 
    cal.setTime(ts); 
    ZoneOffset offset = ZoneOffset.of(timeZone); 
    return OffsetDateTime.of(
      cal.get(Calendar.YEAR), 
      cal.get(Calendar.MONTH)+1, 
      cal.get(Calendar.DAY_OF_MONTH), 
      cal.get(Calendar.HOUR_OF_DAY), 
      cal.get(Calendar.MINUTE), 
      cal.get(Calendar.SECOND), 
      cal.get(Calendar.MILLISECOND)*1000000, 
      offset); 
} 

但是,代碼在ZoneOffset offset = ZoneOffset.of(timezone)失敗的價值Europe/Copenhagen

我用下面的代碼來打印所有時區的列表,我看到Europe/Copenhagen在該列表

Set<String> allZones = ZoneId.getAvailableZoneIds(); 
    LocalDateTime dt = LocalDateTime.now(); 

    List<String> zoneList = new ArrayList<String>(allZones); 
    Collections.sort(zoneList); 

    for (String s : zoneList) { 
     ZoneId zone = ZoneId.of(s); 
     ZonedDateTime zdt = dt.atZone(zone); 
     ZoneOffset offset = zdt.getOffset(); 
     int secondsOfHour = offset.getTotalSeconds() % (60 * 60); 
     String out = String.format("%35s %10s%n", zone, offset); 
     System.out.printf(out); 
    } 

現在我不明白是怎麼回事。我如何轉換java.sql.timestampISO8601字符串(我不關心,如果我必須使用OffsetDateTime與否。我寧願不使用任何第三方庫

http://pastebin.com/eHJKWpAv

+0

什麼是您的數據類型在你的數據庫?帶時區的時間戳?還有別的嗎? – Tunaki

+0

在數據庫中,我有時間戳,例如「2016-05-23 15:00:00:00」,我有另一個有時區的列,例如「歐洲/哥本哈根」。這就是爲什麼我將'timezone'作爲單獨的字符串傳遞。 –

+0

表達式'ZoneOffset.of(「歐洲/哥本哈根」)'必須失敗,因爲該區域標識不僅僅是偏移量(包含夏令時規則等附加信息)。在這種情況下,您首先需要構建一個'ZonedDateTime',然後從中派生出'OffsetDateTime'或'Instant'。 –

回答

-1

我沒有管理,但我轉換我不知道這是否是這樣做或不正確的做法。這是我爲別人的代碼誰是尋找答案

public static OffsetDateTime sqlTimetampeToOffsetDateTime(Timestamp ts, String timeZone) 
{ 
    if (ts == null) 
    { 
     return null; 
    } 

    ZoneId zoneId = ZoneId.of(timeZone); 

    Calendar cal = Calendar.getInstance(); 
    cal.setTime(ts); 
    ZonedDateTime zdt = ZonedDateTime.of(
      cal.get(Calendar.YEAR), 
      cal.get(Calendar.MONTH) + 1, 
      cal.get(Calendar.DAY_OF_MONTH), 
      cal.get(Calendar.HOUR_OF_DAY), 
      cal.get(Calendar.MINUTE), 
      cal.get(Calendar.SECOND), 
      cal.get(Calendar.MILLISECOND) * 1000000, 
      zoneId); 
    return zdt.toOffsetDateTime(); 
} 

timeZone處於Europe/Copenhagen形式...你可以看到完整列表,支持Java8 m張貼在問題

+0

我想'返回ts.toInstant()。atZone(ZoneId.of(timeZone))。toOffsetDateTime();'是所需要的。 – Tunaki

+0

您的代碼正在爲產生的時間添加偏移量。只是想寫在這裏,以便如果別人正在閱讀他知道的區別。 –

+0

好吧,那就是'ts.toLocalDateTime()。atZone(ZoneId.of(timeZone)).toOffsetDateTime();'。 – Tunaki

0

如果您擁有了zoneidŸ引擎收錄的網址,這是非常容易的使用即時類來做到這一點:在一個特定時間點打交道時

Timestamp t = new Timestamp(System.currentTimeMillis()); 

ZoneId zone = ZoneId.of("Europe/Copenhagen"); 

OffsetDateTime offsetDateTime = ZonedDateTime 
    .ofInstant(Instant.ofEpochMilli(t.getTime()), zone) 
    .toOffsetDateTime(); 
0

ZoneOffset纔有意義。在歐洲/倫敦,我們目前根據一年中的時間使用BST或GMT。然而,在100年前(給與或接受),歐洲/倫敦沒有BST。 ZoneOffset.of()僅從調用ZoneOffset.ofTotalSeconds()時才填充的內部緩存中檢索區域偏移量。這是記錄不完善的。然而,一個簡單的解決方案存在:

ZoneId.of("Europe/London").getRules().getOffset(Instant.now()); 
(例如今天)

現在正好返回正確ZoneOffset歐洲/倫敦