如何使用LINQ查询平均DateTime字段?

时间:2012-04-13 23:19:53

标签: c# linq linq-to-sql

我有一个数据库,它在DateTime字段中包含以下记录:

2012-04-13 08:31:00.000
2012-04-12 07:53:00.000
2012-04-11 07:59:00.000
2012-04-10 08:16:00.000
2012-04-09 15:11:00.000
2012-04-08 08:28:00.000
2012-04-06 08:26:00.000

我想运行linq to sql查询以从上面的记录中获取平均时间。我尝试了以下方法:

(From o In MYDATA Select o.SleepTo).Average()

由于“SleepTo”是一个日期时间字段,我在Average()上得到一个错误。如果我试图得到一个整数的平均值,上面的linq查询就可以了。

我需要做些什么才能让它适用于日期时间?

3 个答案:

答案 0 :(得分:8)

在内部,每个DateTime实际上都存储为多个刻度。 DateTime的Ticks属性定义为“自1月1日午夜12:00:00起经过的100纳秒间隔的数量”。 (见http://msdn.microsoft.com/en-us/library/system.datetime.ticks.aspx

您可以将DateTimes转换为刻度,然后平均,然后转换回日期时间。

var averageTicks = (long) dates.Select(d => d.Ticks).Average();
var averageDate = new DateTime(averageTicks);

使用您的数据结构和格式,它看起来像这样:

var averageTicks = (long)(from o in MYDATA select o.SleepTo.Ticks).Average();
var averageDate = new DateTime(averageTicks);

如果您想获得每个SleepTo值的平均时间(忽略Date组件),您可以获得恰好时间的刻度:

var averageTicks = (long)(from o in MYDATA select o.SleepTo.TimeOfDay.Ticks).Average();
var averageTime = new TimeSpan(averageTicks);

答案 1 :(得分:4)

这里有几个扩展方法可以帮助解决这个问题...有一个核心问题,如果你在列表中有很多DateTimes,那么ticks(long vars)的LINQ平均值会溢出

    public static long Average(this IEnumerable<long> longs)
    {
        long count = longs.Count();
        long mean = 0;
        foreach (var val in longs)
        {
            mean += val / count;
        }
        return mean;
    }

    public static DateTime Average(this IEnumerable<DateTime> dates)
    {
        return new DateTime(dates.Select(x => x.Ticks).Average());
    }

答案 2 :(得分:1)

数据库LINQ提供程序似乎不了解如何在绝对日期执行平均值。如果你考虑一下,这是有意义的(平均值是一个总和除以一个数 - 总和是多少?)。

因此,如果您无法运行以下内容:

(From o In MYDATA Select o.SleepTo).Sum()

然后你也无法.Average()

由于你想要的实际上是SleepTo的平均时间,你需要得到日期的时间成分作为TimeSpan(时间减去午夜)并平均。你有没有机会SleepFrom

与此同时,您可能会发现这篇文章很有启发性:LINQ Average TimeSpan?