java.time 包是 Java 8 引入的现代日期时间 API(JSR-310),在JDK 17中依然沿用, 设计清晰、不可变、线程安全,取代了老旧的 java.util.DateCalendar。以下是其中最常用的核心类及其用途,适合日常开发使用:

✅ 一、核心日期时间类

说明典型用途
LocalDateTime本地日期时间(无时区)表示如 2025-10-22T14:30:00,常用于日志、业务时间(不涉及时区)
LocalDate仅日期(无时、无时区)如 2025-10-22,用于生日、订单日期等
LocalTime仅时间(无日期、无时区)如 14:30:45,用于闹钟、营业时间等
ZonedDateTime带时区的完整日期时间如 2025-10-22T14:30:00+08:00[Asia/Shanghai],用于全球时间处理
Instant时间戳(UTC 时刻)表示从 Unix Epoch(1970-01-01T00:00:00Z)开始的纳秒数,用于系统时间、日志时间戳

💡 LocalDateTimeInstant:前者是“本地视角”的时间(如“今天下午2点”),后者是“全球统一时刻”(如“UTC时间某毫秒”)。

✅ 二、时区与区域相关

说明
ZoneId表示时区,如 ZoneId.of("Asia/Shanghai") 或 ZoneId.systemDefault()
ZoneOffset表示固定偏移量,如 +08:00(不包含夏令时规则)
Clock提供对当前时间的访问,支持测试时 mock 时间

✅ 三、格式化与解析

说明
DateTimeFormatter用于格式化和解析日期时间字符串
✅ 预定义常量:
ISO_LOCAL_DATE_TIME
ofPattern("yyyy-MM-dd HH:mm:ss")
LocalDateTime now = LocalDateTime.now();
String text = now.format(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"));
LocalDateTime parsed = LocalDateTime.parse("2025/10/22 14:30", 
    DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"));

✅ 四、时间段与周期

说明示例
Duration表示时间量(基于秒/纳秒),用于机器时间差Duration.between(start, end) → 2小时30分
Period表示日历量(年/月/日),用于人类可读周期Period.between(birthDate, today) → 25年3个月
// 计算两个时间相差多少小时
Duration dur = Duration.between(LocalDateTime.now(), futureTime);
long hours = dur.toHours();

// 计算年龄
LocalDate birth = LocalDate.of(1990, 5, 15);
Period age = Period.between(birth, LocalDate.now());
System.out.println(age.getYears() + "岁");

✅ 五、时间单位(用于计算)

说明
ChronoUnit枚举类,表示时间单位(DAYSHOURSMINUTESYEARS 等)
long days = ChronoUnit.DAYS.between(date1, date2);
LocalDateTime nextWeek = now.plus(7, ChronoUnit.DAYS);

✅ 六、其他实用类

说明
YearYearMonthMonthDay表示部分日期
YearMonth.of(2025, 10) → 2025年10月(适合信用卡有效期)
MonthDay.of(12, 25) → 每年12月25日(适合生日提醒)
TemporalAdjusters提供高级日期调整器
如:firstDayOfMonth()lastDayOfYear()
LocalDate firstDay = today.with(TemporalAdjusters.firstDayOfMonth());
LocalDate nextFriday = today.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));

📌 使用建议总结

场景推荐类
系统时间戳、日志时间Instant
数据库 datetime 字段(无时区)LocalDateTime
用户生日、订单日期LocalDate
全球会议时间、跨时区应用ZonedDateTime
时间差(机器计算)Duration
年龄、日历周期Period
格式化输出DateTimeFormatter
时区处理ZoneId + ZonedDateTime

❌ 避免使用的旧类(JDK 8+ 不推荐)

  • java.util.Date
  • java.util.Calendar
  • java.text.SimpleDateFormat(非线程安全!)

示例:完整常用操作

// 1. 当前时间
LocalDateTime now = LocalDateTime.now();

// 2. 指定时间
LocalDateTime dt = LocalDateTime.of(2025, 10, 22, 14, 30);

// 3. 加7天
LocalDateTime nextWeek = dt.plusDays(7);

// 4. 转时间戳
long timestamp = dt.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();

