6

我有一个数据库,在 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 查询有效。

我需要做什么才能让它在日期时间工作?

4

3 回答 3

11

在内部,每个 DateTime 实际上都存储为许多滴答声。DateTime的Ticks属性定义为“自 0001 年 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);
于 2012-04-14T21:27:55.673 回答
5

这里有几个可以帮助解决这个问题的扩展方法......有一个核心问题,如果列表中有很多 DateTimes,那么滴答声(longvars )的 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());
    }
于 2013-04-03T15:33:08.750 回答
1

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

因此,如果您无法运行以下命令:

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

那你也做不到.Average()

由于您想要的实际上是 SleepTo 的平均时间,因此您只需将日期的时间部分作为 TimeSpan (时间可能减去午夜)并将其取平均值。你有没有机会SleepFrom

同时,您可能会发现这篇文章很有启发性:LINQ 平均时间跨度?

于 2012-04-13T23:24:42.533 回答