天天看點

介紹 java 8 TemporalAdjuster 類型

介紹 java 8 TemporalAdjuster 類型

本文我們介紹 java 8 TemporalAdjuster 類以及其使用場景。java 8 引入了新的日期、時間庫————即java.time包,TemporalAdjuster 類是其中之一。

簡而言之,TemporalAdjuster 類是調整Temporal對象的政策。在使用TemporalAdjuster 類之前,我們先看看Temporal接口。

Temporal 接口

Temporal可以根據實際需求表示為日期、時間或兩者組合。其幾個實作類包括:

LocalDate – 表示沒有時區的日期
LocalDateTime – 表示沒有時區的日期和時間

           

TemporalAdjuster 接口

TemporalAdjuster 是函數接口,在TemporalAdjusters 類中有很多預定義的實作。TemporalAdjuster僅有一個帶Temporal對象參數的抽象方法adjustInto()。

TemporalAdjuster可以執行複雜的日期操作,例如,可以獲得下一個星期日對于日期、當月的最後一天、下一年的第一天。當然也可以通過舊的java.util.Calendar api實作。不同的是,新api使用預定義的實作抽象出底層邏輯。

TemporalAdjusters類中預定義實作

TemporalAdjusters類有很多預定義的static方法傳回TemporalAdjuster對象,使用不同方式調節Temporal對象而與Temporal實作無關。

下面列舉部分方法及其定義描述:

  • dayOfWeekInMonth() – 一周中的某一天,例如,三月中第二個星期二
  • firstDayOfMonth() – 目前月的第一天
  • firstDayOfNextMonth() – 下一個月的第一天
  • firstDayOfNextYear() – 下一年的第一天
  • firstDayOfYear() – 當年的第一天
  • lastDayOfMonth() – 當月的最後一天
  • nextOrSame() – 下一次或當天發生的一周中的某天

這些方法的名稱都是自解釋的,更多TemporalAdjusters參考官方文檔。

我們從簡單執行個體開始————我們可以使用特定的日期,也可以使用LocalDate.now()獲得目前日期。但對本例來說,我們使用固定日期,因為不希望後面期望結果變化造成測試不通過。下面看看如果通過TemporalAdjusters類獲得2017-07-08之後的星期日:

@Test
public void whenAdjust_thenNextSunday() {
    LocalDate localDate = LocalDate.of(2017, 07, 8);
    LocalDate nextSunday = localDate.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
     
    String expected = "2017-07-09";
     
    assertEquals(expected, nextSunday.toString());
}
           

再看如何獲得當月的最後一天:

LocalDate lastDayOfMonth = localDate.with(TemporalAdjusters.lastDayOfMonth());
           

自定義TemporalAdjuster 實作

我們可以通過兩種不同方式自定義TemporalAdjuster 實作。

使用lambda表達式

請看如何通過Temporal.with()方法獲得2017-07-09之後14天的日期:

@Test
public void whenAdjust_thenFourteenDaysAfterDate() {
    LocalDate localDate = LocalDate.of(2017, 07, 8);
    TemporalAdjuster temporalAdjuster = t -> t.plus(Period.ofDays(14));
    LocalDate result = localDate.with(temporalAdjuster);
     
    String fourteenDaysAfterDate = "2017-07-22";
     
    assertEquals(fourteenDaysAfterDate, result.toString());
}
           

該示例中,使用了lambda表達式,設定temporalAdjuster為給localDate(2017, 07, 8)對象增加14天。

下面看如何獲得2017-07-08之後的工作日,通過自定義TemporalAdjuster 實作,但這次使用static工廠方法ofDateAdjuster():

static TemporalAdjuster NEXT_WORKING_DAY = TemporalAdjusters.ofDateAdjuster(date -> {
    DayOfWeek dayOfWeek = date.getDayOfWeek();
    int daysToAdd;
    if (dayOfWeek == DayOfWeek.FRIDAY)
        daysToAdd = 3;
    else if (dayOfWeek == DayOfWeek.SATURDAY)
        daysToAdd = 2;
    else
        daysToAdd = 1;
    return today.plusDays(daysToAdd);
});
           

測試代碼:

@Test
public void whenAdjust_thenNextWorkingDay() {
    LocalDate localDate = LocalDate.of(2017, 07, 8);
    TemporalAdjuster temporalAdjuster = NEXT_WORKING_DAY;
    LocalDate result = localDate.with(temporalAdjuster);
 
    assertEquals("2017-07-10", date.toString());
}
           

實作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);
    }
}
           

測試代碼:

@Test
public void whenAdjustAndImplementInterface_thenNextWorkingDay() {
    LocalDate localDate = LocalDate.of(2017, 07, 8);
    CustomTemporalAdjuster temporalAdjuster = new CustomTemporalAdjuster();
    LocalDate nextWorkingDay = localDate.with(temporalAdjuster);
     
    assertEquals("2017-07-10", nextWorkingDay.toString());
}
           

總結

本文我們介紹了TemporalAdjuster接口、TemporalAdjusters類中預定義實作和應用。同時也介紹了兩種方法自定義TemporalAdjuster實作。