在 Java 8 之前,java.util.Calendar 是處理日期時間的主力類。本文詳細說明如何利用 Calendar 計算兩個日期之間的天數與週數,並指出毫秒轉換的陷阱與現代替代方案。
Calendar.getTimeInMillis() 取得自 1970-01-01 00:00:00 UTC 的毫秒數,兩日期相減得差值,再換算:
long diffMs = endMs - startMs; long days = diffMs / (1000 * 60 * 60 * 24); // 毫秒 → 天
import java.util.Calendar;
import java.util.Date;
import org.apache.commons.lang3.StringUtils;
/** 計算天數差 */
public Integer countDays(Date start, Date end) {
if (start == null || end == null) return null;
Calendar cal = Calendar.getInstance();
cal.setTime(start);
long startMs = cal.getTimeInMillis();
cal.setTime(end);
long endMs = cal.getTimeInMillis();
long days = (endMs - startMs) / (1000 * 60 * 60 * 24);
return (int) days;
}
/** 計算週數(不足一週按一週、餘數進位) */
public Integer countWeeks(Date start, Date end) {
Integer days = countDays(start, end);
if (days == null) return null;
if (days <= 0) return 0;
if (days <= 7) return 1;
int fullWeeks = days / 7;
int remainder = days % 7;
return remainder > 0 ? fullWeeks + 1 : fullWeeks;
}
Calendar.getInstance() 預設使用 JVM 時區,跨天邊界(如夏令時切換)可能導致 ±1 天誤差。建議明確設定 cal.setTimeZone(TimeZone.getTimeZone("UTC"))。java.time 套件。import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public long daysBetween(LocalDate start, LocalDate end) {
return ChronoUnit.DAYS.between(start, end); // 自動處理時區、夏令時
}
public long weeksBetween(LocalDate start, LocalDate end) {
long days = daysBetween(start, end);
return (days + 6) / 7; // 向上取整
}
Calendar 以毫秒差換算天數/週數邏輯直觀,但需自行處理時區、夏令時、自然日邊界等細節。新專案請直接使用 java.time.LocalDate + ChronoUnit,語意清晰且線程安全。維護舊代碼時,記得加上 UTC 時區與歸零處理,降低誤差風險。