Как проверить временной интервал в Java? - PullRequest
0 голосов
/ 10 октября 2019

Я хочу создать новую аннотацию для проверки диапазона меток времени, но это было напрасно. Я попытался создать его с помощью javax.validation, который должен проверить интервал validFrom и validTo.

1 Ответ

1 голос
/ 10 октября 2019

Создайте объект, который наследует этот интерфейс.

public interface EpochInterval {
    Long getStartTime();
    Long getEndTime();
}

Затем создайте свой валидатор

@Component
public class PeriodConstraintValidator implements ConstraintValidator<PeriodConstraint, EpochInterval> {

    private final TimeZoneUtil timeZoneUtil;
    private Set<ChronoUnit> supportedUnits;

    private long amount;
    private ChronoUnit units;

    public PeriodConstraintValidator(TimeZoneUtil timeZoneUtil) {
        this.timeZoneUtil = timeZoneUtil;
        supportedUnits = new HashSet<>(5);
        supportedUnits.add(ChronoUnit.DAYS);
        supportedUnits.add(ChronoUnit.WEEKS);
        supportedUnits.add(ChronoUnit.MONTHS);
        supportedUnits.add(ChronoUnit.YEARS);
    }

    @Override public void initialize(PeriodConstraint constraintAnnotation) {
        ChronoUnit units = constraintAnnotation.units();
        if (!supportedUnits.contains(units))
            throw new IllegalArgumentException("Unit " + this.units.name() + " is not supported");

        this.amount = constraintAnnotation.amount();
        this.units = units;
    }

    @Override public boolean isValid(EpochInterval interval, ConstraintValidatorContext context) {

        Instant start = Instant.ofEpochSecond(interval.getStartTime());
        Instant end = Instant.ofEpochSecond(interval.getEndTime());

        Period between = Period.between(
                start.atZone(timeZoneUtil.getUTC()).toLocalDate(),
                end.atZone(timeZoneUtil.getUTC()).toLocalDate());

        // Custom checking, delete if not necessary
        if (between.getDays() <= 0) {
            context.disableDefaultConstraintViolation();
            context
                    .buildConstraintViolationWithTemplate("Period should be at least one day long")
                    .addPropertyNode("startTime")
                    .addConstraintViolation();
            context
                    .buildConstraintViolationWithTemplate("Period should be at least one day long")
                    .addPropertyNode("endTime")
                    .addConstraintViolation();
            return false;
        }

        if (between.get(units) < amount) {
            String unit = units.toString();
            String msg = "Given duration is less than a " + unit.substring(0, unit.length() - 1).toLowerCase();
            context.disableDefaultConstraintViolation();
            context
                    .buildConstraintViolationWithTemplate(msg)
                    .addPropertyNode("startTime")
                    .addConstraintViolation();
            context
                    .buildConstraintViolationWithTemplate(msg)
                    .addPropertyNode("endTime")
                    .addConstraintViolation();
            return false;
        }

        return true;
    }
}

Затем создайте аннотацию для интервала:

@Constraint(validatedBy = PeriodConstraintValidator.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface PeriodConstraint {
    String message() default "Invalid interval";
    Class<?>[] groups() default { };
    Class<? extends Payload>[] payload() default { };
    ChronoUnit units();
    long amount();
}

Затем аннотируйте ваш объект, который должен наследовать интерфейс выше, как этот:

@PeriodConstraint(units = ChronoUnit.DAYS, amount = 7)
public class YourClazz implements EpochInteval {
    private Long startTime;
    private Long endTime;    

    // Getters and setters are omitted for brevity
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...