package org.helioviewer.jhv.base.interval;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class Interval implements Comparable<Interval> {

    public Date start;
    public Date end;

    public Interval(Date start, Date end) {
        this.start = start;
        this.end = end;
        if (start == null || end == null) {
            Thread.dumpStack();
            System.exit(1);
        }
    }

    public boolean containsInclusive(Interval other) {
        return this.containsPointInclusive(other.start) && this.containsPointInclusive(other.end);
    }

    public boolean containsPointInclusive(Date time) {
        assert start.compareTo(end) <= 0;
        return (time.compareTo(this.start) >= 0) && (time.compareTo(this.end) <= 0);
    }

    public boolean overlapsInclusive(Interval other) {
        return (this.containsPointInclusive(other.start) || this.containsPointInclusive(other.end)) || (other.containsPointInclusive(this.start) || other.containsPointInclusive(this.end));
    }

    /**
     * Returns the value that is as close as possible to the given value, but
     * still contained in the interval. If the given value is outside the
     * interval, the the interval's closest 'edge' is returned.
     */
    public Date squeeze(Date value) {
        if (this.containsPointInclusive(value)) {
            return value;
        } else if (value.compareTo(start) < 0) {
            return start;
        } else if (value.compareTo(end) > 0) {
            return end;
        }
        // this case should never occur
        assert false;
        return value;
    }

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

    @Override
    public int compareTo(Interval other) {
        return this.start.compareTo(other.start);
    }

    public static ArrayList<Interval> splitInterval(final Interval interval, int days) {
        final ArrayList<Interval> intervals = new ArrayList<Interval>();

        final Calendar calendar = new GregorianCalendar();
        Date startDate = interval.start;

        while (true) {
            calendar.clear();
            calendar.setTime(startDate);
            calendar.add(Calendar.DAY_OF_MONTH, days);

            final Date newStartDate = calendar.getTime();

            if (interval.containsPointInclusive(newStartDate)) {
                intervals.add(new Interval(startDate, calendar.getTime()));
                startDate = newStartDate;
            } else {
                intervals.add(new Interval(startDate, interval.end));
                break;
            }
        }

        return intervals;
    }

    @Override
    public boolean equals(Object other) {
        if (other instanceof Interval) {
            Interval s = (Interval) other;
            return (this.start.equals(s.start) && (this.end.equals(s.end)));
        }
        return false;
    }

    @Override
    public int hashCode() {
        return (this.start.toString() + " - " + this.end.toString()).hashCode();
    }

}

@@ -275,24 +275,25 @@
 terval(Date 
+_
 start, Date 
@@ -292,16 +292,17 @@
 t, Date 
+_
 end) %7B%0A 
@@ -312,21 +312,16 @@
     
-this.
 start = 
 star
@@ -316,16 +316,17 @@
 start = 
+_
 start;%0A 
@@ -336,19 +336,15 @@
     
-this.
 end = 
+_
 end;
@@ -535,21 +535,16 @@
  return 
-this.
 contains
@@ -574,21 +574,16 @@
 art) && 
-this.
 contains
@@ -728,17 +728,16 @@
  return 
-(
 time.com
@@ -743,21 +743,16 @@
 mpareTo(
-this.
 start) %3E
@@ -754,22 +754,20 @@
 rt) %3E= 0
-)
  && 
-(
 time.com
@@ -773,21 +773,16 @@
 mpareTo(
-this.
 end) %3C= 
@@ -782,17 +782,16 @@
 nd) %3C= 0
-)
 ;%0A    %7D%0A
@@ -861,22 +861,16 @@
  return 
-(this.
 contains
@@ -900,21 +900,16 @@
 art) %7C%7C 
-this.
 contains
@@ -937,14 +937,12 @@
 end)
-)
  %7C%7C 
-(
 othe
@@ -966,21 +966,16 @@
 clusive(
-this.
 start) %7C
@@ -1009,18 +1009,12 @@
 ive(
-this.
 end)
-)
 ;%0A  
@@ -1300,21 +1300,16 @@
     if (
-this.
 contains
@@ -1776,21 +1776,16 @@
  return 
-this.
 start.co
@@ -2796,30 +2796,24 @@
      return 
-(this.
 start.equals
@@ -2825,22 +2825,16 @@
 art) && 
-(this.
 end.equa
@@ -2842,18 +2842,16 @@
 s(s.end)
-))
 ;%0A      
@@ -2941,21 +2941,16 @@
 return (
-this.
 start.to
@@ -2972,13 +2972,8 @@
 %22 + 
-this.
 end.

Reduce this