方法定义与功能说明
1. minusDays(long daysToSubtract)
public LocalDate minusDays(long daysToSubtract)
- 功能:从当前日期减去指定天数。
- 参数:
daysToSubtract
- 要减去的天数(可为负数,负数相当于加法)。 - 返回值:新的
LocalDate
实例。 - 异常:
DateTimeException
(如果结果超出支持的日期范围)。
2. minusWeeks(long weeksToSubtract)
public LocalDate minusWeeks(long weeksToSubtract)
- 功能:从当前日期减去指定周数(1 周 = 7 天)。
- 参数:
weeksToSubtract
- 要减去的周数。 - 等价操作:
minusDays(weeksToSubtract * 7)
3. minusMonths(long monthsToSubtract)
public LocalDate minusMonths(long monthsToSubtract)
- 功能:从当前日期减去指定月数。
- 智能处理:自动处理不同月份天数差异和闰年。
- 示例:
2025-03-31.minusMonths(1)
→2025-02-28
(自动调整到2月最后一天)
4. minusYears(long yearsToSubtract)
public LocalDate minusYears(long yearsToSubtract)
- 功能:从当前日期减去指定年数。
- 智能处理:自动处理闰年2月29日问题。
- 示例:
2024-02-29.minusYears(1)
→2023-02-28
(非闰年,调整为28日)
三、详细示例代码
import java.time.LocalDate;
public class LocalDateMinusExample {
public static void main(String[] args) {
LocalDate today = LocalDate.of(2025, 8, 16);
System.out.println("今天: " + today);
// === minusDays ===
LocalDate sevenDaysAgo = today.minusDays(7);
System.out.println("7天前: " + sevenDaysAgo); // 2025-08-09
LocalDate tomorrow = today.minusDays(-1); // 负数 = 加法
System.out.println("明天: " + tomorrow); // 2025-08-17
// === minusWeeks ===
LocalDate oneWeekAgo = today.minusWeeks(1);
System.out.println("1周前: " + oneWeekAgo); // 2025-08-09
LocalDate fourWeeksAgo = today.minusWeeks(4);
System.out.println("4周前: " + fourWeeksAgo); // 2025-07-19
// === minusMonths ===
LocalDate oneMonthAgo = today.minusMonths(1);
System.out.println("1月前: " + oneMonthAgo); // 2025-07-16
LocalDate threeMonthsAgo = today.minusMonths(3);
System.out.println("3月前: " + threeMonthsAgo); // 2025-05-16
// 特殊情况:月末处理
LocalDate endOfMonth = LocalDate.of(2025, 3, 31);
LocalDate febEnd = endOfMonth.minusMonths(1);
System.out.println("3月31日减1月: " + febEnd); // 2025-02-28
// === minusYears ===
LocalDate oneYearAgo = today.minusYears(1);
System.out.println("1年前: " + oneYearAgo); // 2024-08-16
LocalDate tenYearsAgo = today.minusYears(10);
System.out.println("10年前: " + tenYearsAgo); // 2015-08-16
// 闰年处理
LocalDate leapDay = LocalDate.of(2024, 2, 29);
LocalDate nonLeapDay = leapDay.minusYears(1);
System.out.println("2024-02-29 减1年: " + nonLeapDay); // 2023-02-28
}
}
四、链式调用(Chaining)
minus*
方法支持链式调用,非常适合构建复杂的时间运算:
LocalDate complexDate = today
.minusYears(2) // 2年前
.minusMonths(3) // 再减3个月
.minusWeeks(1) // 再减1周
.minusDays(5); // 再减5天
System.out.println("复杂计算结果: " + complexDate);
// 等价于: today.minusDays(2*365 + 3*30 + 7 + 5) 的近似值
五、常见错误
❌ 错误 1:误以为修改了原对象
LocalDate date = LocalDate.of(2025, 8, 16);
date.minusDays(1); // ❌ 错误!没有接收返回值
System.out.println(date); // 仍然是 2025-08-16
// 正确做法:
LocalDate yesterday = date.minusDays(1);
System.out.println(yesterday); // 2025-08-15
❌ 错误 2:忽略月末/闰年处理
// 期望 2025-02-31?不存在!
LocalDate invalid = LocalDate.of(2025, 3, 31).minusMonths(1);
// 实际结果: 2025-02-28(自动调整)
❌ 错误 3:超出日期范围
// 可能抛出 DateTimeException
// LocalDate ancient = LocalDate.MIN.minusDays(1);
六、注意事项
- 不可变性:必须接收返回值,原对象不会改变。
- 智能调整:
minusMonths/minusYears
会自动调整到有效日期(如 3月31日 → 2月28日)。- 不会抛出异常,而是进行合理调整。
- 负数参数:相当于加法操作(
minusDays(-5)
=plusDays(5)
)。 - 大数值:支持
long
类型,但需注意结果是否超出LocalDate
范围(约 ±100万年)。 - 线程安全:
LocalDate
是不可变对象,线程安全。
七、使用技巧
✅ 技巧 1:封装常用时间偏移
public class DateUtils {
public static LocalDate daysAgo(int days) {
return LocalDate.now().minusDays(days);
}
public static LocalDate weeksAgo(int weeks) {
return LocalDate.now().minusWeeks(weeks);
}
}
// 使用
LocalDate lastWeek = DateUtils.daysAgo(7);
LocalDate lastMonth = DateUtils.daysAgo(30); // 近似
✅ 技巧 2:计算时间间隔
LocalDate startDate = LocalDate.of(2025, 1, 1);
LocalDate today = LocalDate.now();
// 计算距离年初已过去多少天
long daysPassed = today.toEpochDay() - startDate.toEpochDay();
System.out.println("今年已过去 " + daysPassed + " 天");
✅ 技巧 3:结合 isBefore
/isAfter
使用
LocalDate thirtyDaysAgo = LocalDate.now().minusDays(30);
if (someDate.isBefore(thirtyDaysAgo)) {
System.out.println("超过30天了");
}
八、最佳实践与性能优化
✅ 最佳实践 1:优先使用语义化方法
// 推荐:语义清晰
date.minusWeeks(2)
// 不推荐:可读性差
date.minusDays(14)
✅ 最佳实践 2:避免连续大量调用
// 对于大偏移量,直接计算更高效
LocalDate veryOld = LocalDate.of(1900, 1, 1);
// ❌ 低效
// for (int i = 0; i < 10000; i++) {
// veryOld = veryOld.minusDays(1);
// }
// ✅ 高效
LocalDate result = veryOld.minusDays(10000);
✅ 性能说明
minus*
方法都是 O(1) 时间复杂度,性能极高。- 内部计算优化良好,无需担心性能问题。
- 在高并发场景下,由于
LocalDate
不可变,天然线程安全。
九、总结对比
方法 | 单位 | 智能调整 | 典型用途 |
---|---|---|---|
minusDays() |
天 | 否 | 精确天数计算 |
minusWeeks() |
周(7天) | 否 | 周报、周期计算 |
minusMonths() |
月 | ✅ 是 | 月度报表、账单周期 |
minusYears() |
年 | ✅ 是 | 年龄计算、年度对比 |