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

Android Calendar 月份運算陷阱:set vs add 方法差異

     編輯:程式設計綜合問答

問題現象

使用 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 日。

正確解決方案:使用 add() 方法

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() vs add() 差異對照

方法行為適用場景
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.time (API 26+ / ThreeTenABP)

// 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。

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