我会用创建一个自定义类Schedule
来封装计算和数据。然后,您可以填写您用作数据源的List<Schedule>
(或不同的集合类型/数据库)。
这里是一个可能的实现:
public class Schedule
{
public enum Type
{
Monthly,
Weekly
}
public Schedule(DayOfWeek weekDay)
{
this.ScheduleType = Type.Weekly;
this.WeekDay = weekDay;
}
public Schedule(int monthDay)
{
if (monthDay < 1 || monthDay > 31)
throw new ArgumentException("Invalid day");
this.ScheduleType = Type.Monthly;
this.MonthDay = monthDay;
}
public Type ScheduleType { get; set; }
public int MonthDay { get; set; }
public DayOfWeek WeekDay { get; set; }
public String Comment { get; set; }
}
下面的列表,并与您的样本数据初始化:
private List<Schedule> _AllSchedules;
public List<Schedule> AllSchedules
{
get
{
if (_AllSchedules == null)
{
_AllSchedules = new List<Schedule>();
Schedule s1 = new Schedule(1);
Schedule s2 = new Schedule(15);
Schedule s3 = new Schedule(29);
Schedule s4 = new Schedule(DayOfWeek.Monday);
Schedule s5 = new Schedule(DayOfWeek.Wednesday);
Schedule s6 = new Schedule(DayOfWeek.Friday);
_AllSchedules.AddRange(new[] { s1, s2, s3, s4, s5, s6 });
}
return _AllSchedules;
}
}
下面是应该给的计算可能(不彻底的测试)实施你的想法:
public DateTime? GetNextScheduledDate(DateTime from)
{
var nextMonthDay = AllSchedules
.Where(s => s.ScheduleType == Schedule.Type.Monthly && s.MonthDay >= from.Day)
.OrderBy(s => s.MonthDay)
.DefaultIfEmpty(AllSchedules
.Where(s => s.ScheduleType == Schedule.Type.Monthly && s.MonthDay < from.Day)
.OrderByDescending(s => s.MonthDay)
.FirstOrDefault())
.FirstOrDefault();
var nextWeekDay = AllSchedules
.Where(s => s.ScheduleType == Schedule.Type.Weekly)
.Select(s => new { Schedule = s, Diff = ((int)s.WeekDay- (int)from.DayOfWeek) })
.OrderBy(x => x.Diff >= 0)
.ThenBy(x => Math.Abs(x.Diff))
.FirstOrDefault();
DateTime? nextMonthDate = null;
DateTime? nextWeekDate = null;
if (nextMonthDay != null)
{
int diff = nextMonthDay.MonthDay - from.Day;
if (diff < 0)
{
// next month
nextMonthDate = from.AddMonths(1).AddDays(diff);
}
else
{
// this month
nextMonthDate = from.AddDays(diff);
}
}
if (nextWeekDay != null)
{
nextWeekDate = from.AddDays(nextWeekDay.Diff < 0 ? 7 - Math.Abs(nextWeekDay.Diff) : nextWeekDay.Diff);
}
if (!nextMonthDate.HasValue && !nextWeekDate.HasValue)
return null;
else
return nextMonthDate < nextWeekDate ? nextMonthDate : nextWeekDate;
}
现在它很简单,重新adable:
DateTime? nextScheduled = GetNextScheduledDate(DateTime.Today);
// nextScheduled.Value.ToString("d", CultureInfo.InvariantCulture): "12/16/2013"