TemporalAdjuster в Java

1. Общ преглед

В този урок ще разгледаме бързо TemporalAdjuster и ще го използваме в няколко практически сценария.

Java 8 представи нова библиотека за работа с дати и часове - java.time и TemporalAdjuster е част от нея. Ако искате да прочетете повече за java.time, проверете тази уводна статия.

Най-просто казано, TemporalAdjuster е стратегия за коригиране на Temporal обект. Преди да започнем да използваме TemporalAdjuster , нека да разгледаме самия интерфейс Temporal .

2. Временна

А Времеви определя представяне на дата, час, или комбинация от двете, в зависимост от изпълнението ние ще използваме.

Има редица изпълнения на временния интерфейс, включително:

  • LocalDate - която представлява дата без часова зона
  • LocalDateTime - който представлява дата и час без часова зона
  • HijrahDate - която представлява дата в системата на календара Hijrah
  • MinguoDate - която представлява дата в календарната система на Minguo
  • ThaiBuddhistDate - която представлява дата в тайландската будистка календарна система

3. TemporalAdjuster

Един от интерфейсите, включени в тази нова библиотека, е TemporalAdjuster .

TemporalAdjuster е функционален интерфейс, който има много предварително дефинирани реализации в класа TemporalAdjusters . Интерфейсът има един абстрактен метод, наречен AdjuInto (), който може да бъде извикан във всяка от неговите реализации, като му предаде Temporal обект.

TemporalAdjuster ни позволява да извършваме сложни манипулации с дати. Например можем да получим датата на следващата неделя, последния ден от текущия месец или първия ден на следващата година. Можем, разбира се, да направим това с помощта на стария java.util.Calendar .

Новият API обаче абстрахира основната логика, използвайки своите предварително дефинирани реализации. За повече информация посетете Javadoc.

4. Предварително дефинирани TemporalAdjusters

Класът TemporalAdjusters има много предварително дефинирани статични методи, които връщат TemporalAdjuster обект, за да коригират Temporal обекти по много различни начини, независимо каква реализация на Temporal те биха могли да бъдат.

Ето кратък списък на тези методи и тяхното бързо определяне:

  • dayOfWeekInMonth () - регулатор за обикновения ден от седмицата. Например датата на втория вторник през март
  • firstDayOfMonth () - регулатор за датата на първия ден от текущия месец
  • firstDayOfNextMonth () - регулатор за датата на първия ден от следващия месец
  • firstDayOfNextYear () - регулатор за датата на първия ден на следващата година
  • firstDayOfYear () - коректор за датата на първия ден от текущата година
  • lastDayOfMonth () - коректор за датата на последния ден от текущия месец
  • nextOrSame () - регулатор за датата на следващото появяване на определен ден от седмицата или същия ден, в случай че днес съвпада с необходимия ден от седмицата

Както виждаме, имената на методите са почти обясними. За повече TemporalAdjusters посетете Javadoc.

Нека започнем с прост пример - вместо да използваме конкретна дата, както в примерите, можем да използваме LocalDate.now (), за да получим текущата дата от системния часовник.

Но за този урок ще използваме фиксирана дата, така че тестовете да не се провалят по-късно, когато очакваният резултат се промени. Нека да видим как можем да използваме класа TemporalAdjusters, за да получим датата на неделята след 08.07.2017:

@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());

5. Дефиниране на изпълнение на персонализирани временни настройки

Също така можем да дефинираме нашите персонализирани реализации за TemporalAdjuster . Има два различни начина за това.

5.1. Използване на ламбда изрази

Нека да видим как можем да получим датата, която е 14 дни след 08.07.2017 г., използвайки метода Temporal.with () :

@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()); }

В този пример, използвайки ламбда израз, задаваме обекта temporalAdjuster да добавя 14 дни към обекта localDate , който съдържа датата (08.07.2017 г.).

Нека да видим как можем да получим датата на работния ден веднага след 08.07.2017 г., като дефинираме собствените си реализации на TemporalAdjuster с помощта на ламбда израз. Но този път, използвайки статичния фабричен метод на 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()); }

5.2. Чрез внедряване на интерфейса TemporalAdjuster

Нека да видим как можем да напишем персонализиран TemporalAdjuster, който получава работния ден след 08.07.2017 чрез прилагане на интерфейса 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()); }

6. Заключение

В този урок показахме какво е TemporalAdjuster , предварително дефинирани TemporalAdjusters, как те могат да се използват и как можем да реализираме нашите персонализирани реализации на TemporalAdjuster по два различни начина.

Пълното изпълнение на този урок може да бъде намерено в GitHub.