首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 8 時間 API 完全指南:告別 Date/Calendar,擁抱 LocalDateTime 與 DateTimeFormatter

     編輯:Java 相關知識

歷史包袱:為什麼要棄用 java.util.Date?

  • 線程不安全:SimpleDateFormat 非線程安全,多線程下易拋 NumberFormatException 或產生錯誤日期;
  • 設計缺陷:月份 0-11、年份從 1900 起、可變對象導致防禦性拷貝泛濫;
  • 時區處理痛苦:Date 本質是 UTC 時間戳,顯示時才套用默認時區,極易產生「同一時刻顯示不同日期」的 Bug。

Java 8 三大核心類:Instant、LocalDateTime、ZonedDateTime

類含義適用場景
Instant時間線上的瞬間(UTC 時間戳,納秒精度)日誌時間戳、數據庫存儲、跨系統傳輸
LocalDateTime無時區的日期時間(如 2024-06-15T14:30)業務邏輯、表單綁定、定時任務觸發時間
ZonedDateTime帶時區的日期時間(如 2024-06-15T14:30+08:00[Asia/Shanghai])用戶面向顯示、跨時區業務、國際化系統

常用操作速查表

1. 獲取當前時間

Instant nowInstant = Instant.now();                    // UTC 納秒
LocalDateTime nowLocal = LocalDateTime.now();          // 系統默認時區
ZonedDateTime nowZoned = ZonedDateTime.now();          // 帶時區
ZonedDateTime nyTime = ZonedDateTime.now(ZoneId.of("America/New_York")); // 指定時區

2. 字符串解析與格式化(線程安全!)

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 解析
LocalDateTime parsed = LocalDateTime.parse("2024-06-15 14:30:00", fmt);
// 格式化
String formatted = nowLocal.format(fmt); // "2024-06-15 14:30:00"

最佳實踐:DateTimeFormatter 為不可變對象,可定義為 static final 常量,全局共享,零同步開銷。

3. 日期時間運算(不可變,鏈式調用)

LocalDateTime future = nowLocal.plusYears(1).plusMonths(2).minusDays(3);
LocalDateTime past = nowLocal.minusWeeks(1).withHour(0).withMinute(0).withSecond(0); // 當天零點

4. 互轉:Instant ⇄ LocalDateTime ⇄ ZonedDateTime


// Instant -> LocalDateTime (需指定時區)
LocalDateTime ldt = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();

// LocalDateTime -> Instant (需指定時區)
Instant instant = ldt.atZone(ZoneId.systemDefault()).toInstant();

// LocalDateTime -> ZonedDateTime
ZonedDateTime zdt = ldt.atZone(ZoneId.of("Asia/Shanghai"));

// 時間戳長整型互轉
long epochMilli = instant.toEpochMilli();
Instant fromMilli = Instant.ofEpochMilli(epochMilli);

5. 截取/比較/區間

LocalDate date = ldt.toLocalDate();           // 只要日期部分
LocalTime time = ldt.toLocalTime();           // 只要時間部分
boolean isBefore = ldt1.isBefore(ldt2);       // 比較
Duration gap = Duration.between(ldt1, ldt2);  // 精確間隔(納秒級)
Period period = Period.between(date1, date2); // 日期間隔(年/月/日)

與舊 API 互操作(遷移期必備)


// Date -> Instant
Instant instant = oldDate.toInstant();
// Instant -> Date
Date date = Date.from(instant);

// Calendar -> ZonedDateTime
ZonedDateTime zdt = calendar.toInstant().atZone(calendar.getTimeZone().toZoneId());
// ZonedDateTime -> Calendar
Calendar cal = Calendar.from(zdt);

格式化模式字符對照表

符號含義示例
y年2024
M月06 / Jun / June
d日15
H時(0-23)14
h時(1-12)02
m分30
s秒05
S毫秒123
z時區名CST
X時區偏移+0800 / +08:00

總結:遷移清單

  1. 新代碼全面使用 java.time.*,禁用 java.util.Date、Calendar、SimpleDateFormat;
  2. 數據庫存儲用 Instant(對應 TIMESTAMP WITH TIME ZONE)或 LocalDateTime(對應 TIMESTAMP);
  3. 所有格式化器定義為 static final DateTimeFormatter;
  4. 業務邏輯傳遞 LocalDateTime,跨時區顯示轉 ZonedDateTime;
  5. 遺留系統邊界用 .toInstant() / Date.from() 無縫銜接。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved