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

Java 8 日期時間 API 完全指南:LocalDate、LocalTime、DateTimeFormatter 與時區處理

     編輯:Java 相關知識

為什麼要新 API?

  • java.util.Date:月份 0-based、非線程安全、可變、設計混亂 (既有日期又有時間)。
  • java.time (JSR-310):不可變、線程安全、領域模型清晰 (LocalDate/Time/DateTime/ZonedDateTime/Instant/Duration/Period)。

核心類速覽

類含義典型用途
LocalDate只有日期 (年月日)生日、合約生效日
LocalTime只有時間 (時分秒納秒)鬧鐘、營業時間
LocalDateTime日期+時間 (無時區)本地會議時間、日誌時間戳
ZonedDateTime日期+時間+時區跨國航班、國際會議
Instant時間線上的瞬間 (UTC)系統事件、資料庫 TIMESTAMP
Duration時間量 (秒/納秒)代碼執行耗時、倒計時
Period日期量 (年/月/日)年齡、訂閱週期

創建與格式化

// 創建
LocalDate today = LocalDate.now();
LocalDate christmas = LocalDate.of(2024, 12, 25);
LocalDate parsed = LocalDate.parse("2024-12-25"); // ISO 格式

LocalTime now = LocalTime.now();
LocalTime noon = LocalTime.of(12, 0);
LocalTime parsedT = LocalTime.parse("12:00:00.123");

LocalDateTime dt = LocalDateTime.now();
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Asia/Taipei"));

// 格式化 (線程安全)
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String str = dt.format(fmt);
LocalDateTime back = LocalDateTime.parse(str, fmt);

強大的時間運算 (TemporalAdjusters)

// 本月第一天/最後一天
LocalDate first = today.with(TemporalAdjusters.firstDayOfMonth());
LocalDate last = today.with(TemporalAdjusters.lastDayOfMonth());

// 下一個周五
LocalDate nextFri = today.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));

// 今年第一個周一
LocalDate firstMon = LocalDate.of(2024, 1, 1).with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));

// 加減
LocalDate tomorrow = today.plusDays(1);
LocalDateTime in2Hours = LocalDateTime.now().plusHours(2);
Period age = Period.between(LocalDate.of(1990, 5, 1), today);
Duration elapsed = Duration.between(Instant.now(), Instant.now().plusSeconds(3600));

與資料庫交互 (JDBC 4.2+)

// 寫入
PreparedStatement ps = conn.prepareStatement("INSERT INTO events (event_time) VALUES (?)");
ps.setObject(1, LocalDateTime.now()); // 自動映射到 TIMESTAMP

// 讀取
ResultSet rs = stmt.executeQuery("SELECT event_time FROM events");
if (rs.next()) {
    LocalDateTime ldt = rs.getObject(1, LocalDateTime.class); // 直接獲取對象
}

時區處理最佳實踐

  • 系統內部統一用 Instant (UTC) 或 ZonedDateTime 傳遞存儲。
  • 展示層根據用戶時區轉換:zdt.withZoneSameInstant(userZoneId)。
  • 資料庫儲存建議用 TIMESTAMP WITH TIME ZONE (PostgreSQL) 或統一存 UTC DATETIME (MySQL) + 應用層處理時區。

避坑指南

  • LocalDateTime 不帶時區,不可直接跨時區比較,需先 .atZone(zoneId) 轉為 ZonedDateTime。
  • Period 處理年月日,Duration 處理時分秒,**不可混用**。
  • DateTimeFormatter 為不可變且線程安全,可定義為 static final 常量。
  • 序列化建議用 ISO-8601 字串 (Instant.toString()) 或長整數毫秒數,避免時區歧義。

結語

Java 8 時間 API 以「不可變、領域驅動、線程安全」三大特性徹底解決舊 API 痛點。掌握 LocalDate/Time/DateTime 三兄弟與 TemporalAdjusters、DateTimeFormatter、ZoneId 即可應對 95% 以上業務場景。新專案**強制禁用** java.util.Date 與 Calendar。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved