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

Java 日期時間處理完全指南:Calendar、DateFormat、時間運算與比較

     編輯:Java 相關知識

前言

Java 日期時間 API 歷經三代演進:Date/Calendar (Java 1.1)、LocalDateTime (Java 8)、Temporal API (Java 8+)。本文聚焦傳統 Calendar 與 SimpleDateFormat 實用技巧,適用於維護舊系統、Android 開發、或尚未遷移至 Java 8 的專案。

核心類別速查

類別套件用途線程安全
Calendarjava.util日期運算、欄位存取否
Datejava.util時間戳記、傳統 API 相容否
SimpleDateFormatjava.text格式化/解析字串否 (每執行緒建立實例)
DateFormatjava.text抽象基類、預設格式取得否

常用操作範例集

1. 取得當前時間


// 方式一:Calendar
Calendar cal = Calendar.getInstance();
Date now = cal.getTime(); // Fri Jan 06 21:03:36 CST 2017

// 方式二:Date 直接取得
Date now2 = new Date();

2. 格式化輸出


DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(fmt.format(new Date()));      // 2017-01-06 21:19:02
System.out.println(fmt.format(cal.getTime()));   // 2017-01-06 23:41:00

// 常用格式模式
// yyyy-MM-dd          -> 2017-01-06
// HH:mm:ss            -> 21:19:02 (24小時制)
// hh:mm:ss a          -> 09:19:02 PM (12小時制)
// E                   -> 週五 (星期)
// z                   -> CST (時區)

3. 取得年、月、日、時、分、秒


Calendar cal = Calendar.getInstance();

// 年
int year = cal.get(Calendar.YEAR);        // 2017

// 月 (0-11,需 +1)
int month = cal.get(Calendar.MONTH) + 1;  // 1

// 日
int day = cal.get(Calendar.DAY_OF_MONTH); // 6

// 時 (24小時制)
int hour = cal.get(Calendar.HOUR_OF_DAY); // 23

// 分
int minute = cal.get(Calendar.MINUTE);    // 41

// 秒
int second = cal.get(Calendar.SECOND);    // 0

// 星期 (1=星期日, 2=星期一, ...)
int week = cal.get(Calendar.DAY_OF_WEEK); // 6 (星期五)

4. 時間加減運算


Calendar cal = Calendar.getInstance();

// 1 小時後
cal.add(Calendar.HOUR_OF_DAY, 1);  // 修改 cal 物件本身
// 或不修改原物件
Calendar later = (Calendar) cal.clone();
later.add(Calendar.HOUR_OF_DAY, 1);

// 6 分鐘前
cal.add(Calendar.MINUTE, -6);

// 取得運算後的格式化字串
String timeStr = fmt.format(cal.getTime()); // 2017-01-06 23:26:39

5. 兩個時間比較


Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal2.add(Calendar.HOUR, 7); // cal2 比 cal1 晚 7 小時

// compareTo: cal1 < cal2 回傳 -1; 相等 0; 大於 1
int cmp = cal1.compareTo(cal2); // -1

6. 計算時間差


Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal2.add(Calendar.HOUR, 7);

// 毫秒差
long diffMs = cal2.getTimeInMillis() - cal1.getTimeInMillis(); // 25200000

// 換算小時
long diffHours = diffMs / (1000 * 60 * 60); // 7

// 更精確:使用 TimeUnit (Java 5+)
long diffHours2 = TimeUnit.MILLISECONDS.toHours(diffMs); // 7
long diffMinutes = TimeUnit.MILLISECONDS.toMinutes(diffMs); // 420

7. 設定特定日期時間


// 方式一:set 方法
Calendar cal = Calendar.getInstance();
cal.set(2024, Calendar.DECEMBER, 25, 12, 30, 0); // 2024-12-25 12:30:00
cal.set(Calendar.MILLISECOND, 0);

// 方式二:SimpleDateFormat 解析
DateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date specific = df.parse("2024/12/25 12:30:00");
cal.setTime(specific);

常見陷阱與最佳實踐

  1. SimpleDateFormat 非線程安全:不可作為 static 共享欄位,請使用 ThreadLocal 或每次新建,或遷移至 Java 8 DateTimeFormatter
  2. 月份 0-based 陷阱:Calendar.JANUARY = 0,顯示時必須 +1
  3. lenient 模式:預設寬鬆模式允許 2024-02-30 自動轉為 2024-03-01,嚴格模式 df.setLenient(false)
  4. 時區問題:跨時區系統務必明確設定 cal.setTimeZone(TimeZone.getTimeZone("UTC"))
  5. mutability:cal.add() 會修改原物件,需注意副作用

Java 8+ 現代化替代方案(強烈建議遷移)


// 當前時間
LocalDateTime now = LocalDateTime.now();

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

// 解析
LocalDateTime parsed = LocalDateTime.parse("2024-12-25 12:30:00", fmt);

// 時間運算 (不可變,鏈式呼叫)
LocalDateTime later = now.plusHours(1).minusMinutes(6);

// 時間差
Duration duration = Duration.between(start, end);
long hours = duration.toHours();

// 時區
ZonedDateTime zdt = now.atZone(ZoneId.of("Asia/Taipei"));

遷移對照表

傳統 APIJava 8+ API優勢
Calendar.getInstance()LocalDateTime.now()不可變、線程安全
cal.get(Calendar.YEAR)ldt.getYear()直接回傳 int、無 0-based
cal.add(HOUR, 1)ldt.plusHours(1)不可變、鏈式、易讀
SimpleDateFormatDateTimeFormatter線程安全、效能更好
cal.getTimeInMillis()Instant.now().toEpochMilli()統一時間戳模型
TimeZoneZoneId / ZoneOffset命名清晰、支援規則變更

總結

Calendar/SimpleDateFormat 是 Java 歷史包袱,但在大量存量程式碼中仍佔主流。掌握其核心用法、陷阱與替代方案,能在維舊專案時游刃有餘。新專案強制使用 Java 8+ java.time 套件,從根源避免線程安全、可變性、時區等經典坑點。

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