Рубрики
Без рубрики

TemporalAdjuster в Java

Быстрый и практический пример использования TemporalAdjusters из java.time.

Автор оригинала: baeldung.

1. Обзор

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

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

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

2. Временная

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

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

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

3. TemporalAdjuster

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

TemporalAdjuster – это функциональный интерфейс, который имеет множество предопределенных реализаций в классе TemporalAdjusters . Интерфейс имеет один абстрактный метод с именем adjustInto () , который может быть вызван в любой из его реализаций путем передачи ему Временного объекта.

TemporalAdjuster позволяет нам выполнять сложные манипуляции с данными. Например , мы можем получить дату следующего воскресенья, последнего дня текущего месяца или первого дня следующего года. Конечно, мы можем сделать это, используя старый java.util.Календарь .

Однако новый API абстрагирует базовую логику, используя ее предопределенные реализации. Для получения дополнительной информации посетите Javadoc .

4. Предопределенные временные настройки

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

Вот краткий список этих методов и их краткое определение:

  • dayOfWeekInMonth() – регулятор для порядкового дня недели. Например, дата второго вторника в марте
  • firstDayOfMonth() – регулятор для даты первого дня текущего месяца
  • firstDayOfNextMonth() – регулятор для даты первого дня следующего месяца
  • firstDayOfNextYear() – регулятор для даты первого дня следующего года
  • firstDayOfYear() – корректировщик на дату первого дня текущего года
  • lastDayOfMonth() – регулятор для даты последнего дня текущего месяца
  • nextOrSame() – регулятор для даты следующего наступления определенного дня недели или того же дня, если сегодняшний день соответствует требуемому дню недели

Как мы видим, названия методов в значительной степени объясняют сами себя. Для получения дополнительной информации TemporalAdjusters посетите Javadoc .

Давайте начнем с простого примера – вместо использования конкретной даты, как в примерах, мы можем использовать 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());

5. Определение пользовательских Реализаций TemporalAdjuster

Мы также можем определить наши пользовательские реализации для TemporalAdjuster . Есть два разных способа сделать это.

5.1. Использование Лямбда-Выражений

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

Давайте посмотрим, как мы можем получить дату рабочего дня сразу после 2017-07-08, определив наши собственные TemporalAdjuster реализации с помощью лямбда-выражения. Но на этот раз с помощью метода of Date Adjuster() static factory:

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 , который получает рабочий день после 2017-07-08, реализовав интерфейс 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 .