一、java.util.Date(旧日期类)
1. 介绍
java.util.Date,JDK1.0 诞生,大部分方法过时,开发只记住两个常用构造
- 底层本质:保存一个毫秒值,代表距离1970 年 1 月 1 日 00:00:00 UTC的毫秒数
2. 两个核心构造
// ① Date():创建当前系统时间的Date对象 Date d1 = new Date(); // ② Date(long date):传入毫秒值,构造指定时间 Date d2 = new Date(1000); // 1000ms = 1s3. 常用方法
d1.getTime(); // 获取对象内部的毫秒值 d1.setTime(long ms); // 修改毫秒值,改变时间✅ 缺点:
- 可变对象,线程不安全
- 很多 getYear/getMonth 标记过时,月份从 0 开始,反人类
- 格式化需要 SimpleDateFormat,同样线程不安全
二、JDK8 新时间包 java.time(推荐!不可变、线程安全)
包含:LocalDate(只有日期:年月日)、LocalTime(只有时间:时分秒)、LocalDateTime(日期 + 时间)
特点:不可变对象,修改时间不会改变原对象,返回新对象
2.1 LocalDate(年月日)
创建对象
// now():获取系统当前日期 LocalDate today = LocalDate.now(); // of():指定年月日创建 LocalDate day = LocalDate.of(2025, Month.AUGUST, 10); // 也可以直接传数字 of(2025,8,10)常用获取方法(截图表格)
int year = day.getYear(); // 获取年份 Month m = day.getMonth(); // 获取Month枚举(AUGUST) int month = day.getMonthValue(); // 获取数字月份 1~12 int dayOfMonth = day.getDayOfMonth(); // 获取当月第几天2.2 LocalTime(时分秒)
LocalTime nowTime = LocalTime.now(); LocalTime t = LocalTime.of(14,30,20); //时、分、秒 // 获取 t.getHour(); t.getMinute(); t.getSecond();2.3 LocalDateTime(日期 + 时间,最常用)
// 当前日期时间 LocalDateTime now = LocalDateTime.now(); // 指定构造 LocalDateTime dt = LocalDateTime.of(2025,8,10,14,30); // LocalDate / LocalTime 互相转换 LocalDate date = dt.toLocalDate(); LocalTime time = dt.toLocalTime();2.4 修改时间方法(plus /minus/with,返回新对象)
LocalDateTime newDt = now.plusDays(3); // +3天 LocalDateTime newDt2 = now.minusMonths(1); // -1个月 LocalDateTime newDt3 = now.withYear(2026); // 修改年份三、DateTimeFormatter 格式化 & 解析
替代旧的 SimpleDateFormat,线程安全!
格式模板字母(牢记)
yyyy4 位年MM2 位月份dd2 位日期HH24 小时制小时mm分钟ss秒
完整示例
import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; public class Example21 { public static void main(String[] args) { LocalDateTime now = LocalDateTime.now(); // 1. 创建格式化器,指定模板 DateTimeFormatter fm1 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"); // 方式1:LocalDateTime对象调用format System.out.println("方式1:" + now.format(fm1)); // 方式2:格式化器对象调用format System.out.println("方式2:" + fm1.format(now)); // ===== 解析:字符串 → LocalDateTime ===== String str = "2024-08-15 11:40:35"; DateTimeFormatter fm2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); // parse解析字符串 LocalDateTime ld = LocalDateTime.parse(str, fm2); System.out.println("解析结果:" + ld); } }⚠️ 注意:parse 的时候,字符串格式必须和 ofPattern 模板严格匹配,否则报错
四、新旧 API 对比总结
| 类 | 包 | 是否可变 | 线程安全 | 使用场景 |
|---|---|---|---|---|
| Date | java.util | ✅可变 | ❌不安全 | 老项目维护,不推荐新项目 |
| LocalDate/LocalTime/LocalDateTime | java.time | ❌不可变 | ✅安全 | 新项目首选 |
| DateTimeFormatter | java.time.format | ❌不可变 | ✅安全 | 日期格式化解析(替代 SimpleDateFormat) |
五、高频易错点
- Date 的月份是 0 开始(0 代表 1 月);Local 系列月份是 1 开始,符合正常人思维
- Local 时间对象是不可变:plus/minus/with 必须接收返回值,原对象不变
- ofPattern 模板区分大小写:MM 是月份,mm 是分钟,写反直接出错
- parse 解析字符串,格式模板和文本必须一一对应
- 旧 SimpleDateFormat 不要在多线程共用;DateTimeFormatter 可以全局共用
六、速记口诀
旧 Date 存毫秒,大多方法已过时; Local 新包 JDK8,日期时间分开制; now 拿当前,of 指定值; getMonthValue 拿数字,getMonth 拿枚举; DateTimeFormatter 格式化,模板字母要熟记; yyyy 年 MM 月,HH 时 mm 分 ss 秒; format 转字符串,parse 反向来解析; 新类不可变,线程更安全。