TemporalMatcher.java
/**
* Copyright (C) 2022 Christopher J. Stehno
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.cjstehno.testthings.match;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import java.time.DayOfWeek;
import java.time.Month;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalField;
import java.util.Locale;
import static java.time.DayOfWeek.*;
import static java.time.temporal.ChronoField.*;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.*;
/**
* Matchers used to match temporal-based criteria.
*/
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class TemporalMatcher extends BaseMatcher<Temporal> {
private final TemporalField temporalField;
private final Matcher<Integer> matcher;
/**
* Matches a temporal field that is equal to the specified value.
*
* @param field the temporal field
* @param value the target value
* @return the matcher
*/
public static Matcher<Temporal> fieldIsEqualTo(final TemporalField field, int value) {
return new TemporalMatcher(field, equalTo(value));
}
/**
* Matches a temporal field that is greater than the specified value.
*
* @param field the temporal field
* @param value the target value
* @return the matcher
*/
public static Matcher<Temporal> fieldIsGreaterThan(final TemporalField field, int value) {
return new TemporalMatcher(field, greaterThan(value));
}
/**
* Matches a temporal field that is greater than or equal to the specified value.
*
* @param field the temporal field
* @param value the target value
* @return the matcher
*/
public static Matcher<Temporal> fieldIsGreaterThanOrEqualTo(final TemporalField field, int value) {
return new TemporalMatcher(field, greaterThanOrEqualTo(value));
}
/**
* Matches a temporal field that is less than the specified value.
*
* @param field the temporal field
* @param value the target value
* @return the matcher
*/
public static Matcher<Temporal> fieldIsLessThan(final TemporalField field, int value) {
return new TemporalMatcher(field, lessThan(value));
}
/**
* Matches a temporal field that is less than or equal to the specified value.
*
* @param field the temporal field
* @param value the target value
* @return the matcher
*/
public static Matcher<Temporal> fieldIsLessThanOrEqualTo(final TemporalField field, int value) {
return new TemporalMatcher(field, lessThanOrEqualTo(value));
}
/**
* Matches a YEAR value with the specified value.
*
* @param year the year
* @return the matcher
*/
public static Matcher<Temporal> isInYear(final int year) {
return fieldIsEqualTo(YEAR, year);
}
/**
* Matches a MONTH_OF_YEAR value with the specified value.
*
* @param month the month of the year
* @return the matcher
*/
public static Matcher<Temporal> isInMonth(final Month month) {
return fieldIsEqualTo(MONTH_OF_YEAR, month.getValue());
}
/**
* Matches a MONTH_OF_YEAR value with the specified value.
*
* @param month the month of the year
* @return the matcher
*/
public static Matcher<Temporal> isInMonth(final int month) {
return isInMonth(Month.of(month));
}
/**
* Matches a HOUR_OF_DAY value with the specified value.
*
* @param hour the hour of the day
* @return the matcher
*/
public static Matcher<Temporal> isInHourOfDay(final int hour) {
return fieldIsEqualTo(HOUR_OF_DAY, hour);
}
/**
* Matches an HOUR_OF_DAY value after midnight and before noon.
*
* @return the matcher
*/
public static Matcher<Temporal> isInMorning() {
return allOf(
fieldIsGreaterThanOrEqualTo(HOUR_OF_DAY, 0),
fieldIsLessThan(HOUR_OF_DAY, 12)
);
}
/**
* Matches an HOUR_OF_DAY value of noon or later, but before midnight.
*
* @return the matcher
*/
public static Matcher<Temporal> isInAfternoon() {
return allOf(
fieldIsGreaterThanOrEqualTo(HOUR_OF_DAY, 12),
fieldIsLessThan(HOUR_OF_DAY, 24)
);
}
/**
* Matches a DAY_OF_WEEK value with the specified value.
*
* @param dow day of the week
* @return the matcher
*/
public static Matcher<Temporal> isDayOfWeek(final DayOfWeek dow) {
return fieldIsEqualTo(DAY_OF_WEEK, dow.getValue());
}
/**
* Matches a DAY_OF_WEEK value with the specified value.
*
* @param dow day of the week
* @return the matcher
*/
public static Matcher<Temporal> isDayOfWeek(final int dow) {
return isDayOfWeek(DayOfWeek.of(dow));
}
/**
* Matches a DAY_OF_WEEK value for a weekday (i.e. MONDAY through FRIDAY inclusive).
*
* @return the matcher
*/
public static Matcher<Temporal> isWeekday() {
return anyOf(
isDayOfWeek(MONDAY),
isDayOfWeek(TUESDAY),
isDayOfWeek(WEDNESDAY),
isDayOfWeek(THURSDAY),
isDayOfWeek(FRIDAY)
);
}
/**
* Matches a DAY_OF_WEEK value for a weekend (i.e. SATURDAY or SUNDAY).
*
* @return the matcher
*/
public static Matcher<Temporal> isWeekend() {
return anyOf(
isDayOfWeek(SATURDAY),
isDayOfWeek(SUNDAY)
);
}
@Override public boolean matches(final Object actual) {
return matcher.matches(((Temporal) actual).get(temporalField));
}
@Override public void describeTo(final Description description) {
description.appendText("a " + temporalField.getDisplayName(Locale.ROOT) + " matching ");
matcher.describeTo(description);
}
}