TemporalAdjuster в Java

TemporalAdjuster в Java

1. обзор

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

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

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

2. Temporalс

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

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

  • LocalDate - дата без часового пояса

  • LocalDateTime - представляет дату и время без часового пояса

  • HijrahDate - это дата в календарной системе хиджры.

  • MinguoDate - представляет дату в календарной системе Минго

  • ThaiBuddhistDate - представляет дату в тайской буддийской календарной системе

3. TemporalAdjusterс

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

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

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

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

4. ПредопределенныйTemporalAdjusters

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

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

  • dayOfWeekInMonth() - регулятор порядкового дня недели. Например, дата второго вторника марта

  • firstDayOfMonth() - корректировщик числа первого числа текущего месяца

  • firstDayOfNextMonth() - настройщик числа первого числа следующего месяца

  • firstDayOfNextYear() - корректор на дату первого дня следующего года

  • firstDayOfYear() - корректор на дату первого дня текущего года

  • lastDayOfMonth() - корректировщик числа последнего дня текущего месяца

  • nextOrSame() - корректировщик даты следующего наступления определенного дня недели или того же дня в случае, если сегодня совпадает с требуемым днем ​​недели

Как мы видим, имена методов в значительной степени говорят сами за себя. Чтобы узнать больше оTemporalAdjusters, посетитеJavadoc.

Let’s start with a simple example - вместо использования конкретной даты, как в примерах, мы можем использовать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. Использование лямбда-выражений

Давайте посмотрим, как с помощью методаTemporal.with() получить дату через 14 дней после 08.07.2017:

@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).

Давайте посмотрим, как мы можем получить дату рабочего дня сразу после 8 июля 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, который получает рабочий день после 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 двумя разными способами.

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