一、CST 时区混乱

CST是一个混乱的时区,它有四种含义:

  1. 美国标准时间 Central Standard Time (USA):UTC-06:00(或UTC-05:00)。夏令时:3月11日至11月7日,使用 UTC-05:00;冬令时:11月8日至次年3月11日,使用 UTC-06:00
  2. 澳大利亚标准时间 Central Standard Time (Australia):UTC+09:30
  3. 中国标准时 China Standard Time:UTC+08:00
  4. 古巴标准时 Cuba Standard Time:UTC-04:00

中国其实也实行过夏令时,(1992年之后中国已经没有再实行过夏令时了),当实行夏令时,中国标准时间的时区偏移量就是+09:00,当非夏令时,中国标准时间的时区偏移量就是+08:00

CST在Linux、MySQL、Java中的含义:

  • 在Linux或MySQL中,CST表示的是:中国标准时间(UTC+08:00)
  • 在Java中,CST表示的是:中央标准时间(美国标准时间)(UTC-05:00UTC-06:00)

注:Java 的 Date 中的CST是表示的中国标准时间

早期基准是:GMT(格林尼治标准时间)
后来基准是:UTC(协调世界时)

二、Java 时区

@Test
public void testTimeZone() {TimeZone defaultTZ = TimeZone.getDefault();TimeZone shanghaiTZ = TimeZone.getTimeZone("Asia/Shanghai");TimeZone chinaTZ = TimeZone.getTimeZone("GMT+08:00");TimeZone tokyoTZ = TimeZone.getTimeZone("Asia/Tokyo");TimeZone utc = TimeZone.getTimeZone("UTC");TimeZone gmt = TimeZone.getTimeZone("GMT");TimeZone cst = TimeZone.getTimeZone("CST");Date date = new Date(0L);SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");sdf.setTimeZone(defaultTZ);System.out.println(String.format("%-15s %-15s %s", defaultTZ.getID(), defaultTZ.getDisplayName(), sdf.format(date)));sdf.setTimeZone(shanghaiTZ);System.out.println(String.format("%-15s %-15s %s", shanghaiTZ.getID(), shanghaiTZ.getDisplayName(), sdf.format(date)));sdf.setTimeZone(chinaTZ);System.out.println(String.format("%-15s %-15s %s", chinaTZ.getID(), chinaTZ.getDisplayName(), sdf.format(date)));sdf.setTimeZone(tokyoTZ);System.out.println(String.format("%-15s %-15s %s", tokyoTZ.getID(), tokyoTZ.getDisplayName(), sdf.format(date)));sdf.setTimeZone(utc);System.out.println(String.format("%-15s %-15s %s", utc.getID(), utc.getDisplayName(), sdf.format(date)));sdf.setTimeZone(gmt);System.out.println(String.format("%-15s %-15s %s", gmt.getID(), gmt.getDisplayName(), sdf.format(date)));sdf.setTimeZone(cst);System.out.println(String.format("%-15s %-15s %s", cst.getID(), cst.getDisplayName(), sdf.format(date)));
}

控制台输出:

Asia/Shanghai   中国标准时间          1970-01-01 08:00:00
Asia/Shanghai   中国标准时间          1970-01-01 08:00:00
GMT+08:00       GMT+08:00       1970-01-01 08:00:00
Asia/Tokyo      日本标准时间          1970-01-01 09:00:00
UTC             协调世界时           1970-01-01 00:00:00
GMT             格林尼治标准时间        1970-01-01 00:00:00
CST             北美中部标准时间        1969-12-31 18:00:00

在Java中,CST表示的是:中央标准时间(美国标准时间)(UTC-05:00UTC-06:00)

三、MySQL 服务端时区

  • system_time_zone (系统时区):在 MySQL 启动时会检查当前系统的时区并根据系统时区设置全局参数 system_time_zone 的值,默认值一般为 CST
  • time_zone (全局时区或当前会话时区)

可通过 SQL 语句查看:

mysql> show global variables like '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | CST    |
| time_zone        | SYSTEM |
+------------------+--------+
2 rows in set (0.00 sec)

四、Java 与 MySQL 时区转换

1. jdbc 驱动

url : jdbc:mysql://127.0.0.1:3306/nginx_log?serverTimezone=GMT%2B9

对于 mysql-connector-java-8.0.18.jar,设置 jdbc 的 serverSession 时区有:

  1. 获得 mysql 服务端的 time_zone 值,若 time_zone 为 SYSTEM,获得 system_time_zone 的值,可叫做服务端配置的时区
  2. 获取 url 配置的 serverTimezone 的值,可叫做客户端配置的时区
  3. 若 serverTimezone 为 null,设置 serverSession 的时区是服务端的时区;若 serverTimezone 有值,设置 serverSession 的时区是客户端的时区

