Как группировать даты по неделям?
Я пишу экспортер Excel для созданного на заказ приложения, которое я создаю, и у меня есть вопрос о группировке LINQ в С#.
В принципе, этому новому классу экспортеров Excel даются две даты. Затем класс извлекает все партии между этим диапазоном дат.
Как часть этого экспортера, мне нужно иметь возможность группировать даты в недели и получать значения за эту неделю. Так, например, если мне дано 07/12/2011 и 22/12/2011 (формат dd/MM/yyyy), мне нужно сгруппировать все партии между ними диапазонами в недели (каждую неделю, начиная с воскресенья). Идеальный результат с использованием вышеуказанных дат был бы
Week 1: (consignments between 04/12/2011 and 10/12/2011)
Week 2: (consignments between 11/12/2011 and 17/12/2011)
Week 3: (consignments between 18/11/2011 and 24/12/2011)
Любые идеи?
Ответы
Ответ 1
Основной вопрос здесь заключается в том, как спроектировать экземпляр DateTime
в значение недели года. Это можно сделать, позвонив Calendar.GetWeekOfYear
. Определите проекцию:
Func<DateTime, int> weekProjector =
d => CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(
d,
CalendarWeekRule.FirstFourDayWeek,
DayOfWeek.Sunday);
Вы можете точно определить, как определяется номер недели, путем настройки параметров в вызове метода. Вы также можете определить проекцию, например. если вы предпочитаете метод расширения; это не меняет сути кода. В любом случае, вы готовы к группе по неделям:
var consignmentsByWeek = from con in consignments
group con by weekProjector(con.Date);
Если вы также хотите ограничить вывод конвейцами между двумя конкретными датами, просто добавьте соответствующее предложение where
; логика группировки не изменяется.
Ответ 2
Hesitant, хотя я не согласен с уважаемым автоответчиком, я считаю, что принятый ответ здесь неправильный, и это не принципиально вопрос проецирования на недельную ценность.
GetWeekOfYear(), и концепция в целом заключается в присвоении значений индексов неделям в течение года в соответствии с некоторым согласованным стандартом. Он не подходит для размещения дат в группы из семи смежных дней, как я полагаю, требует допрос.
Не только будет использовать GetWeekOfYear() в качестве предлагаемого результата в группах менее семи дней в конце многих лет, но еще хуже, так как различные стандарты, поддерживаемые GetWeekOfYear(), будут часто распределять первые дни года до последней недели предыдущего года, и все же результат GetWeekOfYear() содержит только индекс целочисленной недели без ссылки на соответствующий год, группировка new { Year = date.Year, weekProjector(date) }
или date.Year + "-" + weekProjector(date)
в отчетный год увидит, что 1 января 2011 года сгруппирован с День Рождества до Нового года двенадцать месяцев в том же году.
Итак, я бы сказал, что исходный вопрос принципиально один из проецируемых не к значению недели года, а к значению недели всего времени, "начало недели в/м/д", которое вы могли бы сказать, поэтому группировка должна быть только сделанный в первый день недели, т.е. (при условии, что вы счастливы по умолчанию в воскресенье) просто:
group by date.AddDays(-(int)date.DayOfWeek)
Ответ 3
В дополнение к ответу Jon's
вы можете получить дату первого дня недели, а затем группу по этой дате.
Получить дату первого дня недели.
вы можете использовать этот код:
public static class DateTimeExtensions
{
public static DateTime StartOfWeek(this DateTime dt, DayOfWeek startOfWeek)
{
int diff = dt.DayOfWeek - startOfWeek;
if (diff < 0)
{
diff += 7;
}
return dt.AddDays(-1 * diff).Date;
}
}
то вы можете сгруппировать по первой дате недели следующим образом:
var consignmentsByWeek = from con in consignments
group con by con.Datedate.StartOfWeek(DayOfWeek.Monday);