/**
* ***************************************************************************
* Copyright (c) 2010 Qcadoo Limited
* Project: Qcadoo Framework
* Version: 1.4
*
* This file is part of Qcadoo.
*
* Qcadoo is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation; either version 3 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***************************************************************************
*/
package com.qcadoo.commons.dateTime;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.joda.time.LocalDate;
import org.joda.time.LocalTime;
import com.google.common.base.Preconditions;
/**
* Immutable, thread-safe class representing time range. Time ranges with end time before start time are interpreted as ending in
* the next day (from start do midnight (inclusive) and from midnight to end time).
*
* @author Marcin Kubala
* @since 1.2.1
*
*/
public class TimeRange implements Comparable<TimeRange> {
private final LocalTime from;
private final LocalTime to;
/**
* Get new Time range
*
* If time to is earlier than time from, range will be considered as ending at next day.
*
* @param from
* lower bound
* @param to
* upper bound
*/
public TimeRange(final LocalTime from, final LocalTime to) {
Preconditions.checkArgument(from != null, "Missing lower bound for time range.");
Preconditions.checkArgument(to != null, "Missing upper bound for time range.");
this.from = from;
this.to = to;
}
/**
* @return true if from is greater than to.
*/
public boolean startsDayBefore() {
return to.isBefore(from);
}
/**
* Check if given time is included in this time range. If from & to boundaries is in reversed order (time from is greater than
* to; startsDayBefore() returns true) then it will be checked that given time is contained in range [from time = midnight
* (inclusive)] or [midnight - to time].
*
* @param time
* @return true if this time range contains given time.
*/
public boolean contains(final LocalTime time) {
if (startsDayBefore()) {
return !time.isAfter(to) || !time.isBefore(from);
}
return !time.isAfter(to) && !time.isBefore(from);
}
public LocalTime getFrom() {
return from;
}
public LocalTime getTo() {
return to;
}
public Interval toInterval(final LocalDate date) {
DateTime start = date.toDateTime(getFrom());
DateTime end = date.toDateTime(getTo());
if (startsDayBefore()) {
end = end.plusDays(1);
}
return new Interval(start, end);
}
@Override
public int compareTo(final TimeRange other) {
return getFrom().compareTo(other.getFrom());
}
@Override
public int hashCode() {
return new HashCodeBuilder(1, 31).append(from).append(to).toHashCode();
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
TimeRange other = (TimeRange) obj;
return new EqualsBuilder().append(from, other.from).append(to, other.to).isEquals();
}
}