0
点赞
收藏
分享

微信扫一扫

Java日期时间终极指南:从Calendar到java.time与Hutool

一、 “黑历史”:Date 与 Calendar 的深坑

在拥抱新世界之前,我们必须了解旧世界的“坑”在哪里。

1. java.util.Date 的“原罪”

  • 名不副实: Date 类名暗示它代表一个“日期”,但它实际上是一个精确到毫秒的时间戳,代表自 1970-01-01T00:00:00Z(UTC)以来的毫秒数。它包含了时间信息,却叫Date
  • 可变性 (Mutability):Date 对象是可变的!它的 setYear()setMonth()setDate() 等方法会直接修改对象本身。

Date date1 = new Date();
Date date2 = date1; // 引用同一个对象
date2.setYear(123); // 意外修改了date1!
System.out.println(date1); // 输出被修改后的值

  • 后果: 在多线程环境下极易引发数据错乱,不是线程安全的。
  • 糟糕的设计: 月份从0开始(0=1月,11=12月),日期从1开始,这种不一致性是无数Bug的根源。
  • 时区处理混乱: Date 内部存储的是UTC时间戳,但其 toString() 方法会根据JVM的默认时区进行格式化,容易造成误解。

2. java.util.Calendar 的“补丁”与新坑

Calendar 被设计用来弥补Date的不足,但它本身问题更多。

  • 复杂且笨重: API极其繁琐。获取年份需要 calendar.get(Calendar.YEAR)
  • 依然是可变的: 和Date一样,setadd方法会修改自身。
  • 创建成本高: Calendar.getInstance() 是一个重量级操作,不应在循环中频繁调用。
  • 线程不安全: 多个线程共享一个Calendar实例是灾难性的。

结论: 在新项目中,应彻底避免使用 DateCalendar 进行业务逻辑处理。 它们仅应在与旧API(如JDBC)交互时作为“适配器”使用。

二、 现代曙光:java.time 包 (JSR-310)

Java 8引入的java.time包是日期时间处理的银弹。它基于不可变对象设计,API清晰,功能强大。

核心类概览


用途

是否有时区

示例

Instant

时间线上的一个瞬时点,精确到纳秒。类似旧的Date,但不可变。

❌ (UTC)

2023-10-27T10:15:30.123456789Z

LocalDateTime

本地日期时间,没有时区概念。常用于数据库中的DATETIME类型。


2023-10-27T10:15:30

ZonedDateTime

带时区的日期时间。处理跨时区业务的首选。


2023-10-27T10:15:30+08:00[Asia/Shanghai]

OffsetDateTime

带偏移量的日期时间。偏移量是固定的(如+08:00),不包含时区规则(如夏令时)。


2023-10-27T10:15:30+08:00

LocalDate

仅日期,无时间无时区。


2023-10-27

LocalTime

仅时间,无日期无时区。


10:15:30

ZoneId

时区ID,如 Asia/ShanghaiUTC

Duration

时间量,基于时间的(秒、纳秒)。用于Instant间计算。

PT2H30M (2小时30分钟)

Period

时间量,基于日期的(年、月、日)。用于LocalDate间计算。

P1Y2M10D (1年2个月10天)

核心实践:java.time API 实战

  1. 创建与获取当前时间

// 获取当前时间
LocalDateTime now = LocalDateTime.now(); // 系统默认时区
LocalDateTime nowInUtc = LocalDateTime.now(ZoneOffset.UTC); // UTC
ZonedDateTime nowWithZone = ZonedDateTime.now(); // 包含时区信息

// 从字符串解析
LocalDateTime dt = LocalDateTime.parse("2023-10-27T10:15:30");
LocalDate date = LocalDate.parse("2023-10-27");

// 构造特定时间
LocalDateTime specific = LocalDateTime.of(2023, 10, 27, 10, 15, 30);

  1. 格式化与解析 (DateTimeFormatter)

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = now.format(formatter); // LocalDateTime -> String

LocalDateTime parsed = LocalDateTime.parse("2023-10-27 10:15:30", formatter); // String -> LocalDateTime

常用预定义格式器: DateTimeFormatter.ISO_LOCAL_DATE, DateTimeFormatter.BASIC_ISO_DATE

举报

相关推荐

0 条评论