为了账号安全,请及时绑定邮箱和手机立即绑定

Java 日期和 MySQL 时间戳时区

Java 日期和 MySQL 时间戳时区

四季花海 2022-05-21 17:24:52
我正在编辑一段代码,它基本上是:timestamp = new Date();然后将该timestamp变量保存在TIMESTAMPMySQL 表列中。但是,在通过调试时,我看到Date对象显示在正确的时区GMT+1中,当持久保存在数据库中时,它是GMT时区,所以一小时后。使用该函数CURRENT_TIMESTAMP返回 GMT+1 日期。连接字符串为jdbc:mysql://..../db-name,不带任何参数。编辑:找到这段代码preparedStatement.setTimestamp(2, new Timestamp(timestamp.getTime()));发生了什么?
查看完整描述

1 回答

?
慕森卡

TA贡献1806条经验 获得超8个赞

myPreparedStatement

.setObject(  

    … ,                                   // Specify which placeholder `?` in your SQL statement. 

    OffsetDateTime.now( ZoneOffset.UTC )  // Capture the current moment as seen in the wall-clock time of UTC (an offset-from-UTC of zero).

) ;

避免遗留的日期时间类

您正在使用几年前被java.time类取代的糟糕的日期时间类。


永远不要使用Date或Timestamp。


世界标准时间

以 UTC 捕获当前时刻。大多数数据库以 UTC 存储时刻。通常,您应该在 UTC 中完成大部分业务逻辑、调试、日志记录、存储和数据交换。


OffsetDateTime

OffsetDateTime使用恰当命名的类表示与 UTC 偏移的时刻。


我们想要 UTC 本身,或者偏移量为零。我们可以为此使用一个常数,ZoneOffset.UTC。


OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ) ;

JDBC 4.2

从 JDBC 4.2 开始,我们可以直接与数据库交换java.time对象。


要将这一时刻保存到类似于 SQL 标准的数据类型的列中TIMESTAMP WITH TIME ZONE:


myPreparedStatement.setObject( … , odt ) ;

恢复:


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

ZonedDateTime

要将检索到的时刻呈现给用户,您可能需要调整到用户的预期/期望时区。


ZoneId z = ZoneId.of( "Africa/Tunis" ) ;

ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

永远不要依赖默认时区

请注意,在上面的代码中,我们始终指定所需/预期的偏移量或区域。


如果您未指定,则会以静默方式隐式应用偏移量或区域。最好明确地指定你的意图,因为你的 JVM、数据库和主机操作系统的当前默认值都不是你作为程序员的手。这意味着依赖于默认值的代码在运行时的行为会有所不同。


Java 6 和 7

但是我仍然被迫处理 Java 6


领导 JSR 310 和java.time实现以及著名的Joda-Time项目的 Stephen Colebourne 也领导了另一个项目ThreeTen-Backport。这个库中的大部分java.time功能都向后移植到 Java 6 和 7,API 几乎相同。


因此,请在后端课程中完成所有工作。然后,在最后一刻,java.sql.Timestamp通过DateTimeUtils类转换为/从。


这些转换方法大多使用Instant对象。AnInstant是 UTC 中的时刻,始终是 UTC。您可以OffsetDateTime通过提取Instant. 该类Instant是java.time中的基本构建块类,OffsetDateDate具有更大的灵活性,例如生成字符串时的替代格式模式。但两者都Instant代表OffsetDateTime一个时刻,时间轴上的一个点。


Instant instant = odt.toInstant() ;  

java.sql.Timestamp ts = org.threeten.bp.DateTimeUtils.toSqlTimestamp( instant ) ;

换个方向,Timestamp从数据库中检索 a ,然后立即转换为Instant.


java.sql.Timestamp ts = myResultSet.getTimestamp( … ) ;

Instant instant = org.threeten.bp.DateTimeUtils.toInstant( ts ) ;


查看完整回答
反对 回复 2022-05-21
  • 1 回答
  • 0 关注
  • 160 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信