Calculating difference between cached period and requested
I would suggest moving this method into the TimeSpan class. Let a TimeSpan tell you about its overlaps. Don't interrogate it for internal details and then figure it out for yourself. Private helper methods will make the compareTo calls more readable.
Assorted other thoughts:
A checked exception is probably not right here. I'd suggest preferring IllegalArgumentException, since that's what the problem is. Using a more specific exception than Exception is highly recommended.
Returning early would be preferable to assigning a return value and only returning once. That is a holdover from C, which only allowed a single return.
It's generally preferable to use the List variable type when you don't care about the type of list you're using.
Traditionally, variables are defined at the top of a class, not the bottom.
Traditionally, whitespace is added between if and (, and between ) and {.
The Date class already has an after() method, which would make the TimeSpan constructor cleaner.
Your error message in the constructor is incorrect. The from date also cannot be equal to the to date.
You should strongly consider using java.time instead of the java.util time classes. They are effectively deprecated.
Returning null is probably strictly worse than returning an empty collection, though it's difficult to say that authoritatively without seeing the client code.
If you made all these changes, your code might look something like:
public final class TimeSpan {

    private final Date from;
    private final Date to;

    public TimeSpan(Date from, Date to) throws IllegalArgumentException {
        if (!from.before(to)) {
            throw new IllegalArgumentException(&quot;Start date cannot be greater than or equal to end date&quot;);
        }
        this.from = from;
        this.to = to;
    }

    /**
     * Subtracts the timeSpan argument from this TimeSpan. This will result in a list of between
     * zero and two TimeSpans, ordered by start time.
     * @param timeSpan the span to subtract from this timespan. May not be null.
     * @return a list of TimeSpans covering the time that is in this timespan and not the argument timespan. Will
     * never return null.
     */
    public List&lt;TimeSpan&gt; minus(TimeSpan timeSpan) {
        // This TimeSpan is completely inside the argument.
        if (timeSpan.contains(this.from) &amp;&amp; timeSpan.contains(this.to)) {
            return Collections.emptyList();
        }

        // This TimeSpan is either fully before or fully after argument
        if (this.endsBeforeOrAt(timeSpan) || this.startsAfterOrAt(timeSpan)) {
            return listOf(this); // only OK because this class is immutable
        }

        // This TimeSpan starts before and ends inside the argument
        if (timeSpan.contains(this.to)) {
            return listOf(new TimeSpan(this.from, timeSpan.from));
        }

        // This TimeSpan starts inside and ends after argument
        if (timeSpan.contains(this.from)) {
            return listOf(new TimeSpan(timeSpan.to, this.to));
        }

        // This TimeSpan starts before and ends after argument
        List&lt;TimeSpan&gt; results = new ArrayList&lt;&gt;();
        results.add(new TimeSpan(this.from, timeSpan.from));
        results.add(new TimeSpan(timeSpan.to, this.to));
        return results;
    }

    private boolean endsBeforeOrAt(TimeSpan timeSpan) {
        return this.to.compareTo(timeSpan.from) &lt;= 0;
    }

    private boolean startsAfterOrAt(TimeSpan timeSpan) {
        return this.from.compareTo(timeSpan.to) &gt;= 0;
    }

    private boolean contains(Date date) {
        return (this.from.compareTo(date) &gt;= 0) &amp;&amp; (this.to.compareTo(date) &lt;= 0);
    }

    // If you're using Guava, replace this with Lists.of()
    private static List&lt;TimeSpan&gt; listOf(TimeSpan timeSpan) {
        List&lt;TimeSpan&gt; results = new ArrayList&lt;&gt;();
        results.add(timeSpan);
        return results;
    }

}