/**
   * Returns the result of {@link TimeInterval} i1 &amp; i2 intersection, <code>null</code> if i1
   * does not intersects i2 (<code>null</code> border means infinity).
   */
  public static TimeInterval intersection(TimeInterval i1, TimeInterval i2) {
    if (i1 == null || i2 == null) return null;
    if (!intersects(i1, i2)) return null;
    i1 = arrange(i1);
    i2 = arrange(i2);
    Instant a = null;
    if (i1.getStart() == null && i2.getStart() == null) a = null;
    else if (i1.getStart() == null && i2.getStart() != null) a = i2.getStart();
    else if (i1.getStart() != null && i2.getStart() == null) a = i1.getStart();
    else a = max(i1.getStart(), i2.getStart());

    Instant b = null;
    if (i1.getEnd() == null && i2.getEnd() == null) b = null;
    else if (i1.getEnd() == null && i2.getEnd() != null) b = i2.getEnd();
    else if (i1.getEnd() != null && i2.getEnd() == null) b = i1.getEnd();
    else b = min(i1.getEnd(), i2.getEnd());

    return TimeInterval.between(a, b);
  }
 /** Returns a re-arranged {@link TimeInterval} if borders order is reversed. */
 public static TimeInterval arrange(TimeInterval i) {
   if (i.getStart() != null && i.getEnd() != null && i.getStart().compareTo(i.getEnd()) > 0)
     return TimeInterval.between(i.getEnd(), i.getStart());
   return i;
 }