Java日期时间案例

wen java案例 2

Java日期时间处理实战:从混乱到优雅的完全指南

目录导读

  1. Java日期时间的前世今生 - 为什么我们总是搞混?
  2. 核心API对比:java.util.Date vs java.time - 谁才是现代开发的王者?
  3. 高频案例:格式化、解析、时区转换 - 直接复制可用的代码
  4. 实战陷阱与最佳实践 - 避免80%程序员踩过的坑
  5. 问答环节:解决你最后的疑惑 - 面试与项目双保险

Java日期时间的前世今生

在Java 8之前,java.util.DateSimpleDateFormat几乎是所有开发者的噩梦。可变性、线程不安全、时区处理反人类——这是老API的三大致命伤,举个经典例子:

Java日期时间案例

Date date = new Date(2024, 0, 1); // 竟然是1900+2024年?月份从0开始?

而Java 8引入的java.time包(基于JSR-310)彻底改变了这一局面。不可变类、线程安全、链式调用、ISO标准——这就是现代日期时间处理的王牌。

核心API对比:谁是王者?

场景 老API(Date/Calendar) 新API(java.time)
获取当前时间 new Date() LocalDateTime.now()
格式化 SimpleDateFormat(非线程安全) DateTimeFormatter(线程安全)
时区转换 Calendar.setTimeZone() ZonedDateTime.withZoneSameInstant()
日期计算 Calendar.add()(易错) plusDays() / minusMonths()(链式清晰)

关键结论:任何新项目请直接拥抱java.time,老代码迁移时也用Date.toInstant()桥接。

高频实战案例(可直接复用)

案例1:字符串与日期互转(最常用)

// 解析字符串 -> LocalDate
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
LocalDate date = LocalDate.parse("2025/03/15", formatter);
// 格式化输出
String formatted = date.format(DateTimeFormatter.ISO_LOCAL_DATE); // 2025-03-15

案例2:时区转换(跨国应用必备)

// 北京 -> 纽约
ZonedDateTime beijing = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
ZonedDateTime newYork = beijing.withZoneSameInstant(ZoneId.of("America/New_York"));
System.out.println("北京时间: " + beijing);
System.out.println("纽约时间: " + newYork);

注意withZoneSameInstant()是瞬间点转换,而withZoneSameLocal()只改标签不动时间点。

案例3:计算两个日期差(订单超时判断)

LocalDateTime start = LocalDateTime.of(2025, 3, 1, 10, 0);
LocalDateTime end = LocalDateTime.of(2025, 3, 18, 14, 30);
Duration duration = Duration.between(start, end);
long hours = duration.toHours(); // 412小时

实战陷阱与最佳实践

陷阱1:LocalDateTime不是瞬间
它无时区信息,所以不能直接转时间戳,应改用InstantZonedDateTime

陷阱2:DateTimeFormatteryyyy vs uuuu
ISO规范推荐uuuu表示公元年,yyyy是"纪元年份",绝大部分场景用uuuu更安全。

陷阱3:老API转换时的隐式时区
Date.toInstant()默认使用系统时区,最好显式指定:

ZonedDateTime zdt = date.toInstant().atZone(ZoneId.of("UTC"));

最佳实践清单

  • 所有日期字段用LocalDateLocalDateTime,持久化到数据库时用TIMESTAMP WITH TIME ZONE
  • 存储统一UTC,展示时转本地时区
  • 使用Clock注入时间源,便于测试

问答环节:解决你最后的疑惑

Q1:java.util.Date还在用,我该立即迁移吗?
A:如果项目稳定,优先新代码用java.time,老代码可以在IO边界处转换,不必全量重写,但绝不要在新代码中使用SimpleDateFormat

Q2:为什么LocalDateTime.now()在不同时区下结果不同?
A:因为它取的是当前时区的本地时间,如果你想要全球统一的时间点,用Instant.now()

Q3:如何安全地把时间戳(long)转为LocalDate
A:分两步:

Instant instant = Instant.ofEpochMilli(timestamp);
LocalDate date = instant.atZone(ZoneId.systemDefault()).toLocalDate();

Q4:PeriodDuration有什么区别?
A:Period用于日期(年/月/日),Duration用于时间(小时/分钟/秒),不要混用。


结尾点睛:掌握java.time不是记住API,而是理解时间点、本地时间、时区三者关系,多写测试用例,用Clock模拟不同时间,你的日期处理代码会变得异常稳健,如果这篇文章对你有帮助,欢迎收藏转发,让更多开发者摆脱日期处理的噩梦。

抱歉,评论功能暂时关闭!