JDBC MySQL读取和写入TIMESTAMP,自Unix Epoch

时间:2016-01-08 08:50:18

标签: java mysql jdbc timestamp

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

我想用自己的时代以毫秒为单位表示我的所有瞬间。我只想使用整数字段,但我想使用ON UPDATE CURRENT_TIMESTAMP语法,该语法仅支持TIMESTAMP / DATETIME类型。

JodaTime允许我在epoch之后轻松转换不同的表示和毫秒,但是it's not so simple to use milliseconds since epoch with JDBC/MYSQL

我有没有办法让JDBC在TIMESTAMP列中存储milliseconds_since_epoch,并将millESTAMP列检索为milliseconds_since_epoch,而不必担心由于客户端或服务器更改时区而导致的值更改。

我宁愿不必搞乱mysql服务器设置或jdbc连接设置,但我愿意,如果这是唯一的方法。

2 个答案:

答案 0 :(得分:0)

  

我有没有办法让JDBC在TIMESTAMP列中存储milliseconds_since_epoch,并检索TIMESTAMP列为milliseconds_since_epoch

对于5.6.4之前的MySQL Server版本:

没有。 TIMESTAMP列将丢弃小数秒(参考:here)。

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

对于MySQL Server 5.6.4及更高版本:

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

Fractional Seconds in Time Values

答案 1 :(得分:0)

让您的工具担心毫秒

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

  

我希望将所有时刻表示为自Unix时代以来的毫秒数。

这正是MySQL在TIMESTAMP数据类型中为您所做的事情,只是更精细 - 自UTC 1970年以来的微秒数。致quote the doc

  

TIMESTAMP的范围为'1970-01-01 00:00:01'UTC至'2038-01-19 03:14:07'UTC。

     

...

     

TIMESTAMP值可以包括一个高达微秒(6位)精度的尾随小数秒部分

您对留在UTC的担忧...

  

将millESTAMP列检索为milliseconds_since_epoch,而不必担心由于客户端或服务器更改时区而导致的值更改

......已经解决了。 MySQL以UTC格式存储TIMESTAMP,您的JDBC驱动程序应该以UTC格式检索值,而java.time类Instant以UTC格式存储该值。 Instant类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。 所以你只有UTC,一直到。

尽可能避免使用麻烦的旧日期时间类。而是使用他们的替换,java.time类。如果JDBC driver更新为JDBC 4.2,稍后您可以直接使用java.time类型。

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

...和...

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

如果您的JDBC驱动程序尚未兼容,请简单使用旧的java.sql类型,但立即转换为/从java.time转换。不要使用java.sql类型执行业务逻辑。

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

...和...

Instant instant = myResultSet.getTimestamp( … ).toInstant() ;

如果希望调整UTC以及时区(例如向用户演示),请应用ZoneId获取ZonedDateTime。搜索Stack Overflow以获取更多示例。

ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;  // Same moment, different wall-clock time.

如果您坚持访问milliseconds-since-epoch,请询问Instant对象。但请注意数据丢失,因为该瞬间可能会持续MySQL的微秒或其他来源的纳秒。要求毫秒意味着截断一秒的更精细部分。

long millisSinceEpoch = instant.toEpochMilli() ;

走向另一个方向。

Instant instant = Instant.ofEpochMilli( millisSinceEpoch ) ;

关于 java.time

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

现在位于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