我相信这可以通过一些经过深思熟虑的日期数学来完成,但是下面可能被称为懒惰的出路。这种方法只需要开始日期,一周中上课的日期列表,即星期一,星期二等......,以小时和分钟为单位的课程持续时间,最后是所需的最大总小时和分钟.
根据我的理解,鉴于上述信息,我们想知道,鉴于开课日期和班级开会的星期几……
满足最大总小时数的 LAST 课程将在什么日期。
为了简化这一点,可以派上用场的一件事就是知道......
“需要多少类才能满足 MAX 要求”。
换句话说,如果我们知道需要多少个类来满足最大要求,那么这应该会使事情变得更容易。
计算满足最大要求所需的班级总数,可以通过将最大要求除以班级持续时间来计算。如果除法产生余数,则这意味着需要一 (1) 个额外的类来满足最大要求。
因此,如果我们将类持续时间和最大持续时间变量都作为Timespan 对象,那么我们可以通过它们各自的Tick 属性划分TimeSpan 对象,并返回需要多少类才能满足最大值要求。这种方法可能看起来像……
private int GetTotalNumberOfClassesNeeded(TimeSpan classDuration, TimeSpan totalDuration) {
double td = totalDuration.Ticks / (double)classDuration.Ticks;
int totalClasses = (int)Math.Truncate(td); // <- get the whole portion
if (Math.Floor(td) != td) {
totalClasses++; // <- there is a fractional part - 1 more class needed
}
return totalClasses;
}
接下来,我们需要将日期的DayOfWeek 与班级的DayOfWeek 进行比较。因此,我们可以做的是创建一个List<DayOfWeek> ... 一个类在会话中的DayOfWeek 对象列表。我们将使用此列表来检查特定日期的星期几是否在该列表中。因此,在此示例中,班级在一周中的哪几天见面是一个简单的逗号分隔 string。鉴于此string,代码将解析出日期并返回要与之比较的DayOfWeek 对象的正确列表。这种方法可能看起来像……
private List<DayOfWeek> GetDaysOfWeekForClasses(string daysOfWeek) {
List<DayOfWeek> classesDOW = new List<DayOfWeek>();
string[] splitArray = daysOfWeek.Split(',');
DayOfWeek dow;
for (int i = 0; i < splitArray.Length; i++) {
switch (splitArray[i].Trim()) {
case "Monday":
dow = DayOfWeek.Monday;
break;
case "Tuesday":
dow = DayOfWeek.Tuesday;
break;
case "Wednesday":
dow = DayOfWeek.Wednesday;
break;
case "Thursday":
dow = DayOfWeek.Thursday;
break;
case "Friday":
dow = DayOfWeek.Friday;
break;
case "Saturday":
dow = DayOfWeek.Saturday;
break;
default:
dow = DayOfWeek.Sunday;
break;
}
classesDOW.Add(dow);
}
return classesDOW;
}
这几乎就是我们所需要的。总体思路是……我们首先将int 变量curClassCount 设置为零(0)。此外,我们将创建一个DateTime 对象tempDate,它使用开始日期进行初始化。最后,我们将创建一个DateTime 对象列表scheduledClasses,其中将填充课程的日期。我们将启动一个while 循环,只要curClassCount 小于所需的类总数,就会继续。
在循环的每次迭代中,都会检查tempDate 的DayOfWeek 是否是类的DayOfWeek. 之一……如果是,那么我们将该日期添加到scheduledClasses 列表中并增加curClassCount。最后将tempDate 增加一 (1) 天,然后重新开始循环。最终,curClassCount 将等于所需的类数。这段代码可能看起来像……
while (curClassCount < totalNumberOfClassesNeeded) {
if (ClassDaysOfWeek.Contains(tempDate.DayOfWeek)) {
scheduledClasses.Add(tempDate.Date);
curClassCount++;
}
tempDate = tempDate.AddDays(1);
}
通过将DateTimePicker, four (4) TextBoxes、Button 和多行TextBox 放到新的Winforms .Net 上,将所有这些放在一起,Form 可能看起来像……
使用下面的代码应该可以完成示例。
private void Form1_Load(object sender, EventArgs e) {
dateTimePicker1.Value = new DateTime(2021, 4, 18);
TextBoxTotDaysPerWeek.Text = "3";
textBoxClassDays.Text = "Monday, Tuesday, Wednesday";
textBoxClassDuration.Text = "00:03:00:00";
textBoxMaxDuation.Text = "02:02:00:00";
}
private void btnCalculate_Click(object sender, EventArgs e) {
DateTime StartDate = dateTimePicker1.Value;
TimeSpan.TryParse(textBoxClassDuration.Text.Trim(), out TimeSpan ClassDuration);
TimeSpan.TryParse(textBoxMaxDuation.Text.Trim(), out TimeSpan MaxDuration);
int totalNumberOfClassesNeeded = GetTotalNumberOfClassesNeeded(ClassDuration, MaxDuration);
List<DayOfWeek> ClassDaysOfWeek = GetDaysOfWeekForClasses(textBoxClassDays.Text.Trim());
List<DateTime> scheduledClasses = new List<DateTime>();
int curClassCount = 0;
DateTime tempDate = StartDate.Date;
while (curClassCount < totalNumberOfClassesNeeded) {
if (ClassDaysOfWeek.Contains(tempDate.DayOfWeek)) {
scheduledClasses.Add(tempDate.Date);
curClassCount++;
}
tempDate = tempDate.AddDays(1);
}
txtBoxResults.Text = "";
txtBoxResults.Text = "Start Date: " + StartDate.ToShortDateString() +Environment.NewLine;
for (int i = 0; i < scheduledClasses.Count; i++) {
txtBoxResults.Text += "Class # " + (i + 1) + " of " + totalNumberOfClassesNeeded +
" Date: " + scheduledClasses[i].ToShortDateString() + Environment.NewLine;
}
}
注意,关于最长持续时间……因为 TimeSpan 只允许小时