Я только что опубликовал решение для этой проблемы. Я надеюсь, что это отвечает на ваш вопрос.
Самый простой способ и лучшее описание в теме - тот, который я нашел на этот вопрос . В нем говорится, что диапазоны дат перекрываются, когда для них обоих верно, что их начальная дата не позднее конечной даты другого диапазона дат. Это очень ясно, если немного подумать об этом.
На основе этой концепции я создал два вспомогательных метода:
protected String BuildDateRangeOverlapFilter(DateTime startDate, DateTime endDate)
{
StringBuilder sb = new StringBuilder();
sb.Append(String.Format("<Where><And>{0}{1}</And></Where>",
BuildSimpleDateFilter("StartDate", endDate, "Leq"),
BuildSimpleDateFilter("DueDate", startDate, "Geq")));
return sb.ToString();
}
protected String BuildSimpleDateFilter(String dateFieldName, DateTime filterDate, String relation)
{
String filter = String.Format("<{0}><FieldRef Name='{1}'/><Value Type='DateTime'>{2}</Value></{0}>",
relation, dateFieldName, SPUtility.CreateISO8601DateTimeFromSystemDateTime(filterDate));
return filter;
}
А вот пример использования:
DateTime startDate = DateTime.Today.AddDays(11);
DateTime endDate = DateTime.Today.AddDays(15);
SPList taskList = web.Lists["Tasks"];
SPQuery query = new SPQuery();
query.ViewFields = "<FieldRef Name='Title'/><FieldRef Name='StartDate'/><FieldRef Name='DueDate'/>";
query.Query = BuildDateRangeOverlapFilter(startDate, endDate);
SPListItemCollection matches = taskList.GetItems(query);
foreach (SPListItem match in matches)
{
Console.WriteLine(match["Title"]);
}
Несколько замечаний по использованию:
- Дата начала диапазонов дат должна быть меньше или равна
дата окончания, но я думаю, что это приемлемое ограничение.
- Прежде чем вы спросите, я не проверял это решение с повторяющимися
события, но я предполагаю, что это не работает в этом случае. Извините!
- Чтобы преобразовать мою дату, хранящуюся как DateTime, в строку, которую я использовал ранее,
Метод DateTime.ToString (String format) с шаблоном формата
«yyyy-MM-ddT00: 00: 00Z», позже я обнаружил, что более или менее соответствует
UniversalSortableDateTimePattern, поэтому переключен на параметр «u». Если
вы проверяете исходный код
SPUtility.CreateISO8601DateTimeFromSystemDateTime метод, используемый в
этот образец (например, с отражателем), вы можете увидеть, что вместо
просто вызвать DateTime.ToString с правильным шаблоном, это займет
отдельные части DateTime (например, год, месяц, день и т. д.),
и создает результат, добавляя эти компоненты друг к другу
используя StringBuilder. Сначала это было довольно странно для меня, но
затем подумал, что это должен быть самый быстрый способ преобразования, как это
не имеют накладных расходов на распознавание образов и множество условий
найдено в DateTime.ToString. Однако, если вы должны работать со временем
информация о зоне, то это может быть не идеально для вас. Хотя ISO
8601 поддерживает часовые пояса, AFAIS не реализован в
СоздайтеISO8601DateTimeFromSystemDateTime, например, предоставив
перегрузка с параметром DateTimeOffset. Я не знаю, если CAML
поддерживает все такого рода информацию о часовых поясах, представленных в
строка даты. Я признаю, что это не решающий вопрос в большинстве случаев,
однако это может вызвать сюрприз, если не принять во внимание. Вы
можете прочитать немного больше об этом здесь .