mysql服务器和客户端时区不同,使用jdbc得到的结果差8小时的问题

默认情况下mysqltime_zoneSYSTEM,也就是mysql的时区和服务器的时区是一样的。一般服务器都是东八区。在使用mysql时,客户端所在的时区一般也是东八区。所以从mysql查询timestamp类型数据时一切正常。

现在如果我们的条件是这样的:

  1. 使用的jdbc url长这样jdbc:mysql://localhost:3306/table_name
  2. 客户端的时区为零时区
  3. mysql的时区是东八区

上面几个条件如果满足了,这时候你从mysql查找timestamp的数据,拿到的timestamp值和数据库中的值是一样的,没有考虑时区的问题,所以事实上是多了8小时。

通过debug,发现jdbcConnectionImpl类中configureTimezone()配置time zone时有几个条件

        String canonicalTimezone = getServerTimezone();

        if ((getUseTimezone() || !getUseLegacyDatetimeCode()) && configuredTimeZoneOnServer != null) {
            // user can override this with driver properties, so don't detect if that's the case
            if (canonicalTimezone == null || StringUtils.isEmptyOrWhitespaceOnly(canonicalTimezone)) {
                try {
                    canonicalTimezone = TimeUtil.getCanonicalTimezone(configuredTimeZoneOnServer, getExceptionInterceptor());
                } catch (IllegalArgumentException iae) {
                    throw SQLError.createSQLException(iae.getMessage(), SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor());
                }
            }
        }

        if (canonicalTimezone != null && canonicalTimezone.length() > 0) {
            this.serverTimezoneTZ = TimeZone.getTimeZone(canonicalTimezone);
            ...

getServerTimezone()方法拿到的值默认为nullgetUseTimezone()getUseLegacyDatetimeCode()方法得到的值分别是falsetrue,这样就导致了connector不会使用数据库的time zone。所以我们从数据库内读取timestamp数据,不做任何时区转化。

如果想要开启时区转换,需要将useTimezone设置为true, 即jdbc:mysql://localhost:3306/table_name?useTimezone=true

我们可以看mysql文档对useTimezone描述

useTimezone
Convert time/date types between client and server time zones (true/false, defaults to ‘false’)? This is part of the legacy date-time code, thus the property has an effect only when “useLegacyDatetimeCode=true.”
Default: false

useTimezone设置为true后,还有一点很重要,如果mysqltime_zoneSYSTEM,连接数据库是会报错的,需要给定一个明确的时区。我们可以把数据库的time_zone设置为+08:00,这样timestamp的数据就会根据时区进行转换。 如果不想修改数据库的time_zone,可以在客户端进行设置,指定time_zonejdbc:mysql://localhost:3306/table_name?useTimezone=true&serverTimezone=GMT%2B8,GMT%2B8表示东八区。

猜你喜欢

转载自blog.csdn.net/sweatott/article/details/78111748
今日推荐