Java 自Unix纪元以来JDBC MySQL读写时间戳(毫秒)

Java 自Unix纪元以来JDBC MySQL读写时间戳(毫秒),java,mysql,jdbc,timestamp,Java,Mysql,Jdbc,Timestamp,我通过JDBC访问MySQL表中的TIMESTAMP列。在Java方面,我使用的是JodaTime 我希望将自Unix时代以来的所有实例表示为毫秒。我只想使用一个整数字段,但我想使用只支持TIMESTAMP/DATETIME类型的ON UPDATE CURRENT_TIMESTAMP语法 JodaTime允许我轻松地在不同的表示形式和自epoch以来的毫秒之间进行转换,但是 是否有任何方法可以使用JDBC在时间戳列中存储毫秒\u自\u epoch,并将时间戳列检索为毫秒\u自\u epoch,而

我通过JDBC访问MySQL表中的TIMESTAMP列。在Java方面,我使用的是JodaTime

我希望将自Unix时代以来的所有实例表示为毫秒。我只想使用一个整数字段,但我想使用只支持TIMESTAMP/DATETIME类型的
ON UPDATE CURRENT_TIMESTAMP
语法

JodaTime允许我轻松地在不同的表示形式和自epoch以来的毫秒之间进行转换,但是

是否有任何方法可以使用JDBC在时间戳列中存储毫秒\u自\u epoch,并将时间戳列检索为毫秒\u自\u epoch,而不必担心由于客户端或服务器更改时区而导致的值更改

我希望不必乱弄mysql服务器设置或jdbc连接设置,但如果这是唯一的方法,我愿意这样做

是否有任何方法可以使用JDBC在时间戳列中存储毫秒\u自\u epoch,并将时间戳列检索为毫秒\u自\u epoch

对于5.6.4之前的MySQL服务器版本:

否。时间戳列将丢弃小数秒(参考:)

如果您真的需要存储毫秒,那么您必须将它们放在单独的数字列中。但是,如果您可以使用整秒的时间分辨率,则时间戳列将在存储值时自动将值转换为UTC(参考:)

对于MySQL服务器5.6.4及更高版本:

对。有关更多信息,请参阅以下MySQL文档主题:

让您的工具担心毫秒数 您正在与SQL、JDBC和Java类型系统作斗争。不要担心毫秒数。您的数据库、驱动程序和Java已经在为您这样做了,但更精细(MySQL中为微秒,Java中为纳秒)

我希望将自Unix时代以来的所有实例表示为毫秒

这正是MySQL在其
时间戳
数据类型中为您所做的,只是更精细——自1970年开始以UTC计算以来的微秒数。致:

时间戳的范围为“1970-01-01 00:00:01”UTC到“2038-01-19 03:14:07”UTC

时间戳值可以包括精度高达微秒(6位)的尾随小数秒部分

您对留在UTC的担忧

从\u epoch开始以毫秒\u的形式检索时间戳列,而不必担心由于客户端或服务器更改时区而导致的值更改

…已经解决了。MySQL正在UTC中存储
时间戳
,您的JDBC驱动程序应该在UTC中检索值,java.time类
Instant
将值存储在UTC中。该类表示时间线上的一个时刻,分辨率为(小数点的九(9)位)因此您始终只有UTC。

尽可能避免麻烦的旧日期时间类。而是使用它们的替代品java.time类。如果更新了for和更高版本,则可以直接使用java.time类型

Instant instant = Instant.now() ;  // Current moment in UTC with resolution up to nanoseconds.
myPreparedStatement.setObject( … , instant ) ;
……还有

Instant instant = myResultSet.getObject( … , Instant.class ) ;
Instant instant = myResultSet.getTimestamp( … ).toInstant() ;
如果您的JDBC驱动程序尚不兼容,请简要使用旧的java.sql类型,但立即转换为java.time。不要使用java.sql类型执行业务逻辑

myPreparedStatement.setTimestamp( … , java.sql.Timestamp.from( instant ) ) ;
……还有

Instant instant = myResultSet.getObject( … , Instant.class ) ;
Instant instant = myResultSet.getTimestamp( … ).toInstant() ;
当您想要调整出UTC并进入时区(如向用户演示)时,请应用
ZoneId
以获取
zoneDateTime
。搜索堆栈溢出以获取更多示例

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;  // Same moment, different wall-clock time.
如果您坚持从epoch开始访问毫秒,请询问
Instant
对象。但要小心数据丢失,因为MySQL可能会在瞬间丢失微秒数据,而其他数据源可能会在瞬间丢失纳秒数据。要求毫秒意味着截断一秒钟的更精细部分

long millisSinceEpoch = instant.toEpochMilli() ;
往另一个方向走

Instant instant = Instant.ofEpochMilli( millisSinceEpoch ) ;

关于java.time 该框架内置于Java8及更高版本中。这些类取代了麻烦的旧日期时间类,例如,&

该项目现已启动,建议迁移到类

要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释。规格是

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

从哪里获得java.time类

  • ,及以后
    • 内置的
    • 标准JavaAPI的一部分,带有捆绑实现
    • Java9添加了一些次要功能和修复
    • 大部分java.time功能都在中向后移植到Java6和Java7
    • 更高版本的Android捆绑包实现了java.time类

    • 对于早期的Android(你能详细解释一下为什么你不想使用bigint并实际存储毫秒数而不是目标日期/时间转换吗?如果只是时间戳列更新的速度太快,你可以定义一个匹配的触发器。首先你依靠MySQL自动更新列,但是你需要一种方法来设置它…是什么?我是b我开始认为使用bigint+触发器是我最好的选择,但我仍然保留这个问题,以防有更好的方法来解决。如果没有方法通过JDBC设置字段,那可能没问题,因为我不认为我需要为同一列同时设置+自动更新,但如果时间戳字段可以ld有两个用途。你可能还想考虑选择/报告:日期列提供了一些非常好的嵌入式函数,而秒/毫秒在按同一个工作日进行分组方面不是很方便……这是MySQL 5.7的发展:实际上,MySQL 5.6.4增加了支持。5.6.4之前的MySQL不支持它,but 5.6.4或更高版本(包括