介紹 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實作。