431. Java 日期时间 API - 时间工具 TemporalAdjuster 详解

431. Java 日期时间 API - 时间工具 TemporalAdjuster 详解

大家好,今天我们来聊聊 TemporalAdjuster —— 它是 Java 8 时间 API 中一个很有意思的接口。简单来说,它就是一个 日期调节器,帮我们把一个日期“调整”为另一个日期。

比如:

  • 算出下个月的第一天
  • 找到这个月的最后一个星期五
  • 自动算工资发放日(如果是周末就提前到周五)

是不是很实用?😉


1. 什么是 TemporalAdjuster?

  • 所在包:java.time.temporal
  • 定义:接收一个 Temporal 对象(比如 LocalDate、ZonedDateTime),然后返回一个“调整过”的新日期
  • 特点:
    • 不会修改原始日期(不可变对象)
    • 可以用在 with() 方法里直接调用

👉 类似于给时间对象装上一个“智能计算器”。


2. 预定义的 Adjusters

Java 已经帮我们准备了很多常见的日期调整器,放在 TemporalAdjusters 工具类里。
常见的有:

  • firstDayOfMonth() → 本月第一天
  • lastDayOfMonth() → 本月最后一天
  • firstInMonth(DayOfWeek.MONDAY) → 本月第一个星期一
  • firstDayOfNextYear() → 下一年的第一天

示例代码:

import java.time.*;
import java.time.temporal.*;

public class AdjusterDemo {
    public static void main(String[] args) {
        LocalDate date = LocalDate.of(2000, Month.OCTOBER, 15);
        System.out.printf("%s 是星期 %s%n", date, date.getDayOfWeek());

        System.out.println("本月第一天: " + date.with(TemporalAdjusters.firstDayOfMonth()));
        System.out.println("本月第一个星期一: " + date.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)));
        System.out.println("本月最后一天: " + date.with(TemporalAdjusters.lastDayOfMonth()));
        System.out.println("下个月第一天: " + date.with(TemporalAdjusters.firstDayOfNextMonth()));
        System.out.println("下一年第一天: " + date.with(TemporalAdjusters.firstDayOfNextYear()));
    }
}

输出结果:

2000-10-15 是星期 SUNDAY
本月第一天: 2000-10-01
本月第一个星期一: 2000-10-02
本月最后一天: 2000-10-31
下个月第一天: 2000-11-01
下一年第一天: 2001-01-01

👉 看出来了吗?只要一个 with() 就能搞定常见的日期运算,比手写逻辑要简洁很多。


3. 自定义 Adjuster —— 工资日案例 💰

有些规则比较复杂,比如:

  • 工资日定在 每月 15 号月底
  • 如果碰到周末,提前到星期五

这种情况就要写一个 自定义 Adjuster 了。

实现代码:

import java.time.*;
import java.time.temporal.*;

public class PaydayAdjuster implements TemporalAdjuster {
    @Override
    public Temporal adjustInto(Temporal input) {
        LocalDate date = LocalDate.from(input);
        int day;

        // 如果今天还没到 15 号,那下一个发薪日就是 15 号
        if (date.getDayOfMonth() < 15) {
            day = 15;
        } else { // 否则就是月底
            day = date.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
        }

        date = date.withDayOfMonth(day);

        // 如果发薪日是周六或周日,提前到周五
        if (date.getDayOfWeek() == DayOfWeek.SATURDAY ||
            date.getDayOfWeek() == DayOfWeek.SUNDAY) {
            date = date.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));
        }

        return date;
    }
}

使用方式:

public class PaydayTest {
    public static void main(String[] args) {
        LocalDate d1 = LocalDate.of(2013, 6, 3);
        LocalDate d2 = LocalDate.of(2013, 6, 18);

        LocalDate nextPayday1 = d1.with(new PaydayAdjuster());
        LocalDate nextPayday2 = d2.with(new PaydayAdjuster());

        System.out.println("日期: " + d1 + " → 下个发薪日: " + nextPayday1);
        System.out.println("日期: " + d2 + " → 下个发薪日: " + nextPayday2);
    }
}

输出结果:

日期: 2013-06-03 → 下个发薪日: 2013-06-14
日期: 2013-06-18 → 下个发薪日: 2013-06-28

👉 我们看到,6 月 15 和 30 号都刚好是周末,自动提前到了周五,非常智能!🎯


4. 总结 🎓

  • TemporalAdjuster = 日期调节器
  • TemporalAdjusters = 官方预设的工具箱(第一天、最后一天、下个月…)
  • 自定义 Adjuster 可以解决企业级的复杂需求(例如工资日、报表日、结算日等)
  • 使用方式统一:date.with(adjuster),保持代码简洁。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容