Как группировать даты по неделям?

Я пишу экспортер 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);