如何在java中将Unix时间戳转换为Postgres等效的时间戳?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (322)

在postgres有一个领域

Column     |            Type          
created_at    | timestamp without time zone 

在Java中存储了一个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.

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

提问于
用户回答回答于

不兼容的类型

我在postgres有一个领域...... 没有时区的时间戳......

…和…

我在Java中存储了一个unix时间戳 long createdAtTime = data.getcreatedAtTime();

这是一个矛盾。

SQL准类型TIMESTAMP WITHOUT TIME ZONE故意缺少任何时区指示符或与UTC的偏移量。因此,这种类型并不能代表一个时刻,是不是在时间轴上的一个点。这种类型代表了大约26-27小时范围内的潜在时刻,即全球范围内的时区范围。

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

TIMESTAMP WITH TIME ZONEPostgres中的类型列中检索值时,您始终会获得UTC值。不幸的是,您和数据库之间的一些好心的工具或驱动程序可能决定动态地将时区应用于该值。虽然善意,但我认为这是反特征。此行为会产生存储在数据库中的时区的错觉,而事实上Postgres仅将UTC存储在此类型中

Date convertedTime = new Date(createdAtTime * 1000L);

java.util.Date堂课很糟糕,设计很差,有缺陷。切勿使用这个类也没有了它的兄弟姐妹,CalendarSimpleDateFormat,和这样的。现在这些都是遗留的,几年前由JSR 310中定义的现代java.time类取代。

Instant

Instant级接管java.util.Date。这两个类代表UTC中的一个时刻,但Instant具有更精细的纳秒级与毫秒级的分辨率。

unix时间戳存储在Java中

如果你有一个从1970年第一个时刻的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框架中的基本构建块类。此外,OffsetDateTimeInstant使用标准ISO 8601格式相比,使用各种格式生成字符串等功能更加灵活。

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.sql.Timestamp timestamp = new Timestamp(createdAtTime*1000L); 
record.set("created_at", convertedTime);
record.saveIt();

尝试使用java.sql.Date而不是util,是一种本机类型的SQL。

扫码关注云+社区

领取腾讯云代金券