2016-04-29 42 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欧洲/伦敦