public static void Main()
CalculateForVisits(new [] {
new DateRange(new DateTime(2015, 5, 1), new DateTime(2015, 7, 20)),
new DateRange(new DateTime(2016, 5, 1), 150),
public static void CalculateForVisits(DateRange[] Visits)
var visitsStart = new DateTime(Visits.Select(v => v.Start.Ticks).Min());
var visitsEnd = new DateTime(Visits.Select(v => v.End.Ticks).Max());
var maximumOverlapDaysObserved = 0;
DateRange maximumOverlapedDateRange = null;
for(var periodStart = visitsStart; periodStart < visitsEnd; periodStart += TimeSpan.FromDays(1))
var period = new DateRange(periodStart, 365);
var overlap = Visits.Select(v => v.DaysOverlapInclusive(period)).Sum();
if (overlap > maximumOverlapDaysObserved)
maximumOverlapDaysObserved = overlap;
maximumOverlapedDateRange = period;
Console.WriteLine("Considering the following visits:");
foreach(var visit in Visits)
Console.WriteLine(" " + visit);
Console.WriteLine("The maximum number of days visited for any 365 day period is " + maximumOverlapDaysObserved + " during time period " + maximumOverlapedDateRange + ".");
var initialYear = Visits.Select(v => v.Start.Year).Min();
var lastYear = Visits.Select(v => v.End.Year).Max();
for(var i = initialYear; i <= lastYear; i++) {
var yearRange = new DateRange(new DateTime(i, 1, 1), new DateTime(i+1,1,1).AddDays(-1));
var overlap = Visits.Select(v => v.DaysOverlapInclusive(yearRange)).Sum();
Console.WriteLine("Total time spent in year " + i + " is " + overlap + " days.");
public readonly DateTime Start;
public readonly DateTime End;
public DateRange(DateTime start, DateTime end)
throw new ArgumentException("DateRange specified with start and end dates out of order.");
public DateRange(DateTime start, int totalDaysInclusive) : this(start, start + TimeSpan.FromDays(totalDaysInclusive - 1))
public int DaysOverlapInclusive(DateRange other)
var overlapStart = new DateTime(Math.Max(this.Start.Ticks, other.Start.Ticks));
var overlapEnd = new DateTime(Math.Min(this.End.Ticks, other.End.Ticks));
if (overlapEnd < overlapStart)
return (overlapEnd - overlapStart).Days + 1;
public override string ToString()
var durationInclusive = (End - Start).Days + 1;
return Start.ToLongDateString() + " to " + End.ToLongDateString() + " (" + durationInclusive + " days)";