Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I average a DateTime field with a LINQ query?

I have a database that has the following records in a DateTime field:

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

I want to run a linq to sql query to get the average time from the records above. I tried the following:

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

Since "SleepTo" is a datetime field I get an error on Average(). If I was trying to get the average of say an integer, the above linq query works.

What do I need to do to get it to work for datetimes?

like image 374
Jade Avatar asked Apr 13 '12 23:04

Jade


People also ask

How do you find the average in LINQ query?

In LINQ, you can find the average of the given sequence by using the Average method. This method returns the average of the elements present in the given sequence or collection. It returns nullable, non-nullable decimal, double, floats, int, etc. values.

Is LINQ C# slow?

It is slightly slower LINQ syntax is typically less efficient than a foreach loop. It's good to be aware of any performance tradeoff that might occur when you use LINQ to improve the readability of your code. And if you'd like to measure the performance difference, you can use a tool like BenchmarkDotNet to do so.

What is the data type for Linq query?

There is no single datatype for LINQ queries as it depends on the context. In your case you are selecting "Car" so the datatype is going to be IQueryable. As pointed out in the comments you can hold your mouse over any var (not just those involving LINQ queries) to get the datatype.

When should we use LINQ?

LINQ to objects – Allows querying in-memory objects like arrays, lists, generic list and any type of collections. LINQ to XML – Allows querying the XML document by converting the document into XElement objects and then querying using the local execution engine.


2 Answers

Internally, every DateTime is really stored as a number of ticks. The Ticks property of a DateTime is defined as the "number of 100-nanosecond intervals that have elapsed since 12:00:00 midnight, January 1, 0001." (See http://msdn.microsoft.com/en-us/library/system.datetime.ticks.aspx)

You can convert the DateTimes to ticks, then average, then convert back to a datetime.

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

Using your data structures and formatting, it would look like this:

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

If you want to get the average time of each SleepTo value (ignoring the Date component), you can get the ticks of just the time:

var averageTicks = (long)(from o in MYDATA select o.SleepTo.TimeOfDay.Ticks).Average();
var averageTime = new TimeSpan(averageTicks);
like image 118
Duane Theriot Avatar answered Sep 29 '22 09:09

Duane Theriot


Here are a couple extensions methods that can help with this... There is a core problem where if you have a lot of DateTimes in a list the LINQ average of a the ticks (long vars) will overflow.

    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());
    }
like image 22
jocull Avatar answered Sep 29 '22 07:09

jocull