根据给定的DayOfWeek列表查找下一个DateTime

时间:2019-04-10 17:14:56

标签: c# .net linq

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

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

我想根据List<DayOfWeek>找到任何给定DateTime的下一个DateTime。

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

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

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

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

4 个答案:

答案 0 :(得分:2)

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);
}

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

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();
        }
    }
}

答案 3 :(得分:1)

除了为该问题发布的出色答案之外,这是另一个对我有用的解决方案。我创建了以下私有方法,以根据给定的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));
    }