Skip to content

Instantly share code, notes, and snippets.

@Fristi
Last active December 14, 2015 10:59
Show Gist options
  • Save Fristi/5076190 to your computer and use it in GitHub Desktop.
Save Fristi/5076190 to your computer and use it in GitHub Desktop.
Time windows in C# - A time window is a constrained period of time.
public class Main
{
public Main()
{
var windows = new List<TimeWindow>()
{
new TimeWindow(startHour: 0, endHour: 4, day: DayOfWeek.Monday),
new TimeWindow(startHour: 0, endHour: 5, day: DayOfWeek.Thursday)
};
//check if we are in a window at the moment...
if (windows.Any(x => x.IsInWindow(DateTime.Now)))
{
//do something..
}
//a timespan till the closest window..
TimeSpan timeSpanTillClosestTimeWindow = windows.TimeSpanTillClosestTimeWindow();
}
}
public class SystemTime
{
private static Func<DateTime> now = () => DateTime.Now;
public static Func<DateTime> Now
{
get { return now; }
set { now = value; }
}
}
public class TimeWindow
{
public int StartHour { get; private set; }
public int EndHour { get; private set; }
public DayOfWeek Day { get; private set; }
public TimeWindow(int startHour, int endHour, DayOfWeek day)
{
if (startHour > endHour)
{
throw new ArgumentException("startHour can't be greater then endHour!");
}
StartHour = startHour;
EndHour = endHour;
Day = day;
}
public bool IsInWindow(DateTime dt)
{
return dt.DayOfWeek == Day && dt.Hour >= StartHour && dt.Hour < EndHour;
}
}
public static class TimeWindowExtensions
{
public static TimeSpan TimeSpanTillClosestTimeWindow(this IEnumerable<TimeWindow> timeWindows)
{
if (timeWindows == null)
{
throw new ArgumentNullException("timeWindows");
}
if (!timeWindows.Any())
{
throw new ArgumentException("there should be atleast one timewindow!");
}
var now = SystemTime.Now();
var timeWindowsToday = timeWindows.Where(x => x.Day == now.DayOfWeek && x.StartHour - now.Hour > 0);
if (!timeWindowsToday.Any())
{
return FindRelativeClosestDayFromToday(timeWindows, now);
}
var closestTimeWindows = from n in timeWindowsToday
let relativeClosestHour = n.StartHour - now.Hour
orderby relativeClosestHour
select n;
var closestTimeWindow = closestTimeWindows.FirstOrDefault();
return TimeSpanTillStart(0, closestTimeWindow.StartHour, now);
}
private static TimeSpan FindRelativeClosestDayFromToday(IEnumerable<TimeWindow> timeWindows, DateTime now)
{
var absoluteClosestDay = from n in timeWindows
let deltaDayOfWeek = n.Day - now.DayOfWeek
where deltaDayOfWeek > 0
orderby deltaDayOfWeek
select n;
if (!absoluteClosestDay.Any())
{
return FindRelativeClosestDayNextWeek(timeWindows, now);
}
var closestDay = absoluteClosestDay.FirstOrDefault();
var startOverInDays = closestDay.Day - now.DayOfWeek;
return TimeSpanTillStart(startOverInDays, closestDay.StartHour, now);
}
private static TimeSpan TimeSpanTillStart(int startOverInDays, int startHour, DateTime now)
{
var dt = now;
if (startOverInDays > 0)
{
dt = now.AddDays(startOverInDays);
}
var rdt = new DateTime(dt.Year, dt.Month, dt.Day, startHour, 0, 0);
return rdt.Subtract(now);
}
private static TimeSpan FindRelativeClosestDayNextWeek(IEnumerable<TimeWindow> timeWindows, DateTime now)
{
var relativeClosestDays = from n in timeWindows
let deltaDayOfWeek = Math.Abs(n.Day - now.DayOfWeek)
orderby deltaDayOfWeek descending
select n;
var relativeClosestDay = relativeClosestDays.FirstOrDefault();
var startOverInDays = 7 - Math.Abs(relativeClosestDay.Day - now.DayOfWeek);
return TimeSpanTillStart(startOverInDays, relativeClosestDay.StartHour, now);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment