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 .