Проверяйте дату / время последовательно по месяцам - PullRequest
1 голос
/ 06 августа 2009

У меня есть список, содержащий 60 DateTime объектов (отсортированных по возрастанию), и мне нужно проверить, что каждая дата на 1 месяц больше предыдущей в списке.

Например, следующий список дат будет действительным, поскольку они увеличиваются на один месяц без пропущенных:

январь-2009
февраль-2009
март-2009
Апрель-2009

Однако следующий список дат будет недействительным, поскольку отсутствует февраль 2009 года:

январь 2009 г.
март 2009 г.
апрель 2009 г.

День не имеет значения, считаются только месяц и год .

Есть ли эффективный / красивый способ сделать это?

Ответы [ 4 ]

8 голосов
/ 06 августа 2009

Для всех дат, если вы берете (год * 12 + месяц), вы получите последовательный список целых чисел. Это может быть легче проверить на наличие пробелов.

3 голосов
/ 06 августа 2009

Вы можете попробовать следующее:

int start = list.First().Year * 12 + list.First().Month;
bool sequential = list
    .Select((date, index) => date.Year * 12 + date.Month - index)
    .All(val => val == start);

Это «преобразует» список дат в число, представляющее год и месяц, которые должны увеличиваться на 1 для каждого элемента в списке. Затем мы вычитаем текущий индекс из каждого из этих элементов, поэтому для правильного списка все элементы будут иметь одинаковое значение. Затем мы сравниваем все значения с start, которое является первым вычисленным значением.

1 голос
/ 07 августа 2009

Вот чистая проверка с использованием тщательно созданного селектора, который будет корректно сравниваться с вашим вариантом использования:

IEnumerable<DateTime> dates = ...;
DateTime firstDate = dates.First();
IEnumerable desired = Enumerable.Range(0, 60).Select(months => firstDate.AddMonths(months));
bool correct = dates.SequenceEqual(desired, date => date.Year*12 + date.Month);

Использование этого пользовательского SequenceEqual:

public static bool SequenceEqual<T1, T2>(this IEnumerable<T1> first, IEnumerable<T1> second, Func<T1, T2> selector)
{
    // uses the LINQ Enumerable.SequenceEqual method on the selections
    return first.Select(selector).SequenceEqual(second.Select(selector));
}

// this is also useful, but not used in this example
public static bool SequenceEqual<T1, T2>(this IEnumerable<T1> first, IEnumerable<T1> second, Func<T1, T2> selector, IEqualityComparer<T2> comparer)
{
    return first.Select(selector).SequenceEqual(second.Select(selector), comparer);
}
0 голосов
/ 06 августа 2009
public bool MonthsAreSequential(IList<DateTime> dates)
{
    if (dates.Count < 2) return true;

    for (int i = 0; i < dates.Count - 1; i++)
    {
        var plusOne = dates[i].AddMonth(1);
        var nextMonth = dates[i + 1];
        if (plusOne .Year != nextMonth .Year 
            || plusOne .Month != nextMonth .Month)
            return false;
    }
    return true;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...