DateRange in C#

Su richiesta di qualcuno ho provveduto a fare il porting in C# di una mia “vecchia” classe per la gestione dei range di data di cui avevo parlato qui.

Ecco la versione C# (…devo ammettere mi ha fatto scovare un po’ di “cavolate” che VB non segnalava Imbarazzato)

    public class DateRange 
    {

        public enum IntervalType
        {
            Milliseconds,
            Second,
            Minute,
            Hour,
            Day
        }

        public enum Direction
        {
            Foward,
            Backward
        }

        private DateTime _start;
        public DateTime Start
        {
            get { return _start; }
            set { _start = value; }
        }

        private DateTime _end;
        public DateTime End
        {
            get { return _end; }
            set { _end = value; }
        }

        public DateRange(DateTime start, DateTime end)
        {
            _start = start;
            _end = end;
        }

        public bool IsEmpty
        {
            get
            {
                return (_start.CompareTo(null) == 0 && _end.CompareTo(null) == 0) || (_start.Equals(null) && _end.Equals(null));
            }
        }

        public bool Contains(DateTime value)
        {
            DateTime dateValue = value;
            return _start.CompareTo(dateValue) <= 0 && dateValue.CompareTo(_end) <= 0;
        }

        public bool Contains(DateRange other)
        {
            return this.Contains(other._start) && this.Contains(other._end);
        }

        public bool Intersect(DateRange other)
        {
            return !(this.Contains(other)) || other.Contains(_start) || other.Contains(_end);
        }

        public bool Overlaps(DateRange other)
        {
            return this.Contains(other) || other.Contains(_start) || other.Contains(_end);
        }

        public DateRange Intersection(DateRange other)
        {

            if (!this.Overlaps(other))
                return null;

            if (this.Contains(other))
                return other;
            if (other.Contains(this))
                return this;

            if (this.Start > other.Start)
            {
                return new DateRange(this.Start, other.End);
            }
            else
            {
                return new DateRange(other.Start, this.End);
            }

        }

        public IList<DateRange> Subtraction(DateRange other)
        {
            List<DateRange> ret = new List<DateRange>();

            if (this.Overlaps(other) && !other.Contains(this) && !this.Equals(other))
            {
                if (this.Contains(other))
                {
                    if (!(this.Start == other.Start))
                        ret.Add(new DateRange(this.Start, other.Start));
                    if (!(this.End == other.End))
                        ret.Add(new DateRange(other.End, this.End));
                }
                else
                {
                    if (this.Start >= other.Start)
                    {
                        ret.Add(new DateRange(other.End, this.End));
                    }
                    else
                    {
                        ret.Add(new DateRange(this.Start, other.End));
                    }
                }
            }

            return ret;

        }

        public double Total(IntervalType intervalType)
        {

            switch (intervalType)
            {
                case IntervalType.Day:
                    return _end.Subtract(_start).TotalDays;
                case IntervalType.Hour:
                    return _end.Subtract(_start).TotalHours;
                case IntervalType.Milliseconds:
                    return _end.Subtract(_start).TotalMilliseconds;
                case IntervalType.Minute:
                    return _end.Subtract(_start).TotalMinutes;
                case IntervalType.Second:
                    return _end.Subtract(_start).TotalSeconds;
                default:
                    throw new NotImplementedException("Not supported interval");
            }
        }

        public DateRange Extend(int value, IntervalType intervalType, Direction direction)
        {


            switch (intervalType)
            {
                case IntervalType.Day:
                    if (direction == DateRange.Direction.Backward)
                        return new DateRange(_start.AddDays(-1 * value), _end);
                    else
                        return new DateRange(_start, _end.AddDays(value));
                case IntervalType.Hour:
                    if (direction == DateRange.Direction.Backward)
                        return new DateRange(_start.AddHours(-1 * value), _end);
                    else
                        return new DateRange(_start, _end.AddHours(value));
                case IntervalType.Minute:
                    if (direction == DateRange.Direction.Backward)
                        return new DateRange(_start.AddMinutes(-1 * value), _end);
                    else
                        return new DateRange(_start, _end.AddMinutes(value));
                case IntervalType.Second:
                    if (direction == DateRange.Direction.Backward)
                        return new DateRange(_start.AddSeconds(-1 * value), _end);
                    else
                        return new DateRange(_start, _end.AddSeconds(value));
                case IntervalType.Milliseconds:
                    if (direction == DateRange.Direction.Backward)
                        return new DateRange(_start.AddMilliseconds(-1 * value), _end);
                    else
                        return new DateRange(_start, _end.AddMilliseconds(value));
                default:
                    throw new NotImplementedException("Not supported interval");
            }
        }

        public DateRange Shift(int value, IntervalType intervalType, Direction direction)
        {

            switch (intervalType)
            {
                case IntervalType.Day:
                    if (direction == DateRange.Direction.Foward)
                        return new DateRange(_start.AddDays(value), _end.AddDays(value));
                    else
                        return new DateRange(_start.AddDays(-1 * value), _end.AddDays(-1 * value));
                case IntervalType.Hour:
                    if (direction == DateRange.Direction.Foward)
                        return new DateRange(_start.AddHours(value), _end.AddHours(value));
                    else
                        return new DateRange(_start.AddHours(-1 * value), _end.AddHours(-1 * value));
                case IntervalType.Minute:
                    if (direction == DateRange.Direction.Foward)
                        return new DateRange(_start.AddMinutes(value), _end.AddMinutes(value));
                    else
                        return new DateRange(_start.AddMinutes(-1 * value), _end.AddMinutes(-1 * value));
                case IntervalType.Second:
                    if (direction == DateRange.Direction.Foward)
                        return new DateRange(_start.AddSeconds(value), _end.AddSeconds(value));
                    else
                        return new DateRange(_start.AddSeconds(-1 * value), _end.AddSeconds(-1 * value));
                case IntervalType.Milliseconds:
                    if (direction == DateRange.Direction.Foward)
                        return new DateRange(_start.AddMilliseconds(value), _end.AddMilliseconds(value));
                    else
                        return new DateRange(_start.AddMilliseconds(-1 * value), _end.AddMilliseconds(-1 * value));
                default:
                    throw new NotImplementedException("Not supported interval");

            }
        }

        public override int GetHashCode()
        {
            return _start.GetHashCode() ^ _end.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            if (obj is DateRange)
            {
                return Equals((DateRange)obj);
            }
            else
            {
                return false;
            }
        }

        public bool Equals(DateRange other)
        {
            return _start.Equals(other._start) && _end.Equals(other._end);
        }

        public static bool operator ==(DateRange a, DateRange b)
        {
            return a.Equals(b);
        }

        public static bool operator !=(DateRange a, DateRange b)
        {
            return !(a == b);
        }
    }

Ho approfittato per aggiungere gli operatori == e != (cosa non fattibile in VB).

Spero che la fretta non abbia prodotto danni ai gattini A bocca aperta altrimenti segnalatemi qualsiasi imprecisione.

Tag di Technorati: ,
«agosto»
domlunmarmergiovensab
31123456
78910111213
14151617181920
21222324252627
28293031123
45678910