从MySQL Epoch开始,JDBC MySQL读取和写入TIMESTAMP为毫秒

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

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

JodaTime允许我轻松地在时代之间的不同表示和毫秒之间进行转换,但是从使用JDBC / MYSQL开始的时间使用毫秒并不那么简单。

有没有什么办法可以让我们JDBC将milliseconds_since_epoch存储在T​​IMESTAMP列中,并将TIMESTAMP列作为milliseconds_since_epoch检索,而无需担心由于客户端或服务器更改时区而导致的值更改。

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


有没有什么办法可以让我们JDBC将milliseconds_since_epoch存储在T​​IMESTAMP列中,并将TIMESTAMP列检索为milliseconds_since_epoch

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

否。TIMESTAMP列将舍弃小数秒(参考:这里)。

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

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

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

时间值的分数秒


让你的工具担心毫秒

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

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

这正是MySQL在其TIMESTAMP数据类型中为您所做的,只有更细微的 - 自1970年以来UTC开始的一个微秒数。 引用文档:

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

...

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

你关心的是要留在UTC ......

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

已经解决。 MySQL正在以UTC格式存储TIMESTAMP ,您的JDBC驱动程序应以UTC格式检索值,并且java.time类Instant以UTC格式存储该值。 Instant类表示UTC时间轴上的某个时刻,分辨率为纳秒(小数点后最多九位数字)。 所以你只有UTC,一路通过。

尽可能避免麻烦的旧日期时间课程。 而是使用它们的替代品,java.time类。 如果JDBC驱动程序更新为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 。 搜索堆栈溢出了更多的例子。

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

如果您坚持访问毫秒以来的时间,请询问Instant对象。 但要小心数据丢失,因为这个瞬间可能会持续微秒级的MySQL或来自其他来源的纳秒级。 要求毫秒意味着截断第二秒的较细部分。

long millisSinceEpoch = instant.toEpochMilli() ;

走向另一个方向。

Instant instant = Instant.ofEpochMilli( millisSinceEpoch ) ;

关于java.time

java.time框架内置于Java 8及更高版本中。 这些类取代了诸如java.util.DateCalendarSimpleDateFormat等麻烦的旧式遗留日期时间类。

现在处于维护模式的Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参阅Oracle教程。 并搜索堆栈溢出了很多例子和解释。 规范是JSR 310。

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

何处获取java.time类?

  • Java SE 8Java SE 9和更高版本
  • 内置。
  • 带有捆绑实现的标准Java API的一部分。
  • Java 9增加了一些次要功能和修复。
  • Java SE 6Java SE 7
  • 大部分java.time功能都在ThreeTen-Backport中移植到Java 6和7。
  • Android的
  • 后续版本的java.time类的Android捆绑实现。
  • 对于早期的Android(<26), ThreeTenABP项目采用了ThreeTen-Backport(如上所述)。 请参阅如何使用ThreeTenABP ...。
  • ThreeTen-Extra项目将java.time扩展到其他类。 这个项目是未来可能增加java.time的一个试验场。 您可以在这里找到一些有用的课程,例如IntervalYearWeekYearQuarter等。

    链接地址: http://www.djcxy.com/p/25069.html

    上一篇: JDBC MySQL reading and writing TIMESTAMP as milliseconds since Unix Epoch

    下一篇: Convert date to datetime or timestamp using alter table in mysql