C
C#2y ago
PatrickG

❔ Get a sum of timespans but only counting overlapping time zones once

Hello I have a problem at my job where I have a list of timespans and I need know the total hours of these timespans but while only counting any overlapping regions once. So for example if I have (7am-10am) + (8am-11am) I would only get a total of 4 hours. if I have (8am-10am) + (8am-11am) i would only get 3 hours if i have (7am-7pm) + (8am - 9 aM) + (9am - 10 aM) + (10am - 11 aM) + (10pm - 11 pm) i would only get 13hours
7 Replies
mtreit
mtreit2y ago
A TimeSpan is simply a length of time. It has no actual wall-clock time associated with it. Your question title also mentions time zones but that doesn't seem to be part of the problem as you described it. Perhaps you can show an example input using actual C# types and the desired output (also in C# types) Your problem description implies something like a List of pairs of DateTime objects or something.
PatrickG
PatrickG2y ago
yes sorry, I used wrong terms. I have a list of objects that have attribute BeginTime and EndTime. I want to calculate the sum of (EndTime-BeginTime) which is what I was calling a timespan for a lack of better word. And in my sum , I do not want to count any period that is overlapping more than once. To be clear, this has nothing to do with time zones, it is just the term I came up with to describe a region of a time interval that would overlap with an other one. I can give a more concrete example. If I have a machine and everytime a user uses it, it generates an entry in a db with begin time and end time, and multiple users can use the machine at once, I want to know how many hours the machine was in-use during the day. but if it was in use by multiple user at once im not counting that time twice.
mtreit
mtreit2y ago
Haven't really thought it through but sounds like you could just sort them, walk the list and merge overlapping smaller ranges into larger ranges and then just sum the total time of all of the merged ranges.
PatrickG
PatrickG2y ago
yea that seems to make sense
mtreit
mtreit2y ago
You can have two pointers - one is the "current" range you are working with, the second walks the rest of the ranges to find those that overlap with "current". The current pointer increments as soon as you find a range whose start time is greater than current's end time (since they are sorted, you now know there is no other range that could possibly overlap.) Probably some details and edge cases in there but I would probably try something along those lines. You can keep adjusting the end of the current "merged" range by taking the Math.Max of the end time of two ranges known to overlap.
PatrickG
PatrickG2y ago
actually while i was waiting for answers i asked chat GPT and it gave me this which sounds a lot like what you describe: public static int TotalHours(Timespan[] timespans) { Array.Sort(timespans, (x, y) => x.Start - y.Start); int total = 0; for (int i = 0; i < timespans.Length; i++) { int start = timespans[i].Start; int end = timespans[i].End; // check for overlapping timespans while (i + 1 < timespans.Length && timespans[i + 1].Start < end) { i++; end = Math.Max(end, timespans[i].End); } total += end - start; } return total; } gonna try to plug this in at work tomorrow thanks note : in that exemple timespan is just an custom class with begintime and endtime
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.