设置 serverSession 时区优先级:

  • time_zone 是 SYSTEM,serverTimezone > system_time_zone
  • time_zone 不是 SYSTEM,serverTimezone > time_zone

注:从 mysql 服务端获得 system_time_zone 若为 CST,java 中 CST 表示 UTC-05:00 或 UTC-06:00

// com.mysql.cj.protocol.a.NativeProtocol.javapublic void configureTimezone() {String configuredTimeZoneOnServer = this.serverSession.getServerVariable("time_zone");if ("SYSTEM".equalsIgnoreCase(configuredTimeZoneOnServer)) {configuredTimeZoneOnServer = this.serverSession.getServerVariable("system_time_zone");}String canonicalTimezone = getPropertySet().getStringProperty(PropertyKey.serverTimezone).getValue();if (configuredTimeZoneOnServer != null) {// user can override this with driver properties, so don't detect if that's the caseif (canonicalTimezone == null || StringUtils.isEmptyOrWhitespaceOnly(canonicalTimezone)) {try {canonicalTimezone = TimeUtil.getCanonicalTimezone(configuredTimeZoneOnServer, getExceptionInterceptor());} catch (IllegalArgumentException iae) {throw ExceptionFactory.createException(WrongArgumentException.class, iae.getMessage(), getExceptionInterceptor());}}}if (canonicalTimezone != null && canonicalTimezone.length() > 0) {this.serverSession.setServerTimeZone(TimeZone.getTimeZone(canonicalTimezone));//// The Calendar class has the behavior of mapping unknown timezones to 'GMT' instead of throwing an exception, so we must check for this...//if (!canonicalTimezone.equalsIgnoreCase("GMT") && this.serverSession.getServerTimeZone().getID().equals("GMT")) {throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("Connection.9", new Object[] { canonicalTimezone }),getExceptionInterceptor());}}this.serverSession.setDefaultTimeZone(this.serverSession.getServerTimeZone());}

对于 mysql-connector-java-8.0.29.jar 驱动,设置 jdbc 的 serverSession 时区有:

  1. 获取 url 配置的 serverTimezone 的值,可叫做客户端配置的时区
  2. 若 serverTimezone 为 null,设置 serverSession 的时区是 java 的默认时区;若 serverTimezone 有值,设置 serverSession 的时区是客户端的时区

设置 serverSession 时区优先级:

  • serverTimezone > java 默认时区
// com.mysql.cj.protocol.a.NativeProtocol.javapublic void configureTimeZone() {String connectionTimeZone = getPropertySet().getStringProperty(PropertyKey.connectionTimeZone).getValue();TimeZone selectedTz = null;if (connectionTimeZone == null || StringUtils.isEmptyOrWhitespaceOnly(connectionTimeZone) || "LOCAL".equals(connectionTimeZone)) {selectedTz = TimeZone.getDefault();} else if ("SERVER".equals(connectionTimeZone)) {// Session time zone will be detected after the first ServerSession.getSessionTimeZone() call.return;} else {selectedTz = TimeZone.getTimeZone(ZoneId.of(connectionTimeZone)); // TODO use ZoneId.of(String zoneId, Map<String, String> aliasMap) for custom abbreviations support}this.serverSession.setSessionTimeZone(selectedTz);if (getPropertySet().getBooleanProperty(PropertyKey.forceConnectionTimeZoneToSession).getValue()) {// TODO don't send 'SET SESSION time_zone' if time_zone is already equal to the selectedTz (but it requires time zone detection)StringBuilder query = new StringBuilder("SET SESSION time_zone='");ZoneId zid = selectedTz.toZoneId().normalized();if (zid instanceof ZoneOffset) {String offsetStr = ((ZoneOffset) zid).getId().replace("Z", "+00:00");query.append(offsetStr);this.serverSession.getServerVariables().put("time_zone", offsetStr);} else {query.append(selectedTz.getID());this.serverSession.getServerVariables().put("time_zone", selectedTz.getID());}query.append("'");sendCommand(getCommandBuilder().buildComQuery(null, query.toString()), false, 0);}}

综上:解决时区问题,可设置 url 中的 serverTimezone,serverTimezone 与 mysql 服务端的 system_time_zone 保持一致

2.java 与 mysql

Java 系统时区:Asia/Shanghai(东8区)
JDBC 数据库连接时区:serverTimezone=-5
MySQL 全局时区:time_zone=+08:00

