将String转换为Postgres时间戳并返回

时间:2018-05-03 22:25:12

标签: java postgresql timestamp

第1部分:

我有一个文件,其中包含日期为字符串,格式如下:2006-02-16T21:36:32.000+0000

我需要在Timestamp类型的列中将此值写入Postgres。我如何在Java中实现这一目标?

第2部分:

我需要从Postgres中读取第1部分中保存的值,并将其转换为以下格式的字符串"2006-02-16T21:36:32.000+0000"

这就是我的尝试:

Timestamp lastSyncDate = Timestamp.valueOf(2006-02-16T21:36:32.000+0000)

当我尝试将其写入postgres时,它会给我以下错误:

java.lang.IllegalArgumentException: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]

2 个答案:

答案 0 :(得分:2)

2006-02-16T21:36:32.000+0000看起来像是ISO-8601时间戳。 postgres理解这种格式。就像任何其他字符串一样对待它。

不要尝试将其转换为java时间戳

答案 1 :(得分:2)

TL;博士

myPreparedStatement.setObject( 
    … , 
    OffsetDateTime.parse( "2006-02-16T21:36:32.000+0000" )  
) 

有和没有区域/偏移

您说您的列属于TIMESTAMP类型,是TIMESTAMP WITHOUT TIME ZONE的缩写。这种类型故意缺乏任何时区概念或从UTC偏移。 通常适用于一般商业目的。

您使用了错误的类型

这是您输入的错误类型。您的输入具有零小时的UTC偏移量,这意味着UTC本身。拥有偏移量或区域后,您的数据应仅存储在TIMESTAMP WITH TIME ZONE 类型列中。在Postgres中的此…WITH…类型中,任何提交的偏移/区域信息都用于调整为UTC以进行存储,然后被丢弃。

TIMESTAMP WITHOUT TIME ZONE类型的列中存储带有偏移量或区域的日期时间值就像在一列数字中存储具有指定货币(美元,欧元,卢布等)的价格/成本类型。你正在丢失重要数据,货币。这会使您的数据毫无价值。

有关这些类型,请参阅Postgres documentation page

智能对象,而不是哑字符串

尽可能使用对象与数据库交换数据,而不是传递米字符串。让你的JDBC driver来回marshaling the data来做它。

将输入字符串解析为OffsetDateTime对象。

ISO 8601

您的输入字符串采用ISO 8601标准定义的格式。解析/生成字符串时, java.time 类在默认情况下使用ISO 8601格式。无需指定格式模式。

String input = "2006-02-16T21:36:32.000+0000" ;
OffsetDateTime odt = OffsetDateTime.parse( input ) ;

将SQL定义为预准备语句。

使用JDBC 4.2及更高版本,您可以直接与数据库交换 java.time 对象。无需再次使用麻烦的遗留类,如java.sql.Timestamp

您可以传递OffsetDateTime。我想提取Instant以向读者证明我了解Postgres如何始终以UTC TIMESTAMP WITH TIME ZONE值存储。

Instant instant = odt.toInstant() ;
myPreparedStatement.setObject( … , instant ) ;

检索。

Instant instant = myResultSet.getObject( … , Instant.class ) ;