Last active
December 14, 2015 10:59
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class SystemTime | |
{ | |
private static Func<DateTime> now = () => DateTime.Now; | |
public static Func<DateTime> Now | |
{ | |
get { return now; } | |
set { now = value; } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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