不灭的焱

革命尚未成功,同志仍须努力下载JDK17

作者:Albert.Wen  添加时间:2023-04-09 08:47:58  修改时间:2024-05-02 14:00:48  分类:Java基础  编辑

文章目录

前言

TemporalAdjuster是Java 8引入的新的处理日期和时间API的一部分。

TemporalAdjuster是时间调节器,可以执行复杂的日期操作,例如,可以获得下一个星期日的日期、当月的最后一天(再也不用计算当月是28,29还是30天了)、下一年的第一天、下一个工作日等等。

一. TemporalAdjuster概述

TemporalAdjuster类是一个函数式接口,是Java 8引入的新的处理日期和时间API的一部分。在TemporalAdjusters类中有许多预定义的实现。

该接口有一个名为adjustInto()的抽象方法,可以通过向其传递Temporal对象在其任何实现中调用它。

TemporalAdjuster允许我们执行复杂的日期操作。比如,获得下个星期日,当月的最后一天或下一年的第一天的日期。

  • 包目录:java.time.temporal
  • 类型:函数式接口 public interface TemporalAdjuster
  • 版本:java8引入

TemporalAdjuster是一种调整Temporal对象的策略,在开始使用TemporalAdjuster之前,让我们先看一下Temporal接口。

二. Temporal 接口

Temporal接口是对时间(Temporal)对象的读写访问的框架级接口。比如日期,时间,偏移或这些的某种组合。

Temporal接口是日期,时间和偏移对象的基本接口类型,定义了对日期的增减操作。

Temporal接口有很多实现,包括:

LocalDate - 表示没有时区的日期
LocalDateTime - 表示没有时区的日期和时间
JapaneseDate - 代表日本日历系统中的日期

三. TemporalAdjusters类中预定义实现

TemporalAdjusters工具类有很多预定义的static方法返回TemporalAdjuster对象,使用不同方式调节Temporal对象而与Temporal实现无关。

方法 说明
static TemporalAdjuster firstDayOfMonth() 当前月的第一天
static TemporalAdjuster firstDayOfNextMonth() 下一个月的第一天
static TemporalAdjuster firstDayOfNextYear() 下一年的第一天
static TemporalAdjuster firstDayOfYear() 当年的第一天
static TemporalAdjuster lastDayOfYear() 当年的最后一天
static TemporalAdjuster lastDayOfMonth() 当月的最后一天
static TemporalAdjuster firstInMonth(DayOfWeek dayOfWeek) 某月的第一个星期几
static TemporalAdjuster lastInMonth(DayOfWeek dayOfWeek) 某月的最后一个星期几
static TemporalAdjuster dayOfWeekInMonth(int ordinal, DayOfWeek dayOfWeek) 某月的第几个星期几,例如,三月中第二个星期二
static TemporalAdjuster next(DayOfWeek dayOfWeek) (往后不包括当天)下一个星期几是几月几号。若当前为周三,那么next(DayOfWeek.WEDNESDAY)指下一个周三即下周三;next(DayOfWeek.SUNDAY) 指下一个周日即本周日(此时并不是下周日)
static TemporalAdjuster nextOrSame(DayOfWeek dayOfWeek) (往后包括当天)最近星期几的日期。如最近星期五的日期,如果今天是星期五,则返回今天日期,如果今天不是星期五,则返回下周五的日期
static TemporalAdjuster previous(DayOfWeek dayOfWeek) (往前不包括当天)上一个星期几是几月几号。若当前为周三,那么previous(DayOfWeek.WEDNESDAY)指上一个周三即上周三;previous(DayOfWeek.TUESDAY) 指上一个周二即昨天(此时并不是上周二)
static TemporalAdjuster previousOrSame(DayOfWeek dayOfWeek) (往前包括当天)最近星期几的日期。如最近星期五的日期,如果今天是星期五,则返回今天日期,如果今天不是星期五,则返回上周五的日期

示例:

LocalDate now = LocalDate.now();
System.out.println("当前时间:"+now); //2021-11-30

//获取当月第一天
System.out.println("当月第一天:"+now.with(TemporalAdjusters.firstDayOfMonth()));// 2021-11-01
//获取本月第2天:
System.out.println("本月第2天:"+now.withDayOfMonth(2)); //2021-11-02
//获取下月第一天
System.out.println("下月第一天:"+now.with(TemporalAdjusters.firstDayOfNextMonth())); //2021-12-01
//获取明年第一天
System.out.println("明年第一天:"+now.with(TemporalAdjusters.firstDayOfNextYear())); //2022-01-01
//获取本年第一天
System.out.println("本年第一天:"+now.with(TemporalAdjusters.firstDayOfYear()));//2021-01-01
//获取当月最后一天,再也不用计算是28,29,30还是31:
System.out.println("当月最后一天:"+now.with(TemporalAdjusters.lastDayOfMonth())); //2021-11-30
//获取本年最后一天
System.out.println("本年最后一天:"+now.with(TemporalAdjusters.lastDayOfYear())); //2021-12-31
//获取当月的第一个星期一
System.out.println("当月的第一个星期一:"+now.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY))); //2021-11-01
//获取当月的最后一个星期一
System.out.println("当月的最后一个星期一:"+now.with(TemporalAdjusters.lastInMonth(DayOfWeek.MONDAY))); //2021-11-29

