导言
我知道以前也有人问过类似的问题。但是我仍然需要为我的用例做更多的测试——我对结果有点惊讶/困惑。
以下是测试和结果的说明(带代码)。
我正在开发一个应用程序:
记录事件历史(在某个时间点发生的事情)。
这段历史是一成不变的。一旦一个事件被写入,我们就不会更改它。
我们报道这段历史。
计划未来的,可能是重复的行动。例如,“每周五做一次检查。”
因此,对时间数据的清晰理解是非常重要的。
我试图理解mysql中的时间戳类型(datetime和timestamp),以及它们如何与java代码和iso8601时间字符串交互。
我已经阅读了mysql文档中关于时间戳类型的内容—它如何将时间值转换为utc存储,以及在检索时如何将utc值转换为服务器或会话时区。听起来像是很好的“时间点”存储。
datetime mysql类型更加不透明。这篇文章(http://code.openark.org/blog/mysql/timestamp-vs-datetime-which-should-i-be-using)认为它与字符串没有太大区别。我重复了“select now()+0;”并得到了与文章相同的答案。
为了澄清问题,我编写了一个小型java类,它写入一个由3列组成的数据库表:
tz(表示标准时区id的字符串)。utc用于测试-但它不是时区。
mydatetime(datetime列)
mytimestamp(timestamp列)
java代码
java代码位于此处:https://gist.github.com/iliomad/c6d8a50613fa99e2d079b8ad3b9eca4d
测试1
我创建了3个不同的iso8601时间戳字符串-都是针对同一时间点-但是偏移量/时区不同。每一个都被写入数据库,检索并打印出来。
首先,我将mysql数据库服务器时区设置为“+00:00”。
输出
向数据库写入时间。
UTC
2018-04-13T11:12:00Z, 1523617920
Europe/Amsterdam
2018-04-13T13:12:00+02:00, 1523617920
Asia/Calcutta
2018-04-13T16:42:00+05:30, 1523617920
从数据库读取存储时间。
Description, Datetime column (epoch seconds), Datetime column (as ISO string), Timestamp column (as epoch seconds), Timestamp column (as ISO string)
UTC, 1523617920, 2018-04-13T11:12:00Z, 1523617920, 2018-04-13T11:12:00Z
Europe/Amsterdam, 1523617920, 2018-04-13T13:12+02:00[Europe/Amsterdam], 1523617920, 2018-04-13T13:12+02:00[Europe/Amsterdam]
Asia/Calcutta, 1523617920, 2018-04-13T16:42+05:30[Asia/Calcutta], 1523617920, 2018-04-13T16:42+05:30[Asia/Calcutta]
一切看起来都很好。纪元秒,当放入https://www.epochconverter.com/,同意iso8601时间字符串。
测试2
然后我将mysql服务器的时区从utc(+00:00)更改为europe/amsterdam(+02:00),并再次读取存储的时间。
输出
从数据库读取存储时间。
Description, Datetime column (epoch seconds), Datetime column (as ISO string), Timestamp column (as epoch seconds), Timestamp column (as ISO string)
UTC, 1523617920, 2018-04-13T11:12:00Z, 1523625120, 2018-04-13T13:12:00Z
Europe/Amsterdam, 1523617920, 2018-04-13T13:12+02:00[Europe/Amsterdam], 1523625120, 2018-04-13T15:12+02:00[Europe/Amsterdam]
Asia/Calcutta, 1523617920, 2018-04-13T16:42+05:30[Asia/Calcutta], 1523625120, 2018-04-13T18:42+05:30[Asia/Calcutta]
我的预期是datetime列会受到影响—认为它没有存储时区信息。但是,移动的是timestamp列。
结论
我们不会经常更改服务器时区。我想看看哪个mysql数据类型最能代表一个时间点——我可以认为它是准确的、不变的(而不是令人头痛的)。在此基础上,如果我以iso8601字符串的形式提供时间点信息,datetime mysql类型将保留提供的信息。
很可能我的测试代码不正确和/或我对结果的解释不正确。我需要一点指导。
在上面的测试用例中,datetime mysql类型在存储时间点信息方面做得更好吗?
1条答案
按热度按时间2exbekwf1#
经过更多的调整,我得到了一个java类,它能够存储和检索时间点信息。我还是有点紧张-这么多的部分想有发言权的时候,这让我不舒服。
这门课的主旨是:https://gist.github.com/iliomad/c6d8a50613fa99e2d079b8ad3b9eca4d (修订显示更改)。
我可以将mysql服务器时区更改为任何我想要的。我还是把我放进去的东西拿出来。
直接在mysql查询管理器中执行的查询也会表现为unix epoch中的timestamp列。这就是我所期望的。
从基本时间中选择tz、mydatetime、unix时间戳(mydatetime)作为mydatetime、unix时间戳(mytimestamp);
tz=时区id(字符串);mydatetime(datetime列);mytimestamp(timestamp列)
timestamp mysql type是一个时间戳。我不需要惹麻烦。
Java8java.sql.timestamp类frominstant和toinstant方法声明维护相同的时间点。
我尝试了setobject和getobject preparedstatement方法。mysql connector/j只是不接受它们——我深入查看了源代码。
datetime mysql类型我仍然有点困惑(我不知道它是什么),但是知道时区我可以维护时间点信息。
我尝试了mysql connector/j5.1.46和8.0.11版本。每个人都有相同的行为。
jdbc参数uselegacydatetimecode=false似乎很重要。我需要运行更多的测试有没有这个来确认。
目前还不能完全分析这个问题。想弄清楚这件事可不好玩。