【问题标题】:Find next DateTime based on given DayOfWeek List根据给定的 DayOfWeek 列表查找下一个 DateTime
【发布时间】:2019-04-10 17:14:56
【问题描述】:

我有一个 DayOfWeek 枚举项的列表:var daysOfWeek = List<DayOfWeek>

此列表包含可变数量的 DaysOfWeek 项目,例如周一、周四、周六。

我想根据List<DayOfWeek> 找到任何给定日期时间的下一个日期时间。

如果给定的日期是星期三,则应该返回的下一个 DateTime 将是星期四。

如果给定的日期是星期四,则应该返回的下一个 DateTime 将是星期六。

到目前为止,我一直在摆弄一些 LINQ 表达式并尝试使用 Min() 扩展方法的一些选项,但没有可以共享的代码。我想知道我是否缺少一些真正的基本 LINQ 功能。

到目前为止,给我一些想法的 SO-Topics 包括 this onethat one,但是我无法通过他们的回答为我的问题找到解决方案。

【问题讨论】:

  • 我已经回答了,但必须澄清一下,您是在搜索下一个 DayOfWeek 还是下一个 DateTime?
  • 感谢您的回答@RistoM!我正在搜索与列表中最近的 DayOfWeek 匹配的下一个 DateTime。
  • 好的,让我们看看我是否可以改进答案..
  • 列表中的顺序是否重要(例如,如果是星期一、星期六、星期四,星期四会导致星期一或星期六)?
  • 不,顺序无关紧要。

标签: c# .net linq


【解决方案1】:
public static DateTime GetNextDateOrSomething(DateTime start, IEnumerable<DayOfWeek> weekdays)
{
    if (!weekdays.Any()) throw new ArgumentException($"{nameof(weekdays)} cannot be empty.");
    var increments = Enumerable.Range(1, 6);
    var matchedIncrement = increments.FirstOrDefault(i => weekdays.Contains(start.AddDays(i).DayOfWeek));
    return start.AddDays(matchedIncrement > 0 ? matchedIncrement : 7);
}

[DataTestMethod]
[DataRow("4/10/2019", "Wednesday,Thursday", "4/11/2019")]
[DataRow("4/10/2019", "Thursday", "4/11/2019")]
[DataRow("4/10/2019", "Monday,Tuesday", "4/15/2019")]
[DataRow("4/10/2019", "Tuesday", "4/16/2019")]
public void TestDateMethod(string start, string weekdays, string expected)
{
    var startDate = DateTime.Parse(start);
    var weekDaysList = weekdays.Split(',').Select(d => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), d));
    var expectedDate = DateTime.Parse(expected);
    var result = GetNextDateOrSomething(startDate, weekDaysList);
    Assert.AreEqual(expectedDate, result);
}

【讨论】:

    【解决方案2】:

    您可以计算列表中明天和下一周之间的(非负)距离,然后使用最小距离来获取新日期:

    var tomorrowDOW = startDate.AddDays(1).DayOfWeek;
    var dist = daysOfWeek.Select(w => (w - tomorrowDOW + 14) % 7).Min();
    var nextDate = startDate.AddDays(dist + 1);
    

    【讨论】:

      【解决方案3】:
      class Program
          {
              static DateTime NextDay(List<DayOfWeek> workingDays, DateTime dateTime)
              {
                  var result = dateTime;
                  var dayOfWeek = (int)dateTime.DayOfWeek;
      
                  dayOfWeek++;
                  result = result.AddDays(1);
      
                  while (!workingDays.Any(x=> x == (DayOfWeek)dayOfWeek))
                  {
                      if (dayOfWeek > (int)workingDays.Last())
                      {
                          var delta = ((int)workingDays.First() + 7) - dayOfWeek;
                          dayOfWeek = (int)workingDays.First();
                          result = result.AddDays(delta);
      
                      }
                      else
                      {
                          dayOfWeek++;
                          result = result.AddDays(1);
                      }
                  }
                  return result;
              }
      
              static void Main(string[] args)
              {
                  var workingDays = new List<DayOfWeek>()
                  {
                      DayOfWeek.Monday,
                      DayOfWeek.Thursday,
                      DayOfWeek.Saturday
                  };
      
                  workingDays.Sort();
      
                  var dayOfWeek = NextDay(workingDays, DateTime.Now);
                  Console.WriteLine(dayOfWeek.ToString());
      
                  dayOfWeek = NextDay(workingDays, DateTime.Now.AddDays(1));
                  Console.WriteLine(dayOfWeek.ToString());
      
                  dayOfWeek = NextDay(workingDays, DateTime.Now.AddDays(2));
                  Console.WriteLine(dayOfWeek.ToString());
      
                  dayOfWeek = NextDay(workingDays, DateTime.Now.AddDays(3));
                  Console.WriteLine(dayOfWeek.ToString());
      
                  Console.ReadLine();
              }
          }
      }
      

      【讨论】:

      • 答案应该是一周中第二天的日期,而不是星期几。
      【解决方案4】:

      除了为这个问题发布的很好的答案之外,这里还有另一个对我很有用的解决方案。我创建了以下私有方法来根据给定的 DateTime 返回下一个 DateTime 以获取有效 DayOfWeek 项目的列表:

      private static DateTime NextDateTimeByDayOfWeek(DateTime target, List<DayOfWeek> validDaysOfWeek)
          {
              return Enumerable.Range(1, 7)
                  .Select(n => target.AddDays(n))
                  .First(date => validDaysOfWeek.Contains(date.DayOfWeek));
          }
      

      【讨论】:

        猜你喜欢
        • 2014-07-07
        • 1970-01-01
        • 1970-01-01
        • 2011-01-11
        • 1970-01-01
        • 1970-01-01
        • 2020-10-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多