//获取当月第三周星期五
System.out.println("当月第三周星期五:"+now.with(TemporalAdjusters.dayOfWeekInMonth(3, DayOfWeek.FRIDAY))); //2021-11-19
//获取本周一
System.out.println("本周一:"+now.with(DayOfWeek.MONDAY)); //2021-11-29
//获取上周二
System.out.println("上周二:"+now.minusWeeks(1).with(ChronoField.DAY_OF_WEEK, 2)); //2021-11-23
//(往前不包括当天)获取当前日期的上一个周一  如果今天是周一,则返回上周一
System.out.println("上一个周一(不包括当天):"+now.with(TemporalAdjusters.previous(DayOfWeek.MONDAY))); //2021-11-29
//(往前包括当天)最近星期五的日期  如果今天是星期五,则返回今天日期
System.out.println("上一个周一(包括当天):"+now.with(TemporalAdjusters.previousOrSame(DayOfWeek.FRIDAY))); //2021-11-26
//获取下周二
System.out.println("下周二:"+now.plusWeeks(1).with(ChronoField.DAY_OF_WEEK, 2)); //2021-12-07
//(往后不包括当天)获取当前日期的下一个周日 如果今天是周日,则返回下周日的时间  如果今天是星期一,则返回本周日的时间
System.out.println("下一个周日(不包括当天):"+now.with(TemporalAdjusters.next(DayOfWeek.SUNDAY))); //2021-12-05
//(往后包括当天)最近星期五的日期  如果今天是星期五,则返回今天日期
System.out.println("下一个周日(包括当天):"+now.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY))); //2021-12-03

四. 自定义TemporalAdjuster 实现

我们可以通过两种不同方式自定义TemporalAdjuster 实现。

4.1. 使用lambda表达式

请看如何通过Temporal.with()方法获得2021-12-02之后7天的日期:

LocalDate localDate = LocalDate.of(2021, 12, 2);
TemporalAdjuster temporalAdjuster = t -> t.plus(Period.ofDays(7));
LocalDate result = localDate.with(temporalAdjuster);

String fourteenDaysAfterDate = "2021-12-09";
System.out.println(fourteenDaysAfterDate.equals(result.toString()));//true

该示例中,使用了lambda表达式,设置temporalAdjuster为给localDate.of(2021, 12, 2)对象增加7天。

下面看如何获得2021-12-02之后的工作日,通过自定义TemporalAdjuster 实现,但这次使用static工厂方法ofDateAdjuster():

获取下一个工作日

LocalDate localDate = LocalDate.of(2021, 12, 2);

TemporalAdjuster NEXT_WORKING_DAY = TemporalAdjusters.ofDateAdjuster(date -> {
    DayOfWeek dayOfWeek = date.getDayOfWeek();
    if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {
        return localDate.plusDays(3);
    } else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {
        return localDate.plusDays(2);
    } else {
        return localDate.plusDays(1);
    }
});
System.out.println("下一个工作日:" + localDate.with(NEXT_WORKING_DAY));

简写为:

LocalDate nextWorkDay = LocalDate.now().with(tempDate -> {
   LocalDate localDate = (LocalDate) tempDate;
    DayOfWeek dayOfWeek = localDate.getDayOfWeek();
    if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {
        return localDate.plusDays(3);
    } else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {
        return localDate.plusDays(2);
    } else {
        return localDate.plusDays(1);
    }
});
System.out.println("下一个工作日:" + nextWorkDay);

4.2. 实现TemporalAdjuster 接口

下面通过实现TemporalAdjuster接口实现同样功能:

public class CustomTemporalAdjuster implements TemporalAdjuster {
 
    @Override
    public Temporal adjustInto(Temporal temporal) {
        DayOfWeek dayOfWeek 
          = DayOfWeek.of(temporal.get(ChronoField.DAY_OF_WEEK));
         
        int daysToAdd;
        if (dayOfWeek == DayOfWeek.FRIDAY)
            daysToAdd = 3;
        else if (dayOfWeek == DayOfWeek.SATURDAY)
            daysToAdd = 2;
        else
            daysToAdd = 1;
        return temporal.plus(daysToAdd, ChronoUnit.DAYS);
    }
}

测试代码如下:

LocalDate localDate = LocalDate.of(2021, 12, 3);
CustomTemporalAdjuster temporalAdjuster = new CustomTemporalAdjuster();
LocalDate nextWorkingDay = localDate.with(temporalAdjuster);

System.out.println("2021-12-06".equals(nextWorkingDay.toString())); //true