-1

I have a List<ObjectInstance>.

The ObjectInstance is a class, which has two TimeSpan attributes: StartTime and EndTimes.

The start and end times can be anywhere between 8am and 10pm. Anytimes after 5pm is off peak time, else it is a peak time.

I need to calculate the total peak time and the total off peak time in the list.

What is the best approach to take to do this?

The way I did was basic really: I wrote functions similar to the one below, which have a lot of if conditions on where the peakTimeStart is, relative to the interval start and end times but I feel there must be a better way to do this; perhaps using LINQ, or some extension methods to call on the list?

public static double CalculateTimeIntervalPeakHours(TimeSpan intervalStart, TimeSpan intervalEnd, TimeSpan peakTimeStart)
{
    double peakHours = 0.0;

    // some logic here to find where the interval starts & ends relative to the peakTimeStart!
    return peakHours;
}
t_plusplus
  • 4,079
  • 5
  • 45
  • 60
  • A `TimeSpan` doesn't have a start time, this makes no sense. Also why tag multiple versions of C#? Which one are you actually using? – DavidG Nov 27 '15 at 17:04
  • @DavidG apologies. I fixed the question's wording now. – t_plusplus Nov 27 '15 at 17:07
  • Even with the edit, a `TimeSpan` doesn't denote a time of day, it is a span of time. – DavidG Nov 27 '15 at 17:08
  • @DavidG I am using it to set a start time and end time of an time interval. I know I could've used DateTime instead but I needed the math benefits of the TimeSpan. – t_plusplus Nov 27 '15 at 17:09
  • But how does a `TimeSpan` indicate a start time? – DavidG Nov 27 '15 at 17:11
  • @DavidG: I think it stores the time from `0:00` for some day. Note that this can cause problems since most countries adapt their clocks for daylight saving time. – Willem Van Onsem Nov 27 '15 at 17:12
  • @t_plusplus: how to handle daylight saving time? Although date and time look simple, these are rather complex concepts to perform arithmetic on. – Willem Van Onsem Nov 27 '15 at 17:13
  • Thanks for the notes - there is no use-case scenario for time saving here. It is merely an interval of time. Deciding whether to use DateTime or TimeSpan was discussed here if you want to have a look: http://stackoverflow.com/questions/1706801/declare-variable-for-just-time http://nodatime.org/1.1.x/api/html/T_NodaTime_Period.htm – t_plusplus Nov 27 '15 at 17:19
  • @t_plusplus But note the [answer](http://stackoverflow.com/a/1706836/1663001) from Jon Skeet suggesting that you should use a `DateTime`. – DavidG Nov 27 '15 at 17:21

3 Answers3

2

I agree with others about using datetime & also considering timezones.

From a technical point of view maybe you r looking for something like this -

 var sumPeak = list.Where(timeSP => timeSP > intervalStart && timeSP < intervalEnd).Sum(item => item.Milliseconds);

incase your logic is more than one line, you can you this syntax -

   var sumPeak = list.Where(timeSP =>
            {
                // consider this a funtion now.
              return  timeSP > intervalStart && timeSP < intervalEnd;
            })
            .Sum(item => item.Milliseconds);

Incase your logic is more than 3-4 lines. I suggest to make a function & call like this -

 var sumPeak = list.Where(timeSP => SelectIntervals(timeSP)).Sum(item => item.Milliseconds);

  private bool SelectIntervals(TimeSpan timeSP)
    {
        throw new NotImplementedException();
    }

Even if you use datetime, such an expression will come handy.

Kapoor
  • 1,388
  • 11
  • 21
2

Assuming your class is something like this

class ObjectInstance
{
    public TimeSpan StartTime, EndTime;
}

where StartTime is the inclusive start of interval, EndTime is the exclusive end of the interval, EndTime > StartTime.

First, let encapsulate Peak/OffPeak logic inside the class

class ObjectInstance
{
    public TimeSpan StartTime, EndTime;
    public TimeSpan PeakTime(TimeSpan peakTimeStart)
    {
        return Fit(peakTimeStart) - StartTime;
    }
    public TimeSpan OffPeakTime(TimeSpan peakTimeStart)
    {
        return EndTime - Fit(peakTimeStart);
    }
    private TimeSpan Fit(TimeSpan value)
    {
        return value < StartTime ? StartTime : value > EndTime ? EndTime : value;
    }
}

Now having

IEnumerable<ObjectInstance> list = ...;
TimeSpan peakTimeStart = ...;

total times can easily be calculated using Enumerable.Aggregate

var totalPeakTime = list.Aggregate(TimeSpan.Zero,
    (total, item) => total + item.PeakTime(peakTimeStart));
var totalOffPeakTime = list.Aggregate(TimeSpan.Zero,
    (total, item) => total + item.OffPeakTime(peakTimeStart));

calculating total hours is even easier

var totalPeakHours = list.Sum(item => item.PeakTime(peakTimeStart).TotalHours);
var totalOffPeakHours = list.Sum(item => item.OffPeakTime(peakTimeStart).TotalHours);
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
-1

A time span is the difference between two DataTime objects. You need to replace TimeSpan with DataTime. DateTime is already in your computer UTC time so nothing is needed to handle daylight savings time. When time is entered into a program or outputted a conversion is made between UTC and local time using the TimeZone setting in the computer. So all the math is computed using the UTC time. If you have a List The total time is the can be calculated by subtracting adjacent indexes in the list and adding each subtraction, but this should give the same time as subtracting the first item in list from

jdweng
  • 33,250
  • 2
  • 15
  • 20