-1

Let's say I have two timespan ranges

07.00.00 - 18.59.59
19.00.00 - 06.59.59

Now i have a timespan range, let's call it a duration.

public class Duration {
  public TimeSpan StartingTime{get; set;}
  public TimeSpan EndingTime{get; set;}
}

Which is initialized as

StartingTime 05.00.00
EndingTime 06.00.00

I would like to generate a method where i Pass in the list of timespan ranges, and a new Timespan, where it would return me a correct timespan range.

I have tried modifying Check if a date range is within a date range for TimeSpan, also, tried to convert my timespan ranges to datetime, but it resulted in fail (returning nothing).

Also I've tried going with

var fee = fees.Where(a=> parking.StartTime <= a.EndingTime && parking.EndTime >= a.StartingTime).First();

Where parking would be the duration class, and fees would be a list of timespan ranges.

Also I've looked at c# check if a timespan range is between timespan range and how many hours but this did not result in working solution either.

I am quite frustrated already, and could not think out a solution.

EDIT: Taking example of @NetMage there was a case where 19.40 - 20.35 would result in fail, which I fixed adding another condition.

var fee = fees
                .First(r => (r.StartingTime <= r.EndingTime) ?
                        (r.StartingTime <= parking.StartTime && parking.StartTime <= r.EndingTime) :
                        (parking.StartTime <= r.EndingTime) ?
                        (r.StartingTime <= parking.StartTime + oneDay && parking.StartTime <= r.EndingTime)
                        : (r.StartingTime <= parking.StartTime + oneDay && parking.StartTime <= r.EndingTime + oneDay)
                        );

EDIT2//

Now I am still having problems with checking the overlap from endTime. Tried using the method that NetMage told, but so far nothing

EDIT3//

To check for the ending part it would be

fees.First(r => (r.StartingTime <= r.EndingTime) ?
                        (r.EndingTime >= end && end >= r.StartingTime) :
                        (end >= r.StartingTime) ?
                        (r.EndingTime >= end + oneDay && end >= r.StartingTime) :
                        (r.EndingTime >= end + oneDay && end >= r.StartingTime + oneDay)
                        );

And Finally to check wether it overlaps both ways:

fees.First(r => r.StartingTime >= start && r.EndingTime <= end);
Egert Aia
  • 459
  • 2
  • 12
  • Can you post your model for fees? – David Lee Sep 11 '17 at 18:42
  • And does your parking variable implement the Duration model? – David Lee Sep 11 '17 at 18:45
  • Also confused as to exactly what type of output you are looking for. Is it any fee that is outside or the specified range or is it for any fee that is within the specified range? – David Lee Sep 11 '17 at 18:48
  • Um, why did you implement duration during TimeSpans and not DateTimes? Better yet, why have a duration class at all, and not just use one TimeSpan? – stelioslogothetis Sep 11 '17 at 18:57
  • Can you give an example of inputs and expected outputs please? – Yair Halberstadt Sep 11 '17 at 19:01
  • @stybl. A dateTime has to be different for every day. He may not care about the day. Also a TimeSpan doesn't specify when the timespan starts, only its length. – Yair Halberstadt Sep 11 '17 at 19:02
  • Exactly. I don't care about the date, just the timeranges. my model for fees is List of durations. The parking is actually the duration, with some extra information that i don't care about in that scope. @DavidLee Within the specified range is it possible to have timespan as a range? – Egert Aia Sep 11 '17 at 19:08
  • Egert uses the TimeSpan in the same meaning as property TimeSpan.TimeOfDay does, namely: the fraction of the day that has elapsed since midnight – Harald Coppoolse Sep 11 '17 at 19:57
  • Can you edit your question to define "correct timespan range" in detail? Also, what is a "list of timespan ranges" - is it `List` ? – NetMage Sep 11 '17 at 19:57
  • I think you should define three ranges, all together covering one day: 00:00 - 6:59:56, 07:00:00-18.59.59, 19.00.00 - 23:59:59, because you can't easily work with timespan ranges if they cross midnight. – Gert Arnold Sep 11 '17 at 20:09
  • It is not very obvious what the hangup could be, you did not show any attempt at making it work. The classic mistake is not accounting for midnight being in the interval. So, say, a start time of 8 o'clock in the evening and an end time of 4 o'clock in the morning. You have to add 24. – Hans Passant Sep 11 '17 at 21:56

