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

Java 日期時間處理大全:Date、Calendar 與 Object 核心方法詳解

     編輯:Java 相關知識

日期時間處理是業務開發的高頻需求。本文系統梳理 JDK 1.0 時代的 java.util.Date、Calendar、GregorianCalendar 與根類別 Object 核心方法,並指出其設計缺陷,為後續遷移至 Java 8+ java.time 奠基。

一、Date 類:可變、非執行緒安全、已棄用方法眾多

1. 核心建構子


Date()                          // 當前毫秒時間戳
Date(long millisSinceEpoch)     // 1970-01-01 00:00:00 UTC 起算毫秒數

2. 常用方法(多數已棄用)

方法說明替代方案
getTime()取得毫秒時間戳繼續使用
setTime(long)設定毫秒時間戳繼續使用
getYear()/setYear()年份(1900 起算)Calendar.YEAR 或 LocalDate.getYear()
getMonth()/setMonth()月份(0-11)Calendar.MONTH 或 LocalDate.getMonthValue()
getDate()/setDate()日期(1-31)Calendar.DATE 或 LocalDate.getDayOfMonth()
getDay()星期(0-6)Calendar.DAY_OF_WEEK
getHours()/getMinutes()/getSeconds()時/分/秒Calendar.HOUR_OF_DAY 等
toString()預設格式:dow mon dd hh:mm:ss zzz yyyyDateTimeFormatter

3. 格式化輸出:SimpleDateFormat


Date now = new Date();
// 線程不安全!區域變數使用或 ThreadLocal 複用
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formatted = sdf.format(now);
System.out.println(formatted); // 2024-03-15 14:30:45

警示:SimpleDateFormat 非執行緒安全,併發環境必須每次新建或用 ThreadLocal 包裝。

二、Calendar 抽象類與 GregorianCalendar 實作

1. 取得實例


Calendar cal = Calendar.getInstance(); // 實際回傳 GregorianCalendar
cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.US); // 指定時區/語系

2. 核心操作 API

操作方法範例
設定日期時間set(2024, Calendar.MARCH, 15, 14, 30, 45) 注意:月份 0-based(0=1月)
取得欄位值int year = cal.get(Calendar.YEAR);
加減時間cal.add(Calendar.DAY_OF_MONTH, 7); 一週後
cal.roll(Calendar.MONTH, 1); 月份+1,不進位年份
設定/取得毫秒時間戳cal.setTimeInMillis(ms); / cal.getTimeInMillis()
轉 DateDate d = cal.getTime();
比較cal.before(otherCal), cal.after(otherCal), cal.compareTo(otherCal)

3. 常用欄位常數


YEAR, MONTH (0-11), DATE/DAY_OF_MONTH (1-31),
HOUR (0-11), HOUR_OF_DAY (0-23), MINUTE, SECOND, MILLISECOND,
DAY_OF_WEEK (1=Sun...7=Sat), DAY_OF_YEAR, WEEK_OF_YEAR, AM_PM

4. GregorianCalendar 專屬:閏年判斷


GregorianCalendar gc = new GregorianCalendar();
boolean leap = gc.isLeapYear(2024); // true

三、Object 核心方法:所有類別的共同基因

java.lang.Object 是所有類別的隱性父類,定義了通用協定:

方法預設行為覆寫契約與最佳實踐
toString()ClassName@hashCode必覆寫:返回物件有意義的字串表示,便於除錯/日誌。
範例:"User{id=1, name='Alice'}"
equals(Object)比較記憶體位址(==)覆寫時必同時覆寫 hashCode()。
契約:自反性、對稱性、傳遞性、一致性、非空性。
常用 Objects.equals(a,b) 處理 null。
hashCode()記憶體位址衍生值同樣物件必回傳相同值;equals 相等則 hashCode 必相等。
常用 Objects.hash(fields...) 生成。
clone()淺拷貝(需實作 Cloneable)建議改用複製建構子或序列化拷貝,避免 Cloneable 破壞封裝。
finalize()GC 前調用(已棄用 Java 9)不要使用:執行時間不確定、影響 GC 效能、可能復活物件。
資源清理用 try-with-resources / Cleaner / PhantomReference。
getClass()回傳 Class 物件final,不可覆寫。反射入口。
wait/notify/notifyAll監視器等待/通知需在 synchronized 區塊內呼叫。現代併發優先用 Condition / LockSupport / CompletableFuture。

四、遺留 API 痛點與 Java 8+ 遷移建議

  • 可變性:Date/Calendar 可變 → 併發 Bug 溫床。
    → java.time 全不可變(LocalDateTime, ZonedDateTime, Instant)。
  • 月份 0-based:Calendar.JANUARY = 0 違反直覺。
    → Month.JANUARY = 1。
  • 年份 1900-based:Date.getYear() = 124 代表 2024。
    → LocalDate.getYear() = 2024。
  • 格式化非執行緒安全。
    → DateTimeFormatter 不可變、執行緒安全。
  • 時區處理痛苦。
    → ZoneId, ZonedDateTime 一流支援。

結語

理解 Date/Calendar 歷史包袱,能幫你維護舊代碼並平滑遷移。新專案**直接使用 java.time 套件**,享受不可變、流暢 API、標準 ISO-8601 支援帶來的開發體驗與正確性保障。

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