I\'m trying to understand how LINQ can be used to group data by intervals of time; and then ideally aggregate each group.
Finding numerous examples with explicit dat
You could round the time stamp to the next boundary (i.e. down to the closest 5 minute boundary in the past) and use that as your grouping:
var groups = series.GroupBy(x =>
{
var stamp = x.timestamp;
stamp = stamp.AddMinutes(-(stamp.Minute % 5));
stamp = stamp.AddMilliseconds(-stamp.Millisecond - 1000 * stamp.Second);
return stamp;
})
.Select(g => new { TimeStamp = g.Key, Value = g.Average(s => s.value) })
.ToList();
Above achieves that by using a modified time stamp in the grouping, which sets the minutes to the previous 5 minute boundary and removes the seconds and milliseconds. The same approach of course can be used for other time periods, i.e. hours and days.
Edit:
Based on this made up sample input:
var series = new List<Sample>();
series.Add(new Sample() { timestamp = DateTime.Now.AddMinutes(3) });
series.Add(new Sample() { timestamp = DateTime.Now.AddMinutes(4) });
series.Add(new Sample() { timestamp = DateTime.Now.AddMinutes(5) });
series.Add(new Sample() { timestamp = DateTime.Now.AddMinutes(6) });
series.Add(new Sample() { timestamp = DateTime.Now.AddMinutes(7) });
series.Add(new Sample() { timestamp = DateTime.Now.AddMinutes(15) });
3 groups were produced for me, one with grouping timestamp 3:05, one with 3:10 and one with 3:20 pm (your results may vary based on current time).
I'd suggest using new DateTime() to avoid any issues with sub millisecond differences
var versionsGroupedByRoundedTimeAndAuthor = db.Versions.GroupBy(g =>
new
{
UserID = g.Author.ID,
Time = RoundUp(g.Timestamp, TimeSpan.FromMinutes(2))
});
With
private DateTime RoundUp(DateTime dt, TimeSpan d)
{
return new DateTime(((dt.Ticks + d.Ticks - 1) / d.Ticks) * d.Ticks);
}
N.B. I am here grouping by Author.ID as well as the rounded TimeStamp.
RoundUp function taken from @dtb answer here https://stackoverflow.com/a/7029464/661584
Read about how equality down to the millisecond doesn't always mean equality here Why does this unit test fail when testing DateTime equality?