Java中PreparedStatement处理日期需用java.sql.Date/Time/Timestamp,不可直接传java.util.Date或LocalDateTime;应通过valueOf、from或atZone转换,并匹配SQL类型,设null用setNull,MySQL连接建议加serverTimezone=UTC。

Java 中 PreparedStatement 处理日期类型参数,核心是**用对应 setXXX() 方法传入 java.sql 类型(如 Date、Time、Timestamp)**,而不是直接传 java.util.Date 或 LocalDateTime 等。关键在于类型匹配和时区一致性。
用 java.sql.Date / Time / Timestamp 传参
PreparedStatement 不接受 java.util.Date、LocalDateTime、ZonedDateTime 等 Java 8 时间类直接传入(会报 SQLException)。必须转换为 java.sql 子类:
-
日期(年月日)→ java.sql.Date:用
java.sql.Date.valueOf(LocalDate),或new java.sql.Date(utilDate.getTime()) -
时间(时分秒)→ java.sql.Time:用
java.sql.Time.valueOf(LocalTime) -
日期+时间(精确到毫秒)→ java.sql.Timestamp:推荐用于大多数带时间的场景,可用
Timestamp.from(Instant)或new Timestamp(utilDate.getTime())
推荐写法:优先用 Instant + Timestamp(避免时区陷阱)
java.util.Date 和 java.sql.Timestamp 都基于毫秒数,但隐含系统默认时区,容易出错。更安全的方式是统一用 UTC 时间戳:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 从 LocalDateTime 转:先指定时区 → 转 Instant → 转 Timestamp
LocalDateTime ldt = LocalDateTime.of(2024, 5, 20, 14, 30);<br> Instant instant = ldt.atZone(ZoneId.systemDefault()).toInstant();<br> ps.setTimestamp(1, Timestamp.from(instant)); - 从字符串解析:用 DateTimeFormatter + ZoneId 显式控制时区
Instant.parse("2024-05-20T14:30:00Z")(ISO 8601 带 Z 表示 UTC)
数据库字段类型要匹配
SQL 类型决定该用哪个 java.sql 类:
立即学习“Java免费学习笔记(深入)”;
- DATE(仅日期)→ java.sql.Date(否则时间部分会被截断或报错)
- TIME(仅时间)→ java.sql.Time
- TIMESTAMP / DATETIME → java.sql.Timestamp(保留毫秒和时区语义)
- PostgreSQL 的
timestamptz建议用setObject(1, OffsetDateTime)(JDBC 4.2+),更精准
注意 null 值和时区配置
设空值用 ps.setNull(index, Types.DATE) 等,别用 setDate(null)(会 NPE);另外,MySQL 连接串建议加 serverTimezone=UTC,避免 JDBC 自动转换引入偏差。

















