Java 8 日期時間 API 核心類概覽
| 類 | 用途 | 特點 |
Instant | 時間戳 | 納秒精度、UTC、機器時間 |
LocalDate | 日期(年月日) | 無時間、無時區、生日/紀念日 |
LocalTime | 時間(時分秒) | 無日期、無時區、鬧鐘時間 |
LocalDateTime | 日期時間 | 無時區、本地日曆 |
ZonedDateTime | 帶時區日期時間 | 完整時區資訊、業務顯示 |
OffsetDateTime | 帶偏移量日期時間 | 固定偏移、數據庫存儲 |
Duration | 時間間隔 | 秒/納秒、機器間隔 |
Period | 日期間隔 | 年/月/日、人類間隔 |
所有類:**不可變、線程安全、基於 ISO-8601 日曆系統**。
20 大實戰範例
1. 獲取當前日期
LocalDate today = LocalDate.now();
System.out.println(today); // 2024-01-15
2. 解析日期組件
int year = today.getYear();
int month = today.getMonthValue(); // 1-12
int day = today.getDayOfMonth();
DayOfWeek dow = today.getDayOfWeek(); // MONDAY...
3. 構建指定日期
LocalDate birthday = LocalDate.of(2000, 5, 20); // 2000-05-20
// 無月份 0 基索引陷阱,直觀易用
4. 日期比較
if (today.equals(birthday)) System.out.println("生日快樂!");
if (today.isAfter(birthday)) System.out.println("生日已過");
if (today.isBefore(birthday)) System.out.println("生日未到");
5. 週期性事件檢查(MonthDay)
MonthDay birthdayMd = MonthDay.from(birthday);
MonthDay todayMd = MonthDay.from(today);
if (todayMd.equals(birthdayMd)) System.out.println("生日快樂!");
// 忽略年份,適用於周年紀念、節假日
6. 獲取當前時間
LocalTime now = LocalTime.now(); // 14:30:45.123456789
int hour = now.getHour();
int minute = now.getMinute();
7. 時間加減(plus/minus)
LocalTime later = now.plusHours(2).plusMinutes(30);
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
LocalDate nextMonth = today.plusMonths(1);
LocalDate nextYear = today.plusYears(1);
8. 日期加減
LocalDate lastYear = today.minusYears(1);
LocalDate nextYear = today.plusYears(1);
9. Clock 時鐘抽象(測試友好)
Clock utcClock = Clock.systemUTC();
Clock defaultClock = Clock.systemDefaultZone();
Clock fixedClock = Clock.fixed(Instant.parse("2024-01-01T00:00:00Z"), ZoneId.of("UTC"));
// 注入測試
public class Scheduler {
private final Clock clock;
public Scheduler(Clock clock) { this.clock = clock; }
public boolean isDue(LocalDate deadline) {
return !LocalDate.now(clock).isBefore(deadline);
}
}
10. 時區轉換
ZoneId ny = ZoneId.of("America/New_York");
LocalDateTime local = LocalDateTime.now();
ZonedDateTime nyTime = local.atZone(ny); // 當地時間視為紐約時間
ZonedDateTime utcTime = nyTime.withZoneSameInstant(ZoneOffset.UTC); // 轉 UTC
11. 固定日期模式(YearMonth)
YearMonth ym = YearMonth.now();
int days = ym.lengthOfMonth(); // 當月天數,自動處理閏年
YearMonth expiry = YearMonth.of(2025, 12); // 信用卡過期
12. 閏年判斷
if (today.isLeapYear()) System.out.println("閏年");
13. 兩日期間隔(Period)
LocalDate release = LocalDate.of(2024, 3, 15);
Period p = Period.between(today, release);
System.out.println(p.getMonths() + "月" + p.getDays() + "天");
14. 偏移量日期時間
OffsetDateTime odt = OffsetDateTime.of(
LocalDateTime.of(2024, 1, 15, 10, 30),
ZoneOffset.of("+08:00")
);
15. Instant 時間戳
Instant now = Instant.now(); // 2024-01-15T02:30:45.123Z
// 舊 API 互轉
Date date = Date.from(now);
Instant ins = date.toInstant();
16. 預定義格式化解析
String iso = "20240115";
LocalDate parsed = LocalDate.parse(iso, DateTimeFormatter.BASIC_ISO_DATE);
// 2024-01-15
17. 自定義格式化解析
String custom = "Apr 18 2024";
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MMM dd yyyy", Locale.ENGLISH);
LocalDate holiday = LocalDate.parse(custom, fmt);
18. 日期時間格式化輸出
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MMM dd yyyy hh:mm a");
String formatted = now.format(fmt); // Jan 15 2024 10:30 AM
19. 時區格式化
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Asia/Taipei"));
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
System.out.println(zdt.format(fmt)); // 2024-01-15 10:30:45 CST
20. 練習:下一個工作日計算
public LocalDate nextBusinessDay(LocalDate date) {
LocalDate next = date.plusDays(1);
while (next.getDayOfWeek() == DayOfWeek.SATURDAY
|| next.getDayOfWeek() == DayOfWeek.SUNDAY) {
next = next.plusDays(1);
}
// 可擴展:排除節假日表
return next;
}
關鍵差異速查
| 場景 | 推薦類 | 避免 |
| 生日/入職日 | LocalDate | Date/Calendar |
| 鬧鐘/營業時間 | LocalTime | Date |
| 本地日程 | LocalDateTime | Timestamp |
| 國際會議/航班 | ZonedDateTime | Calendar |
| 數據庫 TIMESTAMP | OffsetDateTime | Date |
| 計算間隔 | Period/Duration | 毫秒相減 |
避坑指南
Month enum 從 1 開始(JANUARY=1),無 0 基陷阱
DayOfWeek enum:MONDAY=1 ... SUNDAY=7
- 格式化模式:
MM 月份,mm 分鐘;HH 24制,hh 12制
yyyy 年份,YYYY 週年(慎用)
- 解析失敗拋
DateTimeParseException,格式化失敗拋 DateTimeException
- 線程安全:
DateTimeFormatter 可靜態共享,SimpleDateFormat 不可