Проверьте, является ли диапазон дат последовательным в c #? - PullRequest
11 голосов
/ 04 мая 2011

Предположим, у меня есть пользовательский интерфейс, в котором пользователь может выбирать дни. Есть ли способ проверить, являются ли выбранные дни последовательными, например:

4/4, 4/5, 4/6, 4/7, 4/8, 4/9, 4/10 или

4/29, 4/30, 5/1, 5/2, 5/3

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

Что касается вышеописанных сценариев, они в порядке и могут перенести на следующий месяц.

Я использую .NET Framework 2.0 и не могу использовать LINQ.

Относительно ответа Тома:

DateTime dtStart = new DateTime(2011,5,4);
DateTime dtEnd = new DateTime(2011,5,11);

int numberOfDaysSelected = 7; //Assume 7 days were selected.

TimeSpan ts = dtEnd - dtStart;


if(ts.Days == numberOfDaysSelected - 1)
{
Console.WriteLine("Sequential");
}
else
{
Console.WriteLine("Non-Sequential");
}

Ответы [ 5 ]

11 голосов
/ 04 мая 2011

Я не верю, что есть встроенный метод для достижения желаемых результатов, но если вы можете легко определить самые ранние и самые поздние даты, вы можете создать новый временной интервал, вычтя самую раннюю дату из самой последней даты, а затем проверив, чтоколичество дней на временной шкале соответствует количеству выбранных дат - 1.

2 голосов
/ 04 мая 2011

Вы не сказали нам, если дни заказаны.

Вы не сказали нам, могут ли они упасть за месяц, как в

30, 31, 1.

Я предполагаю, что заказано, и я предполагаю, что они не упадут за границу месяца (потому что ваш пример упорядочен, и он не попадает за границу месяца).

Тогда вы можете сказать

public bool IsSequential(this IEnumerable<DateTime> sequence) {
    Contract.Requires(sequence != null);
    var e = sequence.GetEnumerator();
    if(!e.MoveNext()) {
        // empty sequence is sequential
        return true;
    }
    int previous = e.Current.Date;
    while(e.MoveNext()) {
        if(e.Current.Date != previous.AddDays(1)) {
            return false;
        }      
        previous = e.Current.Date;
    }
    return true;
}

Обратите внимание, что это решение требует только один раз пройти последовательность. Если у вас нет упорядоченной последовательности или вы допускаете превышение границы месяца, решение более сложное.

1 голос
/ 04 мая 2011

Метод расширения с использованием Linq:

public static bool IsContiguous(this IEnumerable<DateTime> dates)
{
    var startDate = dates.FirstOrDefault();

    if (startDate == null)
        return true;

    //.All() doesn't provide an indexed overload :(
    return dates
        .Select((d, i) => new { Date = d, Index = i })
        .All(d => (d.Date - startDate).Days == d.Index);
}

Тестирование:

List<DateTime> contiguousDates = new List<DateTime>
{
    new DateTime(2011, 05, 05),
    new DateTime(2011, 05, 06),
    new DateTime(2011, 05, 07),
};
List<DateTime> randomDates = new List<DateTime>
{
    new DateTime(2011, 05, 05),
    new DateTime(2011, 05, 07),
    new DateTime(2011, 05, 08),
};

Console.WriteLine(contiguousDates.IsContiguous());
Console.WriteLine(randomDates.IsContiguous());

Возвращает

True
False

EDIT :

.NET 2-подобный ответ:

public static bool CheckContiguousDates(DateTime[] dates)
{
    //assuming not null and count > 0
    var startDate = dates[0];

    for (int i = 0; i < dates.Length; i++)
    {
        if ((dates[i] - startDate).Days != i)
            return false;
    }
    return true;
}
1 голос
/ 04 мая 2011

Ничего не встроено, но вы можете легко создать его, используя Linq:

List<DateTime> timeList = new List<DateTime>();
//populate list..
bool isSequential = timeList.Zip(timeList.Skip(1), 
                                 (a, b) => b.Date == a.Date.AddDays(1))
                            .All(x => x);

Отредактировано - неправильно понял вопрос, означающий сначала возрастание во времени, а не последовательный - исправил это.

0 голосов
/ 01 октября 2013

Вы можете использовать TimeGapCalculator из библиотеки периодов времени для .NET , чтобы найти промежутки между несколькими периодами времени (независимо от порядка, количества и перекрытия):

// ----------------------------------------------------------------------
public void SequentialPeriodsDemo()
{
  // sequential
  ITimePeriodCollection periods = new TimePeriodCollection();
  periods.Add( new Days( new DateTime( 2011, 5, 4 ), 2 ) );
  periods.Add( new Days( new DateTime( 2011, 5, 6 ), 3 ) );
  Console.WriteLine( "Sequential: " + IsSequential( periods ) );

  periods.Add( new Days( new DateTime( 2011, 5, 10 ), 1 ) );
  Console.WriteLine( "Sequential: " + IsSequential( periods ) );
} // SequentialPeriodsDemo

// --------------------------------------------------------------------
public bool IsSequential( ITimePeriodCollection periods, ITimePeriod limits = null )
{
  return new TimeGapCalculator<TimeRange>( 
    new TimeCalendar() ).GetGaps( periods, limits ).Count == 0;
} // IsSequential
...