应直接学习Java 8的java.time包,从LocalDate、LocalTime、LocalDateTime三个不可变类型入手,掌握格式化(DateTimeFormatter)、跨时区(ZoneId)、时间差(Duration/Period)及数据库存储等核心用法,并规避返回新对象、月份编号、时区误解等常见错误。

直接用 Java 8 的 java.time 包学,别绕弯——它就是当前唯一该投入时间掌握的日期时间 API。
从三个不可变类型开始建立直觉
先忘掉 Date 和 Calendar。每天动手写三行,形成肌肉记忆:
-
LocalDate:只管“哪一天”,比如请假单上的开始日期。用
LocalDate.now()看今天,LocalDate.of(2026, 10, 9)写固定日,date.plusDays(7)算下周同日(返回新对象,原值不变) -
LocalTime:只管“几点几分”,比如会议室预约的起止时刻。用
LocalTime.now()获取当前时间,LocalTime.of(14, 30)构造下午两点半 - LocalDateTime:日期+时间合体,但依然“没时区”。适合记录系统日志时间戳(本地服务器时间)、订单创建时间等不跨地域的场景
格式化和解析必须用 DateTimeFormatter
字符串 ↔ 时间对象的转换,只靠它,且必须严格匹配:
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 用预设常量最省心:
DateTimeFormatter.ISO_LOCAL_DATE对应"2026-10-09",DateTimeFormatter.ISO_LOCAL_DATE_TIME对应"2026-10-09T14:22:05" - 自定义格式加引号防歧义:
DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss")→"2026年10月09日 08:41:22" - 解析失败会抛
DateTimeParseException,不是静默忽略。调试时先确认字符串是否真能被模式完全覆盖,比如带空格或中文标点就容易崩
跨时区、算间隔、存数据库,按需选对类型
遇到实际问题再往上走,不堆概念:
立即学习“Java免费学习笔记(深入)”;
- 要显示“纽约现在几点”?用
Instant.now().atZone(ZoneId.of("America/New_York")),别碰SimpleDateFormat - 计算两个时间差多少小时?用
Duration.between(start, end);差多少天/月/年?用Period.between(date1, date2) - 存进 MySQL 的
TIMESTAMP字段?用LocalDateTime;存DATETIME?也用LocalDateTime;需要保留 UTC 时间?用Instant或ZonedDateTime
避坑比语法更重要
几个高频错误点,写一次记一辈子:
- 所有操作都返回新对象,
date.plusDays(1)不改变date,忘了重新赋值就会出错 - 月份是 1–12,不是 0–11;星期一是
DayOfWeek.MONDAY,不是数字 1 - 不要把
LocalDateTime当成带时区的时间,它没有时区含义,强行转ZonedDateTime会默认用系统时区,可能引发线上时间错乱 - 旧 API(
Date、Calendar)只在对接老系统或遗留库时才接触,新代码里绝不出现

















