Как сгруппировать даты по неделям? - PullRequest
18 голосов
/ 19 декабря 2011

Я пишу экспортер Excel для созданного на заказ приложения, и у меня возник вопрос о группировке LINQ в C #.

По сути, этому новому классу экспортеров Excel даны две даты. Затем класс извлекает все грузы в этом диапазоне дат.

Как часть этого экспортера, мне нужно иметь возможность группировать даты по неделям и получать значения для этой недели. Так, например, если мне дают 12/12/2011 и 22/12/2011 (формат дд / мм / гггг), мне нужно сгруппировать все партии между ними по неделям (каждая неделя начинается с воскресенья). Идеальный результат с использованием вышеуказанных дат будет

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)

Есть идеи?

Ответы [ 3 ]

34 голосов
/ 19 декабря 2011

Фундаментальный вопрос здесь заключается в том, как проецировать экземпляр 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; логика группировки не меняется.

23 голосов
/ 24 февраля 2014

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

GetWeekOfYear () и концепция в целом предполагают присвоение значений индекса неделям в течение года в соответствии с некоторыми согласованными стандартами. Он не подходит для размещения дат в группах по семь соседних дней, так как я полагаю, что спрашивающий требует.

Мало того, что GetWeekOfYear () будет использоваться не только как предлагаемый результат в группах менее семи дней в конце многих лет, но, что еще хуже, поскольку различные стандарты, поддерживаемые GetWeekOfYear (), будут часто распределяться по первым дням года до последней недели предыдущего года, и, тем не менее, результат GetWeekOfYear () содержит только целочисленный индекс недели без ссылки на связанный год, с группировкой по new { Year = date.Year, weekProjector(date) } или date.Year + "-" + weekProjector(date) в году опрашивающего, с 1 января 2011 года, сгруппированным с Рождество до Нового года двенадцать месяцев спустя того же года .

Таким образом, я бы сказал, что исходный вопрос в основном состоит в том, чтобы спроецировать не на значение недели года, а на неделю всего времени значение, "неделю, начинающуюся с года / м / d "вы могли бы сказать, поэтому группировка должна производиться только к первому дню недели, т. е. (при условии, что вы будете счастливы по умолчанию на воскресенье) просто:

group by date.AddDays(-(int)date.DayOfWeek)
2 голосов
/ 11 июля 2017

В дополнение к ответу 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...