[英]Getting a timespan by using multiple date ranges against a main date range
我需要通過比較主開始和結束日期時間與多個“忽略”開始和結束日期時間對來找出“有效”時間跨度。
這些“忽略”對可以有任意數量,它們的范圍可以介於甚至完全覆蓋初始的“開始”和“結束日期時間”對之間。
下面是示例輸入和預期輸出(現在使用簡單的時間表示):
例子1
Main Start: 04:00
Main End : 14:00
Ignore Pair 1: 03:00 - 06:00
Ignore Pair 2: 05:00 - 09:00
Ignore Pair 3: 12:00 - 13:00
Expected Result: Timespan(4 'Valid' Hours)
例子2
Main Start: 04:00
Main End : 14:00
Ignore Pair 1: 03:00 - 12:00
Expected Result: Timespan(2 'Valid' Hours)
例子3
Main Start: 04:00
Main End : 14:00
Ignore Pair 1: 03:00 - 20:00
Expected Result: Timespan(0 'Valid' Hours)
例子4
Main Start: 04:00
Main End : 14:00
Ignore Pair 1: 08:00 - 12:00
Expected Result: Timespan(6 'Valid' Hours)
抱歉,如果沒有什么要說的,請讓我知道是否需要進一步的說明。
這應該為您提供有效范圍的列表。 這是沒有優化的第一筆簡單的草稿。 該代碼應在注釋中說明自己。 如果要獲取“有效”時間,只需使用Console.WriteLine("{0} valid hours", valid.Sum(r => (r.End - r.Start).TotalHours));
在結果中添加范圍Console.WriteLine("{0} valid hours", valid.Sum(r => (r.End - r.Start).TotalHours));
它是根據以下假設進行編碼的:范圍已驗證(開始<結束)!
用於存儲時間范圍的類:
class TimeRange
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
public TimeRange ()
{
}
public TimeRange(TimeSpan todayStart, TimeSpan todayEnd)
{
Start = DateTime.Today + todayStart;
End = DateTime.Today + todayEnd;
}
}
Testcode:
static void Main(string[] args)
{
var main = new TimeRange(new TimeSpan(4, 0, 0), new TimeSpan(14, 0, 0));
var except = new List<TimeRange>{
new TimeRange(new TimeSpan(3, 0, 0), new TimeSpan(6, 0, 0)),
new TimeRange(new TimeSpan(5, 0, 0), new TimeSpan(9, 0, 0)),
new TimeRange(new TimeSpan(12, 0, 0), new TimeSpan(13, 0, 0))
};
var valid = GetFreeSlots(main, except);
}
算法:
private static List<TimeRange> GetFreeSlots(TimeRange main, List<TimeRange> except)
{
// 1. ignore Ranges outside
except = except.Where(e => main.Start < e.End && main.End > e.Start).ToList();
// 2. shrink the main timerange from overlapping ranges
while (true)
{
var x = except.FirstOrDefault(e => e.Start <= main.Start);
if (x != null)
{
if (x.End >= main.End)
{
return new List<TimeRange>();
}
main.Start = x.End;
except.Remove(x);
}
else
break;
}
while (true)
{
var x = except.FirstOrDefault(e => e.End >= main.End);
if (x != null)
{
main.End = x.Start;
except.Remove(x);
}
else
break;
}
if (!except.Any())
{
return new List<TimeRange> { main };
}
// 3. add range[start main to start of the 1. exception] to the list of valid ranges and shrink the main time range to start = end of the 1. exception and go through the procedure again
except.OrderBy(e => e.Start);
var valid = new List<TimeRange>{new TimeRange{Start = main.Start, End = except[0].Start}};
main.Start = except[0].End;
except.RemoveAt(0);
return valid.Union(GetFreeSlots(main, except)).ToList();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.