All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentripplanner.model.calendar.ServiceDateInterval Maven / Gradle / Ivy

package org.opentripplanner.model.calendar;

import javax.validation.constraints.NotNull;
import java.util.Objects;

import static org.opentripplanner.model.calendar.ServiceDate.MAX_DATE;
import static org.opentripplanner.model.calendar.ServiceDate.MIN_DATE;


/**
 * Value object which represent an service date interval from a starting date
 * until an end date. Both start and end is inclusive.
 *
 * The {@code start} must be equals or before the {@code end} to form a valid
 * period.
 *
 * {@code null} is used to represent an unbounded interval. One or both the of the {@code start} and
 * {@code end} can be {@code null} (unbounded).
 */
public final class ServiceDateInterval {

    private static final ServiceDateInterval UNBOUNDED = new ServiceDateInterval(
            MIN_DATE, MAX_DATE
    );

    private final ServiceDate start;
    private final ServiceDate end;

    public ServiceDateInterval(ServiceDate start, ServiceDate end) {
        this.start = start == null ? MIN_DATE : start;
        this.end = end == null ? MAX_DATE : end;

        // Guarantee that the start is before or equal the end.
        if(this.end.isBefore(this.start)) {
            throw new IllegalArgumentException(
                    "Invalid interval, the end " + end + " is before the start " +  start
            );
        }
    }

    /**
     * Return a interval with start or end unbounded ({@code null}).
     */
    public static ServiceDateInterval unbounded() {
        return UNBOUNDED;
    }

    public boolean isUnbounded() {
        return start.equals(MIN_DATE) && end.equals(MAX_DATE);
    }

    /**
     * Return the interval start, inclusive. If the period start is unbounded the
     * {@link ServiceDate#MIN_DATE} is returned.
     */
    @NotNull
    public ServiceDate getStart() {
        return start;
    }

    /**
     * Return the interval end, inclusive. If the period start is unbounded the
     * {@link ServiceDate#MAX_DATE} is returned.
     */
    @NotNull
    public ServiceDate getEnd() {
        return end;
    }

    /**
     * The intervals have at least one day in common.
     * @see #intersection(ServiceDateInterval)
     */
    public boolean overlap(ServiceDateInterval other) {
        if(start.isBeforeOrEq(other.end)) {
            return end.isAfterOrEq(other.start);
        }
        return false;
    }

    /**
     * Return a new service interval that contains the period with all dates that exist in both
     * periods (intersection of {@code this} and {@code other}).
     *
     * @see #overlap(ServiceDateInterval) for checking an intersection exist.
     *
     * @throws IllegalArgumentException it the to periods do not overlap.
     */
    public ServiceDateInterval intersection(ServiceDateInterval other) {
        return new ServiceDateInterval(
                start.max(other.start),
                end.min(other.end)
        );
    }

    /**
     * Return {@code true} is the given {@code date} exist in this period.
     */
    public boolean include(ServiceDate date) {
        return start.isBeforeOrEq(date) && end.isAfterOrEq(date);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) { return true; }
        if (o == null || getClass() != o.getClass()) { return false; }
        ServiceDateInterval that = (ServiceDateInterval) o;
        return start.equals(that.start) && end.equals(that.end);
    }

    @Override
    public int hashCode() {
        return Objects.hash(start, end);
    }

    @Override
    public String toString() {
        return "[" + start + ", " + end + "]";
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy