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 )
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 altrimenti segnalatemi qualsiasi imprecisione.
Tag di Technorati:
C#,
Date Range