教程中心 / Java教程 / 日期时间API

日期时间API

8分钟 日期时间

为什么要学习新的日期时间API?

在Java 8之前,开发者主要使用DateCalendar类处理日期时间。但这些旧API存在诸多问题,Java 8引入的全新日期时间API彻底解决了这些问题。

旧API的四大罪状:

  • 可变类:Date和Calendar都是可变的,线程不安全
  • 月份混乱:Calendar月份从0开始计数(0=一月)
  • 命名混乱:Date并不表示日期,只是时间戳
  • 时区麻烦:处理时区非常复杂
// 旧API的痛苦
Date date = new Date(2026 - 1900, 5, 15);  // 月份为什么要减1900,为什么从0开始?
Calendar cal = Calendar.getInstance();
cal.set(2026, 5, 15);  // 5代表六月!不是五月!
date.setMonth(11);  // 什么?我可以直接改内部状态?
// 多线程环境下,这些类是危险的!

Java 8+ 新API的六大核心类

完整类名说明示例
LocalDatejava.time.LocalDate日期(年-月-日)2026-06-15
LocalTimejava.time.LocalTime时间(时:分:秒)14:30:00
LocalDateTimejava.time.LocalDateTime日期时间2026-06-15T14:30:00
ZonedDateTimejava.time.ZonedDateTime带时区的日期时间2026-06-15T14:30+08:00
Instantjava.time.Instant时间戳(UTC)2026-06-15T06:30:00Z
Durationjava.time.Duration时间间隔(秒/纳秒)PT2H30M
Periodjava.time.Period日期间隔(年/月/日)P1M2D

理解这三者的区别

想象你在规划一次旅行:
LocalDate就像日历上的日期——"6月15日",告诉你哪一天,但不关心几点。
LocalTime就像手表上的时间——"下午2:30",告诉你什么时候,但不关心是哪天。
LocalDateTime就像完整的日程安排——"6月15日下午2:30",日期和时间都有。
ZonedDateTime就像带时区的会议通知——"北京时间6月15日下午2:30",明确指出在哪个时区。

新API的六大优势

线程安全

所有日期时间类都是不可变类,天然线程安全

API清晰

不再有月份从0开始等反人类设计

时区支持

完整的时区处理,ZonedDateTime让你轻松处理全球时间

精度灵活

从秒到纳秒,不同场景用不同精度

方法丰富

plusDays、minusHours、withSecond等链式调用

遵循ISO标准

遵循ISO-8601标准,字符串解析和格式化标准化

新旧API对比一览

场景旧API新API
获取当前日期new Date()LocalDate.now()
创建指定日期new Date(2026-1900, 5, 15)LocalDate.of(2026, 6, 15)
日期加法cal.add(Calendar.DAY, 7)date.plusDays(7)
获取年份cal.get(Calendar.YEAR)date.getYear()
月份(Human)cal.get(Calendar.MONTH) + 1date.getMonthValue()
格式化new SimpleDateFormat("yyyy-MM-dd")DateTimeFormatter.ofPattern("yyyy-MM-dd")
线程安全

快速入门示例

import java.time.*;

public class DateTimeQuickStart {
    public static void main(String[] args) {
        // LocalDate - 只关心日期
        LocalDate today = LocalDate.now();
        LocalDate birthday = LocalDate.of(2000, 1, 1);  // 不再是(2000-1900, 0, 1)!
        System.out.println("今天: " + today);
        System.out.println("生日: " + birthday);

        // LocalTime - 只关心时间
        LocalTime now = LocalTime.now();
        LocalTime meeting = LocalTime.of(14, 30);  // 下午2:30
        System.out.println("现在: " + now);
        System.out.println("会议时间: " + meeting);

        // LocalDateTime - 日期和时间都有
        LocalDateTime nowDateTime = LocalDateTime.now();
        LocalDateTime appointment = LocalDateTime.of(2026, 6, 15, 10, 30);
        System.out.println("当前时间: " + nowDateTime);
        System.out.println("预约: " + appointment);

        // Instant - 时间戳(机器友好)
        Instant instant = Instant.now();
        System.out.println("时间戳: " + instant);
        System.out.println("秒数: " + instant.getEpochSecond());
    }
}

小结

  • 旧API问题多:可变、月份从0开始、线程不安全、时区处理复杂
  • LocalDate处理日期(年月日)
  • LocalTime处理时间(时分秒)
  • LocalDateTime处理日期时间(年月日的时分秒)
  • ZonedDateTime处理带时区的日期时间
  • Instant表示UTC时间戳
  • 新API线程安全API清晰遵循ISO标准
☕ Java 在线代码编辑器
📝 运行结果