🔍 一、 java.util.Date:过时设计的“时间戳”
Date本质是自1970-01-01T00:00:00Z的毫秒偏移量(long存储)。其API设计存在严重问题:
Date date = new Date(124, 5, 15); // 坑1:年份=当前年-1900 (2024→124), 月份0基 (5→六月)
System.out.println(date.getYear() + 1900); // 必须+1900获取真实年份(输出2024)
System.out.println(date.getMonth()); // 输出5 (实际是6月)
// 坑2:非线程安全!SimpleDateFormat格式化需额外同步
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String unsafeFormat = sdf.format(date); // 多线程下可能出错
⚙️ 二、 java.util.Calendar:复杂而脆弱的补救方案
Calendar试图解决时区与字段计算问题,但引入新痛点:
Calendar cal = Calendar.getInstance();
cal.set(2024, Calendar.JUNE, 15); // 月份常量仍为0基(JUNE=5)
// 坑1:Mutable对象,计算会修改原实例
cal.add(Calendar.DAY_OF_MONTH, 10); // 直接修改cal对象
// 坑2:时区转换繁琐易错
cal.setTimeZone(TimeZone.getTimeZone("America/New_York"));
System.out.println(cal.get(Calendar.HOUR_OF_DAY)); // 输出纽约时间
// 坑3:API冗余,获取年份需用get(Calendar.YEAR)
int year = cal.get(Calendar.YEAR); // 非直观的链式操作
🚀 三、 救世主:Java 8的 java.time API
立即弃用Date/Calendar,拥抱现代时间库:
// 明确不可变对象 + 清晰API
LocalDate date = LocalDate.of(2024, Month.JUNE, 15); // 月份枚举(JUNE=6)
LocalDateTime dateTime = date.atTime(14, 30);
// 安全时区转换
ZonedDateTime nyTime = dateTime.atZone(ZoneId.of("America/New_York"));
ZonedDateTime utcTime = nyTime.withZoneSameInstant(ZoneOffset.UTC);
// 直观计算(返回新对象)
LocalDate nextWeek = date.plusWeeks(1);
💡 关键结论与迁移建议
Date仅作时间戳载体:用new Date()获取时间戳后,立即转为Instant或java.time对象- 禁用
Calendar进行复杂运算:时区操作、字段加减均用ZonedDateTime/OffsetDateTime
新旧API互转:
Instant instant = oldDate.toInstant(); // Date → Instant
ZonedDateTime newDt = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
Calendar cal = Calendar.getInstance();
cal.setTime(Date.from(newDt.toInstant())); // java.time → Date (万不得已时)
- 逐步重构:老旧项目可用适配器封装,新代码强制使用
java.time
📌 终极建议:将项目JDK升级至Java 8+,彻底告别Date和Calendar的时空陷阱。 清晰、安全、强大的java.time才是Java时间处理的未来!

被折叠的 条评论
为什么被折叠?



