using System.Collections.Generic;
public static void Main()
new Data{Date=DateTime.Parse("01/01/2019 08:00:00"), Field1=1, Field2=1,Field3=1 },
new Data{Date=DateTime.Parse("01/01/2019 08:15:00"), Field1=1, Field2=1,Field3=1 },
new Data{Date=DateTime.Parse("01/01/2019 08:30:00"), Field1=1, Field2=1,Field3=1 },
new Data{Date=DateTime.Parse("01/01/2019 08:31:00"), Field1=1, Field2=1,Field3=1 }
DateTime RoundUp(DateTime dt, TimeSpan d)
=> new DateTime((dt.Ticks + d.Ticks - 1) / d.Ticks * d.Ticks, dt.Kind);
DateTime RoundDown(DateTime dt, TimeSpan d)
=> new DateTime(dt.Ticks - (dt.Ticks % d.Ticks), dt.Kind);
var interval = TimeSpan.FromMinutes(15);
var rangeMin = RoundDown(input.Min(x => x.Date), interval);
var rangeMax = RoundUp(input.Max(x => x.Date), interval);
var ranges = SplitDateRange(rangeMin, rangeMax, interval).ToList();
var temp = from i in input
var result = temp.GroupBy(x => x.Range)
SumField1 = g.Sum(x => x.Field1),
SumField2 = g.Sum(x => x.Field2),
SumField3 = g.Sum(x => x.Field3)
public static IEnumerable<Range<DateTime>> SplitDateRange(DateTime start, DateTime end, TimeSpan ChunkSize)
while ((chunkEnd = start.Add(ChunkSize)) < end)
yield return new Range<DateTime>(start, chunkEnd);
yield return new Range<DateTime>(start, end);
public DateTime Date { get; set; }
public int Field1 { get; set; }
public int Field2 { get; set; }
public int Field3 { get; set; }
public struct Range<T> where T : IComparable<T>
public Range(T start, T end)
public bool Includes(T value) => Start.CompareTo(value) <= 0 && End.CompareTo(value) >= 0;
public bool Includes(Range<T> range) => Start.CompareTo(range.Start) <= 0 && End.CompareTo(range.End) >= 0;
public override string ToString(){return "{Start : " +Start+ "\tEnd : "+End+"}";}