C# - LINQ - 按日期范围分组集合

时间:2021-03-11 19:02:10

标签: c# asp.net list linq group-by

假设我有以下项目集合:

ID: 1, Date: 10/01/2020 08:00
ID: 2, Date: 10/01/2020 12:00
ID: 3, Date: 10/01/2020 18:00
ID: 4, Date: 11/01/2020 06:00
ID: 5, Date: 11/01/2020 08:00

ID: 6, Date: 11/01/2020 08:01
ID: 7, Date: 11/01/2020 12:00
ID: 8, Date: 12/01/2020 01:00
ID: 9, Date: 12/01/2020 07:00

ID: 10, Date: 12/01/2020 12:00
ID: 11, Date: 12/01/2020 14:00
ID: 12, Date: 12/01/2020 16:00

基于上述集合,我想创建 3 个组,其中包含按时间间隔分组的记录 - 从一小时 08:00 到第二天 07:59:

XX.01.2020 08:00 - XX(+1).01.2020 07:59

输出分组集合应该是这样的

**Group 1 (10.01.2020 08:00 - 11.01.2020 07:59):**
   ID: 1, Date: 10/01/2020 08:00
   ID: 2, Date: 10/01/2020 12:00
   ID: 3, Date: 10/01/2020 18:00
   ID: 4, Date: 11/01/2020 06:00
   ID: 5, Date: 11/01/2020 07:59
**Group 2 (11.01.2020 08:00 - 12.01.2020 07:59):**
   ID: 6, Date: 11/01/2020 08:00
   ID: 7, Date: 11/01/2020 12:00
   ID: 8, Date: 12/01/2020 01:00
   ID: 9, Date: 12/01/2020 07:00
**Group 3 (12.01.2020 08:00 - 13.01.2020 07:59):**
   ID: 10, Date: 12/01/2020 12:00
   ID: 11, Date: 12/01/2020 14:00
   ID: 12, Date: 12/01/2020 16:00

这可以使用 Linq 吗? 提前致谢

2 个答案:

答案 0 :(得分:1)

我不知道你有什么收藏,但假设你有 Dictionary<int, DateTime>

然后你可以像这样分组,如果它在 8 点之后“四舍五入”到当天,如果它在 8 点之前“四舍五入”到前一天:

    var groups = dictionary.GroupBy(x =>
        {
            var dt = x.Value;
            if (dt.Hour >= 8)
                return dt.Date;
            else
                return dt.Subtract(TimeSpan.FromHours(24)).Date;
        });

答案 1 :(得分:0)

您没有指定是否希望它在数据库中运行。

但我认为一种非常简单的方法是减去 8 小时使其成为一整天,您可以将其用作分组的基础:

var result = list.GroupBy(x => x.Date.AddHours(-8).Date);

如果您想获得具有正确“开始”和“结束”日期的分组,就像您似乎指定的那样,您可以将此投影打到最后:

    .Select(g => new {
        From = g.Key.AddHours(8),
        To = g.Key.AddHours(8).AddDays(1),
        Values = g.AsEnumerable()
    });

这可能适用于内存中集合的普通 Linq。如果您在 IQueryable 上运行它,则不会被转换为 SQL(除非我很笨)。

如果你接受另一个答案,如果你觉得更好,那也没关系。 :)