At work there is an input-system where customers are able to specify weekdays and a starting time for an event. The weekdays are integers in the range from 1 (Monday) to 7 (Sunday).
After the customer has given the needed input, I need to calculate the next possible DateTime
for the event. If the event is on the same day as today and the current time is not yet over the submitted starting-time, the next possible DateTime
would be today.
This is what I have came up with, but it looks awful and complicated. You can obviously shorten the linq-queries a little, but i let the intermediate objects in there for sake of debugging.
public static class Test
{
public static void Main( string[] args )
{
var now = DateTime.Now;
var startTimes = new List<TimeSpan> {
now.TimeOfDay , // get the next possible starting point
now.TimeOfDay.Add( new TimeSpan( 0 , 1 , 0 ) ) , // starting point is today
};
var weekdaysList = new List<int[]> {
new [] { 1 , 4 , 5 } ,
new [] { 1 , 2 } ,
};
foreach( var weekdays in weekdaysList )
{
foreach( var startTime in startTimes )
{
var dt = GetNext( weekdays , startTime );
}
}
}
public static DateTime GetNext( int[] weekdays , TimeSpan startTime )
{
// convert to german format (Monday:1 - Sunday:7)
var currentWeekDay = (int)DateTime.Now.DayOfWeek;
if( currentWeekDay == 0 )
currentWeekDay = 7;
// if today, and not yet passed, return todays starting time
if( weekdays.Contains( currentWeekDay ) )
{
var today = DateTime.Now.Date.Add( startTime );
if( DateTime.Now < today )
return today;
}
// calculate the day index and keep the added days around (better debugging)
var days = Enumerable.Range( 0 , 7 )
.Select( addedDays => new { addedDays , dayIndex = ( currentWeekDay + addedDays ) % 7 } )
.ToArray();
// only days that are specified
var validDays = days
.Where( x => weekdays.Contains( x.dayIndex ) )
.ToArray();
// the first day is the one that has the least days added
var daysToAdd = validDays.First().addedDays;
// but we already sorted out today, so the next possible day is the second (if exists) or 1 week/ 7 days later
if( daysToAdd == 0 )
{
if( validDays.Count() > 1 )
daysToAdd = validDays.ElementAt( 1 ).addedDays;
else
daysToAdd = 7;
}
return DateTime.Now.Date
.AddDays( daysToAdd )
.Add( startTime );
}
}
I feel like I am missing some obvious shortcuts or linq-fu to shorten this code down and make it easier understandable.
I let this code as it is, but it was bugging me the whole day, how could I improve this?
Only the basic algorithm in the GetNext()
-Method is relevant, no error-checking etc.