// 5. 格式化
String str = dt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));

// 6. 解析
LocalDateTime parsed = LocalDateTime.parse("2025-10-22 14:30", 
    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));

// 7. 计算相差天数
long days = ChronoUnit.DAYS.between(now, dt);

DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") 默认不包含时区信息,因为它通常用于格式化 LocalDateTime(无时区)。若你想在格式化结果中带上时区,需要满足两个条件:

  1. 使用带时区的时间对象(如 ZonedDateTime 或 OffsetDateTime
  2. 在 pattern 中显式加入时区符号

✅ 正确做法:使用 ZonedDateTime + 时区 pattern

示例 1:显示时区 ID(如 Asia/Shanghai
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
String result = zdt.format(formatter);
System.out.println(result); 
// 输出:2025-10-22 10:30:45 CST (或 Asia/Shanghai,取决于系统)

z 表示 时区名称(如 CST, PST, GMT),但可能不显示完整 ID。

示例 2:显示完整时区 ID(推荐用于日志或调试)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss VV");
String result = zdt.format(formatter);
System.out.println(result); 
// 输出:2025-10-22 10:30:45 Asia/Shanghai

VV 表示 时区 ID(ZoneId),如 Asia/ShanghaiEurope/London至少需要两个 V


示例 3:显示 UTC 偏移量(如 +08:00
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss XXX");
String result = zdt.format(formatter);
System.out.println(result); 
// 输出:2025-10-22 10:30:45 +08:00

常用偏移 pattern:

  • X → +08
  • XX → +0800
  • XXX → +08:00(最常用)

⚠️ 重要:不能对 LocalDateTime 使用时区 pattern!

LocalDateTime ldt = LocalDateTime.now();
// ❌ 错误!LocalDateTime 没有时区,会抛异常
ldt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss VV")); // DateTimeException

必须先转为带时区对象

LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
String s = zdt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss XXX"));

✅ 推荐组合(根据需求选择)

需求Pattern示例输出
显示偏移量(通用)"yyyy-MM-dd HH:mm:ss XXX"2025-10-22 10:30:45 +08:00
显示完整时区 ID"yyyy-MM-dd HH:mm:ss VV"2025-10-22 10:30:45 Asia/Shanghai
ISO 8601 标准格式DateTimeFormatter.ISO_ZONED_DATE_TIME2025-10-22T10:30:45+08:00[Asia/Shanghai]

🔁 反向:带时区字符串解析

String text = "2025-10-22 10:30:45 +08:00";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss XXX");

// 解析为 OffsetDateTime(推荐)
OffsetDateTime odt = OffsetDateTime.parse(text, formatter);

// 或转为 ZonedDateTime
ZonedDateTime zdt = odt.atZoneSameInstant(ZoneId.of("Asia/Shanghai"));

注意:用 ZonedDateTime.parse() 需要 pattern 包含 zone ID(如 VV),否则建议先用 OffsetDateTime


总结

目标正确方式
格式化带时区时间用 ZonedDateTime / OffsetDateTime + pattern 含 XXX 或 VV
从 LocalDateTime 加时区先 .atZone(ZoneId) 转为 ZonedDateTime
解析带时区字符串用 OffsetDateTime.parse() + 对应 pattern
public static void main(String[] args) {
        long ts = Instant.now().toEpochMilli();
        System.out.println(ts);

        String result = Instant.ofEpochMilli(ts)
                .atZone(ZoneId.systemDefault())
                .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        System.out.println(result);

        LocalDateTime start = LocalDateTime.of(2025, 1, 1, 0, 0);
        LocalDateTime end = LocalDateTime.now();
        long days = ChronoUnit.DAYS.between(start, end);

        System.out.println(days);

        LocalDateTime now = LocalDateTime.now();
        LocalDateTime tomorrow = now.plusDays(1);
        LocalDateTime oneHourAgo = now.minusHours(1);
        System.out.println(tomorrow);
        System.out.println(oneHourAgo);

        ZonedDateTime now1 = ZonedDateTime.now();
        String format = now1.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss VV"));
        System.out.println(now1);
        System.out.println(format);
    }

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