LocalDateTime 无时区,仅表示本地日历时间;ZonedDateTime 绑定时区(如 Asia/Shanghai),可正确处理夏令时和历史变更,适用于跨系统比对与持久化。

LocalDateTime 和 ZonedDateTime 的核心区别在哪
用 LocalDateTime 表示“2024-05-20T14:30:00”只是本地日历时间,不带时区信息;ZonedDateTime 则明确绑定到某个时区(如 Asia/Shanghai),能正确处理夏令时、历史时区变更等场景。
常见错误:把服务器本地时间直接转成 ZonedDateTime 却没指定时区,结果默认用了系统时区,部署到海外服务器就出错。
-
LocalDateTime.now()永远不包含时区,不能用于跨系统时间比对或持久化存储 -
ZonedDateTime.now(ZoneId.of("Asia/Shanghai"))才是真正代表东八区当前时刻的可靠值 - 数据库字段类型要匹配:PostgreSQL 用
timestamptz存ZonedDateTime,别用timestamp without time zone
Instant 是什么,为什么它适合做时间戳存储
Instant 表示从 1970-01-01T00:00:00Z 开始的纳秒偏移量,本质就是 UTC 时间轴上的一个点。它没有时区概念,也不受本地格式影响,是跨系统、跨语言最安全的时间表示方式。
常见错误:用 System.currentTimeMillis() 构造 LocalDateTime,结果丢失了时区上下文,再转回 Instant 可能偏差一整天。
立即学习“Java免费学习笔记(深入)”;
- 入库前一律转成
Instant:zonedDateTime.toInstant()或localDateTime.atZone(ZoneId.of("UTC")).toInstant() -
前端传来的 ISO 格式字符串(如
"2024-05-20T14:30:00Z")可直接用Instant.parse() - 不要用
new Date().toInstant()——Date是遗留类,语义模糊,容易引发隐式时区转换
DateTimeFormatter 的 pattern 字符必须严格区分大小写
yyyy 和 YYYY 不是一回事:yyyy 是“年份”,YYYY 是“基于周的年份”,在每年年初或年末可能差一年;MM 是月份,mm 是分钟,写错就解析失败或结果错乱。
常见错误:用 DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") 解析带毫秒的字符串(如 "2024-05-20T14:30:00.123"),抛出 DateTimeParseException。
- 解析含毫秒的 ISO 时间,优先用内置常量:
DateTimeFormatter.ISO_LOCAL_DATE_TIME或DateTimeFormatter.ISO_INSTANT - 自定义 pattern 必须匹配输入:毫秒用
SSS,纳秒用nnn,时区用XXX(如+08:00)或ZZZ(如GMT+08:00) - 避免手动拼接字符串:用
LocalDateTime.format()而不是String.format(),后者无法处理时区偏移
ZoneId 和 ZoneOffset 的使用边界
ZoneOffset 是固定偏移(如 +08:00),不随夏令时变化;ZoneId 是真实地理时区(如 Europe/London),会自动应用 DST 规则。两者不能混用。
常见错误:用 ZoneOffset.of("+08:00") 替代 ZoneId.of("Asia/Shanghai"),看似一样,但遇到中国未来调整时区规则时,前者永远不变,后者可通过 JDK 更新支持新规则。
- 只在明确需要固定偏移的场景用
ZoneOffset(如日志时间统一打成 UTC+0) - 涉及用户本地时间、业务营业时间、节假日计算等,必须用
ZoneId -
ZoneId.systemDefault()不可靠——服务器时区可能被运维修改,应显式配置并注入,比如 Spring Boot 中通过@Value("${app.timezone:Asia/Shanghai}")
ZoneId shanghai = ZoneId.of("Asia/Shanghai");
LocalDateTime local = LocalDateTime.of(2024, 3, 31, 2, 30, 0); // 凌晨2:30
ZonedDateTime zdt = local.atZone(shanghai); // 自动按规则处理是否为夏令时(中国不实行,但逻辑存在)
System.out.println(zdt); // 2024-03-31T02:30+08:00[Asia/Shanghai]
时区规则更新、夏令时边界、毫秒精度截断——这些细节不会报错,但会在特定日期、特定地区悄悄出错。写时间逻辑时,别依赖“看起来对”。










