如何将字符串(2017-08-01T15:15:03.313000000 + 02:00)转换为时间戳

问题描述:

String str = "2017-08-01T15:15:03.313456768+02:00"; 
// The following statement gives IllegalArgumentExceptionTimestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff] 
Timestamp timeStamp = Timestamp.valueOf(str); 
ZonedDateTime zoneddate = ZonedDateTime.parse(str); 
System.out.println("ZonedDate: "+zoneddate);// prints 2017-08-01T15:15:03.313456768+02:00 
Instant inst = zoneddate.toInstant(); 
Timestamp newTime = Timestamp.from(inst); 
System.out.println("Timestamp: "+newTime);// prints 2017-08-01 15:15:03.313456768 without Zone 

我在转换过程中缺少区域。任何人都可以建议我如何在TimeStamp获得Zone?如何将字符串(2017-08-01T15:15:03.313000000 + 02:00)转换为时间戳

+0

我是red alredy,但SimpleDateFormat不接受9位毫秒。 – user2814979

+0

请显示您尝试过的代码 – Jens

+1

'SimpleDateFormat'具有毫秒精度(小数点后只有3位数)。对于超过3位数字,您必须使用Java 8新的'java.time' API:https://stackoverflow.com/questions/30135025/java-date-parsing-with-microsecond-or-nanosecond-ccuracy – 2017-08-16 11:51:51

这个问题的最新版本是这样的:

任何人都可以建议我我如何在时间戳

获得区最简单的答案是,你不能。 A Timestamp不包含区域作为其表示的一部分。当你转换生成一个TimestampZonedDateTime你是扔掉时区的偏移量。

您可以通过查看Timestamp类的源代码来验证此情况。没有构造函数允许您传递时区信息,并且日期/时间用UTC表示。 (该getTimezoneOffset()方法返回不同的东西......和方法反正弃用。)

...但我必须坚持时间戳在数据库中,它必须有显示的区域。

然后,您需要使用不同的SQL类型(或类型)来表示Java端的时间戳和相应的类型。请注意,SQL的某些方言不会将时区信息存储在标准的DATE/TIME/TIMESTAMP类型中。

Stephen C的答案是正确的。

避免诸如java.sql.Timestamp之类的麻烦的旧日期时间类。现在由java.time类取代。

您有一个采用标准ISO 8601格式的字符串,表示日期 - 时间偏移量与UTC不同,但没有时区指示。所以解析为OffsetDateTime。移到UTC作为Instant进行存储。

检索后,指定您希望的任何时区。

String input = "2017-08-01T15:15:03.313456768+02:00"; 
OffsetDateTime odt = OffsetDateTime.parse(input) ; 
Instant instant = odt.toInstant() ; // Adjust into UTC for storage. 
myPreparedStatement.setObject(… , instant) ; 

检索。

Instant instant = myResultSet.getObject(… , Instant.class) ; 
ZoneId z = ZoneId.of("America/Montreal") ; // or "Europe/Berlin", "Asia/Kolkata", whatever. 
ZonedDateTime zdt = instant.atZone(z) ; // Move from UTC to a time zone.