datetime时间错误的根源是时区未对齐,因mysql datetime无时区信息,客户端按本地时区自动转换,导致服务端、数据库连接、客户端三者时区不一致(如utc+0与utc+8),常见偏差8小时;需统一配置数据库服务器时区、连接参数(如servertimezone=asia/shanghai)、驱动时区选项及jvm时区。

查出来的 datetime 字段时间不对,大概率是时区没对齐
数据库里存的 datetime 本身不带时区信息(比如 MySQL 的 DATETIME 类型),但客户端读取时会按本地时区自动转换——如果服务端、数据库连接、客户端三者时区配置不一致,就容易出现固定差 8 小时(典型如 UTC+0 vs UTC+8)。
常见错误现象:SELECT NOW() 在命令行返回的是北京时间,但在 Python 或 Navicat 里显示成 UTC 时间;或者 created_at 字段查出来比实际晚/早 8 小时。
- 先确认数据库服务器时区:
SELECT @@global.time_zone, @@session.time_zone; - 检查连接字符串是否显式指定时区,例如 JDBC 要加
serverTimezone=Asia/Shanghai,否则默认用系统 UTC - MySQL 客户端连接后执行
SET time_zone = '+08:00';可临时修正,但不推荐长期依赖
Python pymysql / mysql-connector-python 默认把 DATETIME 当成本地时间解析
这两个驱动默认将 DATETIME 字段当作“无时区时间”,然后用 Python 进程所在系统时区解释——如果你服务器是 UTC,代码跑在 Docker 容器里没设时区,就会少 8 小时。
解决方式不是改数据库,而是控制客户端行为:
- pymysql:初始化连接时传参
timezone='+08:00',或连接后执行cursor.execute("SET time_zone = '+08:00'") - mysql-connector-python:连接参数加
time_zone='+08:00',注意不是timezone - 更稳妥的做法:用
TIMESTAMP类型存时间(它自带 UTC 存储 + 自动时区转换),配合连接层统一设time_zone
Navicat / DBeaver 等 GUI 工具显示异常,优先看连接属性里的时区设置
这类工具往往默认使用系统时区解析时间字段,但不会主动同步数据库时区。比如数据库是 SYSTEM(即系统时区为 CST),而你的 macOS 系统时区是 Asia/Shanghai,但 Navicat 没读到这个上下文。
- Navicat:右键连接 → “编辑连接” → “高级” → 勾选“使用服务器时区”或手动填入
+08:00 - DBeaver:连接设置 → “Driver Properties” → 找
serverTimezone,设为Asia/Shanghai - 别信“自动检测”——很多版本根本没实现,必须手动指定
Spring Boot + MyBatis 查询时间偏移,重点查 jdbcUrl 和 JVM 时区
jdbc:mysql://... 这串 URL 里缺 serverTimezone 是最常见原因;另一个隐蔽问题是 JVM 启动时没设 -Duser.timezone=GMT+08,导致 SimpleDateFormat 或 LocalDateTime 解析出错。
- 确保 jdbcUrl 包含
?serverTimezone=Asia/Shanghai&useTimezone=true - application.yml 中不要只配
spring.jackson.time-zone: GMT+8,它只管 JSON 序列化,不影响 JDBC 层 - 如果用了 HikariCP,注意它的
connection-init-sql可以加SET time_zone = '+08:00'作为兜底
时区问题从来不是单点故障,而是数据库、驱动、JVM、OS 四层时钟对齐失败。调的时候别只盯着 SQL,先抓连接串和启动参数里的 serverTimezone 和 user.timezone。











