Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sum of TimeSpans in C#

Tags:

c#

linq

timespan

I have a collection of objects that include a TimeSpan variable:

MyObject {      TimeSpan TheDuration { get; set; } } 

I want to use LINQ to sum those times. Of course, (from r in MyCollection select r.TheDuration).Sum(); doesn't work!

I'm thinking of changing the datatype of TheDuration to an int and then summing it and converting the sum to a TimeSpan. That will be messy because each TheDuration in my collection is used in as a timespan somewhere else.

Any suggestion on this summation?

like image 948
frenchie Avatar asked Jan 16 '11 00:01

frenchie


People also ask

How do you add two Timespans?

This C# program is used to add two timespan using 's1' and 's2' variables respectively. Here the two timespans are added using 's3' variable, returns a new TimeSpan object whose value is the sum of the specified TimeSpan object and this instance. Sanfoundry Global Education & Learning Series – 1000 C# Programs.

How to sum TimeSpan in list c#?

It should be var totalSpan = new TimeSpan(myCollection. Sum(r => r. Ticks)); in case if myCollection is List<TimeSpan>() .


2 Answers

Unfortunately, there isn't a an overload of Sum that accepts an IEnumerable<TimeSpan>. Additionally, there's no current way of specifying operator-based generic constraints for type-parameters, so even though TimeSpan is "natively" summable, that fact can't be picked up easily by generic code.

One option would be to, as you say, sum up an integral-type equivalent to the timespan instead, and then turn that sum into a TimeSpan again. The ideal property for this is TimeSpan.Ticks, which round-trips accurately. But it's not necessary to change the property-type on your class at all; you can just project:

var totalSpan = new TimeSpan(myCollection.Sum(r => r.TheDuration.Ticks)); 

Alternatively, if you want to stick to the TimeSpan's + operator to do the summing, you can use the Aggregate operator:

var totalSpan = myCollection.Aggregate                 (TimeSpan.Zero,                  (sumSoFar, nextMyObject) => sumSoFar + nextMyObject.TheDuration); 
like image 82
Ani Avatar answered Sep 23 '22 11:09

Ani


This works well (code based on Ani's answer)

public static class StatisticExtensions {         public static TimeSpan Sum<TSource>(this IEnumerable<TSource> source, Func<TSource, TimeSpan> selector)     {         return source.Select(selector).Aggregate(TimeSpan.Zero, (t1, t2) => t1 + t2);     } } 

Usage :

If Periods is a list of objects with a Duration property

TimeSpan total = Periods.Sum(s => s.Duration) 
like image 27
grantnz Avatar answered Sep 22 '22 11:09

grantnz