Найти следующую дату и время на основе заданного списка DayOfWeek

У меня есть список элементов перечисления DayOfWeek: var daysOfWeek = List<DayOfWeek>

Этот список содержит переменное количество элементов DaysOfWeek, например. Понедельник, Четверг, Суббота.

Я хотел бы найти следующее DateTime для любого заданного DateTime на основе List<DayOfWeek>.

Если данная дата выпадет на среду, следующее значение DateTime, которое должно вернуться, будет четвергом.

Если данная дата выпадет на четверг, следующее значение DateTime, которое должно вернуться, будет субботой.

До сих пор я возился с некоторыми выражениями LINQ и пробовал некоторые параметры с методом расширения Min(), но у меня нет кода, которым я мог бы поделиться, который был бы работоспособным. Мне интересно, не хватает ли мне некоторых реальных базовых функций LINQ.

SO-темы, которые до сих пор дали мне некоторые идеи, включают Вот этот и Вон тот, однако я не смог найти решение своей проблемы с их ответами.

Я ответил, но должен уточнить, вы искали следующий DayOfWeek или следующий DateTime?

Risto M 10.04.2019 19:32

Спасибо за ваш ответ @RistoM! Я искал следующий DateTime, который соответствует ближайшему DayOfWeek в моем списке.

jrn 10.04.2019 19:35

Хорошо, посмотрим, смогу ли я улучшить ответ.

Risto M 10.04.2019 19:36

Имеет ли значение порядок в списке (например, если это были понедельник, суббота, четверг, приведет ли четверг к понедельнику или субботе)?

NetMage 10.04.2019 19:39

Нет, порядок не должен иметь значения.

jrn 10.04.2019 19:40
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
281
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий
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);
}

Вы можете вычислить (неотрицательное) расстояние между завтрашним днем ​​и следующим днем ​​недели в списке, а затем использовать минимальное расстояние, чтобы получить новую дату:

var tomorrowDOW = startDate.AddDays(1).DayOfWeek;
var dist = daysOfWeek.Select(w => (w - tomorrowDOW + 14) % 7).Min();
var nextDate = startDate.AddDays(dist + 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();
        }
    }
}

Предполагается, что ответ должен быть Дата следующего дня недели, а не дня недели.

NetMage 10.04.2019 19:59

Помимо отличных ответов, опубликованных на этот вопрос, вот еще одно решение, которое отлично сработало для меня. Я создал следующий частный метод для возврата следующего 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));
    }

Другие вопросы по теме