package com.spun.util.date;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import com.spun.util.DateUtils;
import com.spun.util.MethodExecutionPath;
import com.spun.util.ObjectUtils;
import com.spun.util.filters.Filter;
import com.spun.util.parser.TemplateDate;
public class DateRange
{
public static final DateRange ALL = new DateRange(new Date(0), new Date(Long.MAX_VALUE));
private final Date end;
private final Date start;
/************************************************************************/
public DateRange(Date start, Date end)
{
this.start = start;
this.end = end;
}
/************************************************************************/
public Filter getFilter(Class clazz, String... methodCalls)
{
return getFilter(new MethodExecutionPath(clazz, methodCalls));
}
/************************************************************************/
public Filter getFilter(MethodExecutionPath path)
{
return new DateRangeFilter(this, path);
}
/************************************************************************/
public boolean contains(Date time)
{
time = (time == null) ? new Date() : time;
return (start.getTime() <= time.getTime()) && (time.getTime() < end.getTime());
}
public static DateRange getRangeContaining(DateRange[] ranges, DateRange target)
{
for (DateRange dateRange : ranges)
{
if (dateRange.contains(target)) { return dateRange; }
}
return null;
}
private boolean contains(DateRange range)
{
return contains(range.end) || contains(range.start);
}
/************************************************************************/
public Date getEnd()
{
return end;
}
/************************************************************************/
public Date getStart()
{
return start;
}
/************************************************************************/
@Override
public int hashCode()
{
return ObjectUtils.generateHashCode(start.getTime(), end.getTime());
}
/************************************************************************/
@Override
public boolean equals(Object object)
{
if (this == object)
{
return true;
}
else if (object instanceof DateRange)
{
DateRange that = (DateRange) object;
return this.start.getTime() == that.start.getTime() && this.end.getTime() == that.end.getTime();
}
else
{
return false;
}
}
/************************************************************************/
@Override
public String toString()
{
return String.format("[%s - %s]", new TemplateDate(start).getDateAndTime(), new TemplateDate(end)
.getDateAndTime());
}
/***********************************************************************/
public DateRange[] getWeeks()
{
return getUnits(new WeekAware());
}
private DateRange[] getUnits(UnitAware unit)
{
ArrayList<DateRange> ranges = new ArrayList<DateRange>();
Calendar start = DateUtils.asCalendar(getStart());
Calendar end = (Calendar) start.clone();
while (!(getEnd().getTime() <= end.getTime().getTime()))
{
end.add(Calendar.DAY_OF_YEAR, 1);
if (unit.isStart(end) || getEnd().getTime() <= end.getTime().getTime())
{
ranges.add(new DateRange(start.getTime(), end.getTime()));
start = (Calendar) end.clone();
}
}
return ranges.toArray(new DateRange[ranges.size()]);
}
/***********************************************************************/
public DateRange[] getMonths()
{
return getUnits(new MonthAware());
}
public DateRange[] getQuarters()
{
return getUnits(new QuarterAware());
}
/************************************************************************/
public boolean containsDayOfWeek(int day)
{
return getFirst(day) != null;
}
public Date getFirst(int day)
{
Calendar start = DateUtils.asCalendar(getStart());
while (start.getTime().getTime() <= getEnd().getTime())
{
start.add(Calendar.DAY_OF_YEAR, 1);
if (start.get(Calendar.DAY_OF_WEEK) == day) { return start.getTime(); }
}
return null;
}
/************************************************************************/
/* INNER CLASSES */
/************************************************************************/
public static class DateRangeFilter implements Filter
{
private final MethodExecutionPath path;
private final DateRange range;
public DateRangeFilter(DateRange range, MethodExecutionPath path)
{
this.range = range;
this.path = path;
}
public boolean isExtracted(Object object) throws IllegalArgumentException
{
return range.contains((Date) path.extractValue(object));
}
}
public static interface UnitAware
{
public boolean isStart(Calendar end);
}
public static class WeekAware implements UnitAware
{
public boolean isStart(Calendar end)
{
return end.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY;
}
}
public static class MonthAware implements UnitAware
{
public boolean isStart(Calendar end)
{
return end.get(Calendar.DAY_OF_MONTH) == 1;
}
}
public static class QuarterAware implements UnitAware
{
public boolean isStart(Calendar end)
{
return end.get(Calendar.DAY_OF_MONTH) == 1 && end.get(Calendar.MONTH) % 3 == 0;
}
}
/************************************************************************/
/************************************************************************/
}