MySQL的时区为"GMT+8",而Tomcat的时区为"GMT".当我将datetime保存到数据库时,一切似乎都正常,但当我判断数据库中的datetime值时,我看到了"GMT"值.

另外,当我try 从数据库中获取值时,值被更改,似乎数据库中的值被视为"GMT+8",所以Java将值更改为"GMT".

我将连接URL设置为:

useTimezone=true&serverTimezone=GMT

但它不起作用.

推荐答案

useTimezone是一个较老的解决方案.MySQL团队最近重写了setTimestamp/getTimestamp代码,但只有在设置连接参数useLegacyDatetimeCode=false并且使用最新版本的MySQL JDBC连接器时,才会启用该代码.例如:

String url =
 "jdbc:mysql://localhost/mydb?useLegacyDatetimeCode=false

如果下载mysql连接器源代码并查看setTimestamp,很容易看到发生了什么:

如果use legacy date time code=false,则newSetTimestampInternal(…)被称为.然后,如果传递给newSetTimestampInternal的日历为空,则日期对象将在数据库的时区中格式化:

this.tsdf = new SimpleDateFormat("''yyyy-MM-dd HH:mm:ss", Locale.US);
this.tsdf.setTimeZone(this.connection.getServerTimezoneTZ());
timestampString = this.tsdf.format(x);

日历为空非常重要,因此请确保使用:

setTimestamp(int,Timestamp).

... 不设置时间戳(int、Timestamp、Calendar).

现在应该很清楚这是怎么回事了.如果你用java构建一个日期:2011年1月5日凌晨3:00在美国/洛杉矶(或任何你想要的时区).util.Calendar和call setTimestamp(1,myDate),然后它将记录您的日期,使用SimpleDateFormat将其格式化为database time zone.因此,如果您的DB位于美国/纽约,它将构造要插入的字符串"2011-01-05 6:00:00"(因为纽约领先洛杉矶3小时).

要检索日期,请使用getTimestamp(int)(不带日历).它将再次使用数据库时区来创建日期.

注意:The webserver time zone is completely irrelevant now!如果不将useLegacyDatetimecode设置为false,则webserver时区用于格式化,这会增加很多混乱.


注:

我可能会抱怨服务器时区不明确.例如,如果您的数据库设置为使用EST,那么Java中可能有几个EST时区,因此您可以通过告诉mysql connector数据库时区是什么来澄清这一点:

String url =
 "jdbc:mysql://localhost/mydb?useLegacyDatetimeCode=false&serverTimezone=America/New_York";

只有当它抱怨时,你才需要这样做.

Mysql相关问答推荐

在联合查询中使用GROUP BY和ORDER BY

MySQL有没有办法直接从CSV文件中读取而不是导入它?

查找表中的唯一记录

从单行中获取最大日期的最佳方法

数据导入和默认目标架构空列表. (Mysql 工作台 8)

如何在 SQL 中迭代所有名称和排名排列

MySql SELECT 查找包含数字的区间的时间复杂度是多少?

go&mysql&docker 拒绝连接

mysql insert into select join - 通过连接表将值从一列复制到另一表

由于长时间操作而断开连接后,我的 sql 查询是否继续执行?

在 Presto Athena 中将字符串转换为数组

用两个新列制作表格,按偶数或奇数对另一列进行分类,并将一个类别中的所有偶数和奇数相加

在 MySQL 的存储过程中调用存储过程

在 MySQL Workbench EER 图中的多个列上创建唯一约束

PHP MySQLI 防止 SQL 注入

MySQL行格式:固定和动态之间的区别?

使用 mysqldriver 连接数据库时出错

MySQL 更新连接表

邮箱地址可接受的字段类型和大小?

MySQL中的多列外键?