package org.sigmah.shared.util; /* * #%L * Sigmah * %% * Copyright (C) 2010 - 2016 URD * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import java.io.Serializable; import java.util.Date; import org.sigmah.client.util.ToStringBuilder; /** * Defines a time period as a range of dates. The end points of the range are <em>inclusive</em>, so that a date range * of 1-Jan-09 to 31-Jan-09 would include all events that took place at any moment in the month of January. The * {@code DateRange} can be also be open on either end. Here are a few concrete examples: * <table> * <thead> * <tr> * <td><strong>{@code minDate}</strong></td> * <td><strong>{@code maxDate}</strong></td> * <td><strong>Meaning</strong></td> * </tr> * </thead> <tbody> * <tr> * <td>{@code null}</td> * <td>{@code null}</td> * <td>All dates</td> * </tr> * <tr> * <td>1-Feb-09</td> * <td>{@code null}</td> * <td>All dates on or after 1-Feb-09</td> * </tr> * <tr> * <td>{@code null}</td> * <td>31-Jan-09</td> * <td>All dates on or before 31-Jan-09 (2009 or earlier)</td> * </tr> * </tbody> * <caption>Accepted parameters and result examples</caption> * </table> * * <p> * A server-side version of this class exists for XML manipulations, see * {@link org.sigmah.shared.dto.pivot.model.DateRange}. * </p> * * @author Alex Bertram * @author Denis Colliot (dcolliot@ideia.fr) */ public class DateRange implements Serializable { /** * Serial version UID. */ private static final long serialVersionUID = -3018792678414321316L; /** * The range min date. */ private Date minDate; /** * The range max date. */ private Date maxDate; /** * Initializes a fully open date range (all dates are included). */ public DateRange() { this(null, null); } /** * Initializes a new {@code DateRange}, clone of the given {@code dateRange}. * * @param dateRange * The date range. */ public DateRange(final DateRange dateRange) { this(dateRange != null ? dateRange.minDate : null, dateRange != null ? dateRange.maxDate : null); } /** * Initializes a {@code DateRange} bounded by {@code minDate} and {@code maxDate}. * * @param minDate * The minimum date to be included in this range (inclusive), or {@code null} if there is no minimum bound. * @param maxDate * The maximum date to be included in this range (inclusive), or {@code null} if there is no maximum bound. */ public DateRange(final Date minDate, final Date maxDate) { setMinDate(minDate); setMaxDate(maxDate); } /** * Gets the minimum date in this range (inclusive). * * @return The minimum date in this range (inclusive) or {@code null} if the range has no lower bound */ public Date getMinDate() { return minDate; } /** * Sets the minimum date in this range (inclusive). * * @param minDate * The minimum date in this range (inclusive) or {@code null} if the range has now upper bound. */ public void setMinDate(Date minDate) { this.minDate = minDate; } /** * Gets the maximum date in this range (inclusive). * * @return The maximum date in this range (inclusive) or {@code null} if the range has no upper bound. */ public Date getMaxDate() { return maxDate; } /** * Sets the maximum date in this range (inclusive). * * @param maxDate * The maximum date in this range (inclusive) or {@code null} if the range has no upper bound. */ public void setMaxDate(Date maxDate) { this.maxDate = maxDate; } /** * @return true if the range is closed, i.e. has both min and max dates. */ public boolean isClosed() { return minDate != null && maxDate != null; } /** * Returns the intersection {@code DateRange} between the given two {@code DateRange}s. * * @param a * The first {@code DateRange} (cannot be {@code null}). * @param b * The second {@code DateRange} (cannot be {@code null}). * @return The intersection {@code DateRange} between the given two {@code DateRange}s. */ public static DateRange intersection(final DateRange a, final DateRange b) { final DateRange range = new DateRange(); // Min date. if (a.minDate == null && b.minDate != null) { range.minDate = b.minDate; } else if (a.minDate != null && b.minDate == null) { range.minDate = a.minDate; } else if (a.minDate != null && b.minDate != null) { if (a.minDate.after(b.minDate)) { range.minDate = a.minDate; } else { range.minDate = b.minDate; } } // Max date. if (a.maxDate == null && b.maxDate != null) { range.maxDate = b.maxDate; } else if (a.maxDate != null && b.maxDate == null) { range.maxDate = a.maxDate; } else if (a.maxDate != null && b.maxDate != null) { if (a.maxDate.before(b.maxDate)) { range.maxDate = a.maxDate; } else { range.maxDate = b.maxDate; } } return range; } /** * {@inheritDoc} */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((maxDate == null) ? 0 : maxDate.hashCode()); result = prime * result + ((minDate == null) ? 0 : minDate.hashCode()); return result; } /** * {@inheritDoc} */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } DateRange other = (DateRange) obj; if (maxDate == null) { if (other.maxDate != null) { return false; } } else if (!maxDate.equals(other.maxDate)) { return false; } if (minDate == null) { if (other.minDate != null) { return false; } } else if (!minDate.equals(other.minDate)) { return false; } return true; } /** * {@inheritDoc} */ @Override public String toString() { final ToStringBuilder builder = new ToStringBuilder(this); builder.append("minDate", minDate); builder.append("maxDate", maxDate); return builder.toString(); } }