2 Answers2

1

Assuming your list of time ranges is a List<Duration>, you can query like so:

var OneDay = new TimeSpan(24,0,0);

var startAns = ranges.First(r => {
    var rEndingTime = (r.StartingTime > r.EndingTime) ? r.EndingTime + OneDay : r.EndingTime;
    return (r.StartingTime <= parking.StartingTime && parking.StartingTime <= rEndingTime) ||
           (r.StartingTime <= parking.StartingTime + OneDay && parking.StartingTime + OneDay <= rEndingTime);
});

var endAns = ranges.First(r => {
    var rEndingTime = (r.StartingTime > r.EndingTime) ? r.EndingTime + OneDay : r.EndingTime;
    return (r.StartingTime <= parking.EndingTime && parking.EndingTime <= rEndingTime) ||
           (r.StartingTime <= parking.EndingTime + OneDay && parking.EndingTime + OneDay <= rEndingTime);
});

I replaced the original (conceptually) Let based answer below with the above ones, also using the nice First variant the OP used.

var ans = ranges.Select(r => new { r, r.StartingTime, EndingTime = (r.StartingTime > r.EndingTime ? r.EndingTime + OneDay : r.EndingTime)})
                .Where(r => (r.StartingTime <= parking.StartingTime && parking.StartingTime <= r.EndingTime) ||
                            (r.StartingTime <= parking.StartingTime+OneDay && parking.StartingTime+OneDay <= r.EndingTime))
                .Select(r => r.r).First();
NetMage
  • 26,163
  • 3
  • 34
  • 55
  • Hello @NetMage This is quite good solution, but this fails in case when the time is for example 19:40 – 20:35 . This is because condition parking.StartTime <= r.EndingTime is false (StartTime is 19:40 whereas EndingTime is 06.59.59. Perhaps we should create another condition in there? – Egert Aia Sep 12 '17 at 17:59
  • If Possible, could you help me think out the similar thing for end time overlap as well. – Egert Aia Sep 12 '17 at 18:23
  • You are correct, the optimize version doesn't work in all cases. I added the expression for `parking.EndingTime`. – NetMage Sep 12 '17 at 19:00
0

Updated to resolve issue with period rollover to next day

Using TimeSpan is quite neat for this purpose, but in the case where a period rolls into the next day, this would make the query quite complex and unwieldy.

This can be easily resolved, by splitting the Period that covers two days into two Periods as follows:

00.00.00 - 06.59.59 //off peak 1
07.00.00 - 18.59.59 //peak
19.00.00 - 23.59.59 //off peak 2

In your example you have two possible cases that you need to handle:

  1. Parking duration is entirely in one Fee period - which your query handles.
  2. Parking duration overlaps two (or more periods) - your query will not match any results for this and will crash because you're using .First()

To get more accurate answers you'll need to specify what your required behaviour should be. On the off chance that these might be suitable, here are two possibilities:

This query will return the Fee period that the Parking starts in:

var fee = fees.Where(period => parking.StartTime >= period.StartingTime && parking.StartTime <= period.EndingTime).First();

This query will return the Fee period that the Parking ends in:

var fee = fees.Where(period => parking.EndTime >= period.StartingTime && parking.EndTime <= period.EndingTime).First();

Steve Land
  • 4,852
  • 2
  • 17
  • 36
  • The starting part is exactly what I was looking for. Cheers. EDIT// on second look. It still fails, because in that case it should fall into the range of 19.00.00 - 06.59.59. But as startingTime 05.00.00 for example is not bigger than period startingtime (19.00.00) this still returns an error. – Egert Aia Sep 11 '17 at 19:29
  • @EgertAia Your range confuses me. You have it starting at 19 and ending at 7. How can your starting period be greater than your ending period? Is this because it goes into the next day? – David Lee Sep 11 '17 at 20:01
  • @EgertAia I see - answer updated with my suggestion to resolve that. It could be done with a query, but I think this is a better solution. – Steve Land Sep 11 '17 at 20:49