localdate.with(temporaladjusters.firstdayofmonth())可直接获取当月第一天,无需手动计算年月或处理闰年、大小月;它仅将日设为1,保持原年份和月份不变。

直接调用 LocalDate.with(TemporalAdjusters.firstDayOfMonth()) 就能获取当月的第一天,无需手动计算年月,也无需担心闰年或大小月问题。
理解 firstDayOfMonth() 的作用
这个调整器(TemporalAdjuster)的作用是将任意一个 LocalDate “对齐”到它所在月份的第一天,保持年份和月份不变,只把日设为 1。
它不改变原始日期的年份和月份,只重置“日”字段。例如:
LocalDate.of(2024, 3, 15).with(firstDayOfMonth()) → 2024-03-01LocalDate.of(2023, 12, 31).with(firstDayOfMonth()) → 2023-12-01LocalDate.now().with(firstDayOfMonth()) → 今天所在月的 1 号
正确引入和使用 TemporalAdjusters
需要静态导入或显式引用 java.time.temporal.TemporalAdjusters 类:
- 推荐方式(静态导入):import static java.time.temporal.TemporalAdjusters.firstDayOfMonth;
- 使用时直接写:
date.with(firstDayOfMonth()) - 不导入时写全名:
date.with(TemporalAdjusters.firstDayOfMonth())
注意:不是 TemporalAdjuster(单数接口),而是 TemporalAdjusters(工具类,含多个静态工厂方法)。
常见实用场景
该方法常用于报表周期、账单起始日、数据归档等需要按自然月对齐的业务逻辑中:
- 获取本月第一天:
LocalDate firstDay = LocalDate.now().with(firstDayOfMonth()); - 获取上个月第一天:
LocalDate lastMonthFirst = LocalDate.now().minusMonths(1).with(firstDayOfMonth()); - 结合 Period 计算当月天数:
long daysInMonth = ChronoUnit.DAYS.between(firstDay, firstDay.plusMonths(1));
注意事项
该方法安全可靠,但需注意几点:
- 输入必须是非 null 的
LocalDate,否则抛NullPointerException - 它不会做任何时区处理(
LocalDate本就不含时区) - 如果想获取“本月最后一天”,对应的是
lastDayOfMonth(),不是反向推算 - 不要与
firstDayOfNextMonth()混淆——Java 8+ 不提供该方法,需用plusMonths(1).with(firstDayOfMonth())
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











