OceanusDateRange.java
/*******************************************************************************
* Oceanus: Java Utilities
* Copyright 2012,2025 Tony Washer
*
* 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 net.sourceforge.joceanus.oceanus.date;
import java.time.temporal.ChronoUnit;
import java.util.Locale;
import java.util.Objects;
/**
* Represents a contiguous Range of dates.
*/
public class OceanusDateRange
implements Comparable<OceanusDateRange> {
/**
* Unbounded range description.
*/
protected static final String DESC_UNBOUNDED = OceanusDateResource.RANGE_UNBOUNDED.getValue();
/**
* link range description.
*/
protected static final String DESC_LINK = OceanusDateResource.RANGE_TO.getValue();
/**
* link range description.
*/
protected static final char CHAR_BLANK = ' ';
/**
* The Start Date for the range.
*/
private OceanusDate theStart;
/**
* The End Date for the range.
*/
private OceanusDate theEnd;
/**
* Construct a Range from a Start Date and an End Date.
* @param pStart the start date
* @param pEnd the end date
*/
public OceanusDateRange(final OceanusDate pStart,
final OceanusDate pEnd) {
if (pStart != null) {
theStart = new OceanusDate(pStart);
}
if (pEnd != null) {
theEnd = new OceanusDate(pEnd);
}
}
/**
* Construct a range from another range.
* @param pRange the range to copy from
*/
public OceanusDateRange(final OceanusDateRange pRange) {
this(pRange.getStart(), pRange.getEnd());
}
/**
* Construct an unbounded Range.
*/
public OceanusDateRange() {
this(null, null);
}
/**
* Get the start date for the range.
* @return the Start date
*/
public OceanusDate getStart() {
return theStart;
}
/**
* Get the end date for the range.
* @return the End date
*/
public OceanusDate getEnd() {
return theEnd;
}
/**
* Determine whether a Date is within this range.
* @param pDate the date to test
* @return -1 if the date is after the range, 0 if the date is within the range, 1 if the date
* is before the range
*/
public int compareToDate(final OceanusDate pDate) {
/* Check start date */
if (theStart != null
&& theStart.compareTo(pDate) > 0) {
return 1;
}
/* Check end date */
if (theEnd != null
&& theEnd.compareTo(pDate) < 0) {
return -1;
}
/* Date must be within range */
return 0;
}
@Override
public int compareTo(final OceanusDateRange pThat) {
/* Handle the trivial cases */
if (this.equals(pThat)) {
return 0;
}
if (pThat == null) {
return -1;
}
/* Access target start date */
final OceanusDate myStart = pThat.getStart();
/* If our start is null */
if (theStart == null) {
/* Handle non-null target start */
if (myStart != null) {
return 1;
}
/* else start is non-null */
} else {
/* Handle null target start */
if (myStart == null) {
return -1;
}
/* Compare the start dates */
final int result = theStart.compareTo(myStart);
if (result != 0) {
return result;
}
}
/* Access target end date */
final OceanusDate myEnd = pThat.getEnd();
/* If our end is null */
if (theEnd == null) {
/* Handle non-null target end */
if (myEnd != null) {
return 1;
}
/* else start is non-null */
} else {
/* Handle null target end */
if (myStart == null) {
return -1;
}
/* Compare the end dates */
final int result = theEnd.compareTo(myEnd);
if (result != 0) {
return result;
}
}
/* Ranges are identical */
return 0;
}
@Override
public String toString() {
/* Build range description */
final StringBuilder myBuilder = new StringBuilder();
myBuilder.append(theStart == null
? DESC_UNBOUNDED
: theStart.toString());
myBuilder.append(CHAR_BLANK);
myBuilder.append(DESC_LINK);
myBuilder.append(CHAR_BLANK);
myBuilder.append(theEnd == null
? DESC_UNBOUNDED
: theEnd.toString());
/* return the format */
return myBuilder.toString();
}
@Override
public boolean equals(final Object pThat) {
/* Handle the trivial cases */
if (this == pThat) {
return true;
}
if (pThat == null) {
return false;
}
/* Make sure that the object is a JDateDayRange */
if (pThat.getClass() != this.getClass()) {
return false;
}
/* Access the object as a DateRange */
final OceanusDateRange myThat = (OceanusDateRange) pThat;
/* Check components */
if (theStart == null) {
if (myThat.getStart() != null) {
return false;
}
} else if (!theStart.equals(myThat.getStart())) {
return false;
}
if (theEnd == null) {
if (myThat.getEnd() != null) {
return false;
}
} else if (!theEnd.equals(myThat.getEnd())) {
return false;
}
return true;
}
@Override
public int hashCode() {
return Objects.hash(theStart, theEnd);
}
/**
* Set the locale.
* @param pLocale the locale
*/
public void setLocale(final Locale pLocale) {
if (theStart != null) {
theStart.setLocale(pLocale);
}
if (theEnd != null) {
theEnd.setLocale(pLocale);
}
}
/**
* Determine whether two DateDay objects differ.
* @param pCurr The current Date
* @param pNew The new Date
* @return <code>true</code> if the objects differ, <code>false</code> otherwise
*/
public static boolean isDifferent(final OceanusDateRange pCurr,
final OceanusDateRange pNew) {
/* Handle case where current value is null */
if (pCurr == null) {
return pNew != null;
}
/* Handle case where new value is null */
if (pNew == null) {
return true;
}
/* Handle Standard cases */
return !pCurr.equals(pNew);
}
/**
* Obtain the number of days in the range.
* @return the number of days (or -1 if unbounded)
*/
public long getNumDays() {
/* Handle unbounded */
if (theStart == null || theEnd == null) {
return -1;
}
/* Calculate the number of days */
return 1 + ChronoUnit.DAYS.between(theStart.getDate(), theEnd.getDate());
}
}