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

Java 日期時間互轉完全手冊:Date、Calendar、LocalDateTime、格式化與實戰題

     編輯:Java 綜合教學

Java 日期時間互轉完全手冊:Date、Calendar、LocalDateTime、格式化與實戰題

日期處理是業務開發高頻場景,但 Date、Calendar、SimpleDateFormat、LocalDateTime 混用極易出 Bug。本文梳理核心類轉換鏈路、線程安全陷阱、Java 8 新 API 最佳實踐,並附一道高頻面試題實戰解析。

核心類轉換關係圖

┌─────────────┐     getTime()/ctor      ┌────────┐
│   java.util.Date  ◄──────────────────►  │  long  │  (毫秒時間戳)
└──────┬──────┘                           └────────┘
       │ setTime()/getTime()
       ▼
┌──────────────────┐
│ java.util.Calendar │  (欄位運算、時區感知)
└────────┬─────────┘
       │ getTime()
       ▼
┌──────────────────┐
│   java.util.Date  │
└────────┬─────────┘
       │ SimpleDateFormat.format/parse
       ▼
┌──────────────────┐
│    String        │  (業務展示/存儲/傳輸)
└──────────────────┘

經典舊 API 互轉代碼模板

1. Date ⇄ long (時間戳)

// Date → long
Date date = new Date();
long ts = date.getTime();

// long → Date
long now = System.currentTimeMillis();
Date date2 = new Date(now);

2. Date ⇄ String (格式化/解析)

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

// Date → String
String str = sdf.format(new Date());

// String → Date (拋 ParseException)
Date parsed = sdf.parse("2024-06-15 14:30:00.123");

⚠ 線程安全大坑:SimpleDateFormat 非線程安全,不可作為 static 字段共享。正確做法:
① 局部變量每次 new
② ThreadLocal 緩存
③ Java 8+ 用 DateTimeFormatter (不可變、線程安全)

3. Date ⇄ Calendar (欄位運算)

// Date → Calendar
Calendar cal = Calendar.getInstance();
cal.setTime(date);

// Calendar → Date
Date date3 = cal.getTime();

// 日期運算範例:+3 天 / -1 月
cal.add(Calendar.DATE, 3);
cal.add(Calendar.MONTH, -1);

Java 8+ 新時間 API (java.time) —— 推薦生產首選

類用途關鍵特性
LocalDate純日期 (年月日)無時區、不可變
LocalTime純時間 (時分秒)無時區、不可變
LocalDateTime日期時間無時區、不可變
ZonedDateTime帶時區日期時間時區感知、夏令時自動處理
Instant時間戳 (納秒精度)機器時間、可與 Date 互轉
DateTimeFormatter格式化/解析線程安全、預定義格式豐富

新舊 API 無縫互轉

// Date → Instant → LocalDateTime (系統默認時區)
LocalDateTime ldt = date.toInstant()
                       .atZone(ZoneId.systemDefault())
                       .toLocalDateTime();

// LocalDateTime → Date
Date newDate = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());

// 格式化
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String str = ldt.format(fmt);
LocalDateTime parsed = LocalDateTime.parse(str, fmt);

面試高頻題:日期加 3 天並格式化輸出

/**
 * 參數:Date date
 * 返回:date 往後推 3 天,格式 "yyyy-MM-dd"
 */
public String add3Days(Date date) {
    // 1. 校驗空指針
    if (date == null) return null;

    // 2. 推薦:Java 8 一行流
    return date.toInstant()
               .atZone(ZoneId.systemDefault())
               .toLocalDate()
               .plusDays(3)
               .format(DateTimeFormatter.ISO_LOCAL_DATE);

    // 3. 兼容舊項目:Calendar 版
    /*
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    cal.add(Calendar.DATE, 3);
    return new SimpleDateFormat("yyyy-MM-dd").format(cal.getTime());
    */
}

避坑檢查清單

  • ✅ SimpleDateFormat 不作 static 字段,改用 DateTimeFormatter 或 ThreadLocal
  • ✅ 跨時區業務強制用 ZonedDateTime / Instant,禁用 Date
  • ✅ 數據庫存儲統一用 UTC TIMESTAMP / BIGINT(毫秒),應用層按用戶時區展示
  • ✅ 序列化傳輸優先用 ISO-8601 字符串 (2024-06-15T14:30:00Z) 而非時間戳
  • ✅ 定時任務 cron 表達式時區顯式聲明,避免夏令時導致跑偏

一言蔽之:新項目直接上 java.time 全家桶;維舊項目邊緣封裝工具類隔離 SimpleDateFormat,逐步替換。日期處理沒有銀彈,只有規範與測試。

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