簡體   English   中英

通過針對主日期范圍使用多個日期范圍來獲取時間跨度

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM