使用 Calendar.set(Calendar.MONTH, 1) 嘗試將日期設為 2 月,結果卻跳到 3 月 3 日。
Calendar cal = Calendar.getInstance();
System.out.println("Before " + cal.getTime());
// Before Thu Jan 31 10:07:34 IST 2013
cal.set(Calendar.MONTH, 1); // 嘗試設為 2 月(注意:Calendar 月份 0-11)
System.out.println("After " + cal.getTime());
// After Sun Mar 03 10:07:34 IST 2013 <-- 錯誤!預期 2 月
Calendar.set(field, value) 是直接設定該欄位,不會自動調整其他欄位。當前日期為 1 月 31 日,直接將月份設為 1(2 月),但 2 月只有 28/29 日,系統會自動向後推算多出的天數:31 - 28 = 3 天 → 3 月 3 日。
Calendar cal = Calendar.getInstance();
System.out.println("Before " + cal.getTime());
// Before Thu Jan 31 10:16:23 IST 2013
cal.add(Calendar.MONTH, 1); // 增加 1 個月,會自動處理月末邊界
System.out.println("After " + cal.getTime());
// After Thu Feb 28 10:16:23 IST 2013 <-- 正確!自動調整至 2 月最後一天
| 方法 | 行為 | 適用場景 |
|---|---|---|
set(field, value) | 直接覆寫指定欄位,不調整其他欄位 | 設定固定日期(如生日:年/月/日全知) |
add(field, amount) | 增加/減少指定欄位,自動進位調整相關欄位 | 日期運算(如:一個月後、一週前、100天後) |
roll(field, amount) | 增加/減少指定欄位,不調整較大單位欄位 | 特殊需求(如:月份循環 12→1 不改年份) |
// 需求:將任意日期安全設為同年的 2 月第一天
Calendar cal = Calendar.getInstance();
cal.set(Calendar.MONTH, Calendar.FEBRUARY); // 設為 2 月
cal.set(Calendar.DAY_OF_MONTH, 1); // 設為 1 號,避免月末溢位
// 結果:同年 2 月 1 日 00:00:00
// Java 8+ / Android API 26+
LocalDate date = LocalDate.now(); // 2024-01-31
LocalDate nextMonth = date.plusMonths(1); // 2024-02-29 (閏年自動處理)
LocalDate firstDayFeb = date.withMonth(2).withDayOfMonth(1); // 2024-02-01
日期運算請使用 add() 而非 set()。set() 適用於已知完整年月日時的直接設定;add() 會智慧處理月份天數差異、閏年等邊界條件。現代專案建議遷移至 java.time 套件獲得更清晰、安全的 API。