从MySQL Epoch开始,JDBC MySQL读取和写入TIMESTAMP为毫秒
我在通过JDBC访问的MySQL表中有一个TIMESTAMP列。 在Java方面,我使用JodaTime。
我希望将我的所有时间表示为Unix时代以来的毫秒数。 我只是使用一个整数字段,但我想使用ON UPDATE CURRENT_TIMESTAMP
语法,它只支持TIMESTAMP / DATETIME类型。
JodaTime允许我轻松地在时代之间的不同表示和毫秒之间进行转换,但是从使用JDBC / MYSQL开始的时间使用毫秒并不那么简单。
有没有什么办法可以让我们JDBC将milliseconds_since_epoch存储在TIMESTAMP列中,并将TIMESTAMP列作为milliseconds_since_epoch检索,而无需担心由于客户端或服务器更改时区而导致的值更改。
我宁愿不必捣乱MySQL服务器设置或jdbc连接设置,但我愿意如果它是唯一的方法。
有没有什么办法可以让我们JDBC将milliseconds_since_epoch存储在TIMESTAMP列中,并将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.Date
, Calendar
和SimpleDateFormat
等麻烦的旧式遗留日期时间类。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参阅Oracle教程。 并搜索堆栈溢出了很多例子和解释。 规范是JSR 310。
您可以直接与数据库交换java.time对象。 使用符合JDBC 4.2或更高版本的JDBC驱动程序。 不需要字符串,不需要java.sql.*
类。
何处获取java.time类?
ThreeTen-Extra项目将java.time扩展到其他类。 这个项目是未来可能增加java.time的一个试验场。 您可以在这里找到一些有用的课程,例如Interval
, YearWeek
, YearQuarter
等。
上一篇: JDBC MySQL reading and writing TIMESTAMP as milliseconds since Unix Epoch
下一篇: Convert date to datetime or timestamp using alter table in mysql