Java与MySQL时区相关推荐

  1. java连接mysql时区修改_java连接mysql数据库时的时区设置问题(time_zone)

    java在连接mysql数据库时,会由于时区设置不正确导致报以下的错误: The server time zone value '???ú±ê×??±??' is unrecognized or re ...

  2. java代码中设置mysql时区_关于Java中的mysql时区问题详解

    前言 话说工作十多年,mysql 还真没用几年.起初是外企银行,无法直接接触到 DB:后来一直从事架构方面,也多是解决问题为主. 这次搭建海外机房,围绕时区大家做了一番讨论.不说最终的结果是什么,期间 ...

  3. MySql数据库记录相差14小时排错,使用Java访问Mysql数据库时出现时区异常的解决方案

    最近遇到1个大坑,A系统迁移到B系统,2边系统 同1个字段 createTime 看到的不一致. 表象: A系统: 2019-6-10 17:34 B系统: 2019-6-11 .... 再次尝试: ...

  4. Java连接MySQL数据库时的时区问题

    1.背景 通过Java代码实现向MySQL数据库中存储时间和读取时间, 2.出现的问题 Java代码中的时间点和存到数据库中的时间点不一致,并且验证Linux中的时间点是北京时间. 3.Java代码向 ...

  5. mysql内部时区_一文解决MySQL时区相关问题

    前言: 在使用MySQL的过程中,你可能会遇到时区相关问题,比如说时间显示错误.时区不是东八区.程序取得的时间和数据库存储的时间不一致等等问题.其实,这些问题都与数据库时区设置有关,本篇文章将从数据库 ...

  6. The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized 偶然遇到的mysql时区问题

    因为换了个电脑用,运行时报了个很少见的异常.如下: Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver ...

  7. java获取mysql时间格式化_Java与mysql的时间格式化问题,获取时间的上下午

    Java与mysql的时间格式化问题,获取时间的上下午java 在项目中常常会遇到对时间进行格式化的问题,一次在对应用中发现,使用Java的SimpleDateFormat格式化时间,获取到的是上午, ...

  8. mysql修改系统日期_修改系统和MySQL时区

    修改时间时区比想象中要简单: 各版本系统通用的方法 # cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime # cp /usr/share/zone ...

  9. Java 与 Mysql 时间相差八小时

    Java 与 Mysql 时间相差八小时 在项目中发现,Java获取时间插入到数据库少了8小时 解决过程 最终解决方案 在项目中发现,Java获取时间插入到数据库少了8小时 其实初衷是想做定时去跑我需 ...

最新文章

  1. 基于深度学习的肺癌预测诊断
  2. 函数调用,统计数中'2’的个数
  3. 如何使用matplotlib绘制一个函数的图像
  4. ASP.NET 2.0 学习笔记 1: session 与 script 应用
  5. python画图横轴刻度间隔设置为3个月_Python 天气情况数据分析及可视化
  6. 上位机与1200组态步骤_西门子1200的HSC的应用实例!
  7. ONVIF协议实现1:Server端Discovery的实现详解
  8. sql 拼接int类型的字段_这才是SQL优化的正确姿势!
  9. c语言 函数 收集,c语言库函数大全--资料收集+
  10. DBSCAN聚类(code)
  11. MFC使用简单总结(便于以后查阅)
  12. 【前端】书签应用开发总结
  13. OpenCV实现监控移动侦测
  14. Clickhouse查询语句 sample
  15. nginx容器通过docker内置DNS实现动态负载
  16. C语言二维数组范德蒙,2、编写一个程序,实现一个3×4矩阵转置。
  17. 为什么局部下降最快的方向就是梯度的负方向?
  18. 2022年全国职业技能大赛-网络系统管理竞赛-网络模块-Ruijie-AC-SSH
  19. 软件质量保证和软件配置管理
  20. 随机数的生成【详解】

热门文章

  1. android手机哪家强,Android智能手机充电速度哪家强
  2. 2021考研英语作文石雷鹏
  3. sql server DateName、DatePart 函数
  4. 一元多项式c语言顺序存储,一元多项式相加程序(C语言)
  5. 关于远程连接使用完后已断开连接,服务器端仍显示用户正在连接的解决方法
  6. Oracle数据库一直卡在正在连接中问题解决(Windows)
  7. linux修改密码报错‘Authentication token manipulation error‘
  8. 一个ACM渣渣关于找工作的胡扯
  9. 【编程马拉松】【010-杨辉三角】
  10. Android之乐学成语