Перейти к основному содержимому

TemporalAdjuster в Java

· 5 мин. чтения

1. Обзор

В этом руководстве мы кратко рассмотрим TemporalAdjuster и используем его в нескольких практических сценариях.

В Java 8 появилась новая библиотека для работы с датами и временем — java.time и TemporalAdjuster — ее часть. Если вы хотите узнать больше о java.time, ознакомьтесь с этой вводной статьей.

Проще говоря, TemporalAdjuster — это стратегия настройки объекта Temporal . Прежде чем приступить к использованию TemporalAdjuster , давайте взглянем на сам интерфейс Temporal .

2. Временная

Temporal определяет представление даты, времени или их комбинации, в зависимости от реализации, которую мы собираемся использовать.

Существует ряд реализаций интерфейса Temporal , в том числе:

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

3. Временной корректор

Одним из интерфейсов, включенных в эту новую библиотеку, является TemporalAdjuster .

TemporalAdjuster — это функциональный интерфейс, который имеет множество предопределенных реализаций в классе TemporalAdjusters . Интерфейс имеет единственный абстрактный метод с именем AdjustInto() , который можно вызвать в любой из его реализаций, передав ему объект 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

Мы также можем определить собственные реализации для 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 , который содержит дату (2017-07-08).

Давайте посмотрим, как мы можем получить дату рабочего дня сразу после 2017-07-08, определив наши собственные реализации 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 , предопределенные TemporalAdjuster, как их можно использовать и как мы можем реализовать наши пользовательские реализации TemporalAdjuster двумя разными способами.

Полную реализацию этого руководства можно найти на GitHub .