public struct DateRange : IEquatable<DateRange>, IComparable<DateRange>{    private readonly DateTime _min;    private readonly DateTime _max;    public DateRange(DateTime min, DateTime max)    {        if (min.CompareTo(max) > 0)            throw new ArgumentOutOfRangeException(max, Cannot be less than min.);        _min = min;        _max = max;    }    public DateTime Min    {        get { return _min; }    }    public DateTime Max    {        get { return _max; }    }    public bool Intersects(DateRange other)    {        return other.Max >= this.Min && other.Min <= this.Max;    }    public bool Contains(DateRange other)    {        return other.Min >= this.Min && other.Max <= this.Max;    }    public bool Precedes(DateRange other)    {        return this.Max < other.Min;    }    public bool Follows(DateRange other)    {        return this.Min > other.Max;    }    public int CompareTo(DateRange other)    {        if (Contains(other) || Follows(other))            return 1;        if (Precedes(other))            return -1;        return 0;    }    public bool Equals(DateRange other)    {        return this.Min.Equals(other.Min) && this.Max.Equals(other.Max);    }    public override bool Equals(object obj)    {        return obj is DateRange && Equals((DateRange)obj);    }    public override int GetHashCode()    {        unchecked        {            int hash = 17;            hash = hash * 23 + Min.GetHashCode();            hash = hash * 23 + Max.GetHashCode();            return hash;        }    }    public override string ToString()    {        return string.Format({0:yyyy-MM-dd} to {1:yyyy-MM-dd}, Min, Max);    }}public sealed class DateRangeTree : IEnumerable<DateRange>{    private readonly IImmutableList<DateRange> _items;    private readonly DateRangeTreeNode _root;    public DateRangeTree(IEnumerable<DateRange> items)    {        if (items == null)            throw new ArgumentNullException(items);        _items = items.OrderBy(x => x.Min).ThenByDescending(x => x.Max).ToImmutableList();        _root = new DateRangeTreeNode(_items);    }    public IEnumerator<DateRange> GetEnumerator()    {        foreach (var item in _root)        {            yield return item;        }    }    IEnumerator IEnumerable.GetEnumerator()    {        return GetEnumerator();    }    private sealed class DateRangeTreeNode : IEnumerable<DateRange>    {        private readonly DateRange _center;        private readonly DateRangeTreeNode _left;        private readonly DateRangeTreeNode _right;        private readonly IImmutableList<DateRange> _items;        public DateRangeTreeNode(IEnumerable<DateRange> items)        {            if (items == null)                throw new ArgumentNullException(items);            var points = new System.Collections.Generic.SortedSet<DateRange>();            foreach (var item in items)            {                points.Add(item);;            }            _center = points.Skip(points.Count / 2).First();            var ns = new List<DateRange>();            var ls = new List<DateRange>();            var rs = new List<DateRange>();            foreach (var item in items)            {                if (item.Precedes(_center))                {                    ls.Add(item);                }                else if (item.Follows(_center))                {                    rs.Add(item);                }                else                {                    ns.Add(item);                }            }            if (ns.Count > 0)            {                _items = ns.OrderBy(x => x.Min).ThenByDescending(x => x.Max).ToImmutableList();            }            if (ls.Count > 0)            {                _left = new DateRangeTreeNode(ls.OrderBy(x => x.Min).ThenByDescending(x => x.Max));            }            if (rs.Count > 0)            {                _right = new DateRangeTreeNode(rs.OrderBy(x => x.Min).ThenByDescending(x => x.Max));            }        }        public IEnumerator<DateRange> GetEnumerator()        {            if (_left != null)            {                foreach (var item in _left)                {                    yield return item;                }            }            if (_items.Count > 0)            {                yield return _items[0];            }            if (_right != null)            {                foreach (var item in _right)                {                    yield return item;                }            }        }        IEnumerator IEnumerable.GetEnumerator()        {            return GetEnumerator();        }    }}
Date Range Tree
c#;datetime