我在Stack Overflow和邮件列表上发现了一些帖子,记录了时区,日期时间等的MySQL JDBC问题。但即便如此,我仍然无法弄清楚这一点。我正在使用如下连接字符串:
jdbc:mysql://localhost:3306/BigSense?useLegacyDatetimeCode=false&serverTimezone=UTC
我使用以下内容插入日期:
stmt.setTimestamp(x, s, Calendar.getInstance(TimeZone.getTimeZone("UTC")))
并且日期在UTC时间内正确地存储在MySQL的DateTime列中。我可以从控制台进行SELECT,并以我发送给服务器的时间格式查看。问题是当我在Java / JDBC中进行SELECT时,由于某种原因它将其转换为我的本地时区!我使用Scala代码如下:
using(stmt.getResultSet()) {
ret =>
if (ret != null) {
val meta = ret.getMetaData()
var retbuf = new ListBuffer[Map[String, Any]]()
while (ret.next) {
val rMap = scala.collection.mutable.Map[String, Any]()
for (i <- 1 to meta.getColumnCount()) {
rMap += (meta.getColumnLabel(i) -> ret.getObject(i))
}
这是旧的Scala代码,所以不要评判我。我意识到我不应该使用retval并且有更多的“Scala”方法来写这个:)
无论如何,我尝试了变体,我检查它是否特别是“时间”列并使用getTimestamp代替,无论是否有Calendar对象选项,我仍然把时间翻译成本地!
这是针对BigSense项目,我正在尝试支持多个数据库(目前完全支持Postgres和MS SQL),所以我试图将代码保持为通用/不可知。我的数据库资料的完整来源可以在这里找到:
https://github.com/sumdog/BigSense/blob/master/src/main/scala/io/bigsense/db/DataHandlerTrait.scala
哦,我也尝试了以下内容:
noTimezoneConversionForTimeType=true
仍然得到相同的结果。我的本地机器设置为NZST,所以如果我从JDBC URL中省略“serverTimezone = UTC”,它就会抱怨。插入工作正常,它们不应该返回转换的SELECT。
答案 0 :(得分:0)
Java时间的东西是奇怪的。时间戳没有你可以设置的时区......但它们确实有一个时区偏移...会影响toString ...但是不能更改...而不能转换为字符串然后回来。
Joda-time似乎解决了其中的一些问题,但也需要一些时间来实施,而且我确定它会导致其他问题。
我的PostgreSQL和Microsoft SQL JDBC驱动程序根本没有为返回的时间戳添加时区(由MySQL确实)(或者至少是影响toString呈现时间戳的方式的偏移量)。我终于得到了这个解决方案:
for (i <- 1 to meta.getColumnCount()) {
rMap += (meta.getColumnLabel(i) -> (ret.getObject(i) match {
case null => null
case ts : Timestamp => {
if(dbDialect == DB_MYSQL) {
//Ensure UTC (MySQL is the only driver that has trouble with this)
val dateFormatGmt = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss.SSS")
dateFormatGmt.setTimeZone(TimeZone.getTimeZone("UTC"))
dateFormatGmt.format(ts)
}
else ts
}
case x:Any => x
}))
}
它非常丑陋,并且由于非标准和有点错误/技术债务缠绕的MySQL JDBC实现而到位。但似乎有效。