LINQ 时间分组高级用法(二)

我来介绍一些 LINQ 中关于时间分组的高级用法和常见场景。

using System;
using System.Linq;
using System.Collections.Generic;

public class Order
{
    public int Id { get; set; }
    public DateTime OrderTime { get; set; }
    public decimal Amount { get; set; }
}

public class Program
{
    public static void Main()
    {
        // 示例数据
        var orders = new List<Order>
        {
            new Order { Id = 1, OrderTime = new DateTime(2024, 1, 1, 10, 30, 0), Amount = 100 },
            new Order { Id = 2, OrderTime = new DateTime(2024, 1, 1, 14, 20, 0), Amount = 200 },
            new Order { Id = 3, OrderTime = new DateTime(2024, 1, 2, 9, 15, 0), Amount = 150 },
            new Order { Id = 4, OrderTime = new DateTime(2024, 2, 1, 11, 45, 0), Amount = 300 }
        };

        // 1. 按天分组
        var dailyGroups = orders.GroupBy(o => o.OrderTime.Date)
                               .Select(g => new
                               {
                                   Date = g.Key,
                                   Orders = g.ToList(),
                                   TotalAmount = g.Sum(o => o.Amount)
                               });

        // 2. 按月分组
        var monthlyGroups = orders.GroupBy(o => new { o.OrderTime.Year, o.OrderTime.Month })
                                 .Select(g => new
                                 {
                                     Year = g.Key.Year,
                                     Month = g.Key.Month,
                                     Orders = g.ToList(),
                                     TotalAmount = g.Sum(o => o.Amount)
                                 });

        // 3. 按小时段分组(例如:按4小时一段)
        var hourlyGroups = orders.GroupBy(o => new 
        { 
            Date = o.OrderTime.Date,
            TimeSlot = o.OrderTime.Hour / 4
        })
        .Select(g => new
        {
            Date = g.Key.Date,
            TimeSlot = $"{g.Key.TimeSlot * 4:D2}:00-{(g.Key.TimeSlot + 1) * 4:D2}:00",
            Orders = g.ToList(),
            TotalAmount = g.Sum(o => o.Amount)
        });

        // 4. 按周分组
        var weeklyGroups = orders.GroupBy(o => new 
        { 
            Year = o.OrderTime.Year,
            Week = GetIso8601WeekOfYear(o.OrderTime)
        })
        .Select(g => new
        {
            Year = g.Key.Year,
            Week = g.Key.Week,
            Orders = g.ToList(),
            TotalAmount = g.Sum(o => o.Amount)
        });

        // 5. 按季度分组
        var quarterlyGroups = orders.GroupBy(o => new 
        { 
            o.OrderTime.Year,
            Quarter = (o.OrderTime.Month - 1) / 3 + 1 
        })
        .Select(g => new
        {
            Year = g.Key.Year,
            Quarter = g.Key.Quarter,
            Orders = g.ToList(),
            TotalAmount = g.Sum(o => o.Amount)
        });

        // 6. 动态时间窗口分组(例如:每30分钟一组)
        var windowSize = TimeSpan.FromMinutes(30);
        var timeWindowGroups = orders.GroupBy(o => 
            new DateTime(o.OrderTime.Ticks - (o.OrderTime.Ticks % windowSize.Ticks)))
        .Select(g => new
        {
            WindowStart = g.Key,
            WindowEnd = g.Key.Add(windowSize),
            Orders = g.ToList(),
            TotalAmount = g.Sum(o => o.Amount)
        });
    }

    // 计算ISO 8601周数的辅助方法
    private static int GetIso8601WeekOfYear(DateTime date)
    {
        var thursday = date.AddDays(3 - ((int)date.DayOfWeek + 6) % 7);
        return (thursday.DayOfYear - 1) / 7 + 1;
    }
}

这个代码示例展示了多种 LINQ 时间分组的高级用法:

  1. 按天分组

    • 使用 Date 属性去除时间部分
    • 适合统计每日订单总量、销售额等
  2. 按月分组

    • 使用匿名类型组合年份和月份
    • 避免不同年份同月混在一起
  3. 按时间段分组

    • 将24小时划分为多个时间段
    • 适合分析业务高峰期
  4. 按周分组

    • 使用 ISO 8601 标准计算周数
    • 适合周报表生成
  5. 按季度分组

    • 通过月份计算季度
    • 适合季度报表
  6. 动态时间窗口

    • 自定义时间间隔
    • 适合实时数据分析

你可以根据业务需求选择合适的分组方式。每种分组方法都包含了:

  • 分组键的定义
  • 结果的投影
  • 聚合计算(如总金额)

需要注意的是:

  1. 时区处理:实际应用中需要考虑时区转换
  2. 性能优化:大数据量时考虑添加适当的索引
  3. 内存使用:注意 ToList() 的使用时机
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值