将unix时间戳转换为java中的postgres等效时间戳

时间:2014-12-17 17:55:16

标签: java postgresql

我在postgres中有一个字段

Column     |            Type          
created_at    | timestamp without time zone 

我在Java中用long存储了一个unix时间戳

long createdAtTime = data.getcreatedAtTime();

我想将它转换为java中的时间戳,以便我可以将activejdbc存储到postgres中

我尝试了以下

Date convertedTime = new Date(createdAtTime*1000L);
record.set("created_at", convertedTime);
record.saveIt();

但是我收到以下错误:

Can't infer the SQL type to use for an instance of java.util.Date. Use setObject() with an explicit Types value to specify the type to use.

我应该使用不同的方式首先转换日期吗?

3 个答案:

答案 0 :(得分:0)

java.sql.Timestamp timestamp = new Timestamp(createdAtTime*1000L); 
record.set("created_at", convertedTime);
record.saveIt();

而不是直到你尝试过java.sql.Date。 它是一种本机类型的SQL。

答案 1 :(得分:0)

不兼容的类型

  

我在postgres中有一个字段……

     

没有时区的时间戳...

…和…

  

我有一个用Java存储的unix时间戳记

     

long createdAtTime = data.getcreatedAtTime();

这是一个矛盾。

SQL标准类型TIMESTAMP WITHOUT TIME ZONE故意缺少任何time zoneoffset-from-UTC的指示符。因此,此类型 not 代表一个时刻,不是 not 在时间轴上的一个点。这种类型表示在大约26-27小时(全球时区范围)内的潜在时刻。

如果要跟踪特定时刻,请使用其他SQL标准类型TIMESTAMP WITH TIME ZONE。在Postgres中,所有此类型的值都存储在UTC中(偏移量为零)。如果您传递的值指示其他偏移量或时区,则Postgres在存储前会将其值调整为UTC。

在Postgres中从类型为TIMESTAMP WITH TIME ZONE的列中检索值时,您 总是使用UTC值。不幸的是,位于您和数据库之间的一些意图良好的工具或驱动程序可能会决定动态地将时区应用于该值。虽然用心良苦,但我认为这是反特征。这种行为会造成对存储在数据库中的时区的错觉,而实际上 Postgres仅存储这种类型的UTC

  

日期转换时间=新日期(createdAtTime * 1000L);

java.util.Date类很糟糕,设计欠佳且有缺陷。请勿使用此类及其兄弟姐妹CalendarSimpleDateFormat等。这些都是现在的遗留物,几年前被JSR 310中定义的现代 java.time 类所取代。

Instant

Instant类将接管java.util.Date。尽管Instant的分辨率都比纳秒要好,但这两类都代表UTC时刻。

  

unix时间戳记长时间存储在Java中

如果您从1970年1月UTC 1970-01-01T00:00:00Z的纪元参考开始算起整秒,请转换为Instant

Instant instant = Instant.ofEpochSecond( 1_539_555_140L ) ;

提示:不要养成从时代开始就跟踪时间的习惯。这是模棱两可的(不同的系统使用不同的分辨率和不同的纪元引用),容易出错,并使调试/日志记录变得混乱。使用 java.time 对象和标准的ISO 8601字符串表示日期时间值。

您的JDBC驱动程序可能可以接受Instant

myPreparedStatement.setObject( … , instant ) ;

检索:

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

OffsetDateTime

如果不支持Instant,请使用convert to OffsetDateTime。需要任何JDBC 4.2或更高版本的驱动程序来支持OffsetDateTime

OffsetDateTime表示日期和时间,与UTC偏移。相反,Instant是固定在UTC的,它是 java.time 框架中的基本构建模块类。另外,OffsetDateTime具有更灵活的功能,例如与仅使用标准ISO 8601格式的Instant相比,可以生成各种格式的字符串。

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;

检索:

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

…或…

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

LocalDateTime

如果不是试图表示时刻,例如数据库类型TIMESTAMP WITHOUT TIME ZONE,请使用LocalDateTime类。

但是,如果您认为使用这些类型在某种程度上避免了在跟踪时刻中使用时区的工作,那么您会感到非常误解。这是一种“现在付款或以后付款”的情况:要么立即学习基本的日期时间概念和处理方法,要么稍后拼命拼搏着可怕的失败数据。


关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

目前位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

答案 2 :(得分:0)

我看到您的“数据库”列将值存储为没有时区的时间戳, 你为什么不尝试这个

Timestamp current = Timestamp.from(Instant.now());
record.set("created_at", current);//I don't know if you might need to parse
record.saveIt();