连续重叠多个日期范围C#

时间:2017-09-05 21:29:01

标签: c# date

我正在研究一种算法来计算多个日期范围的连续重叠。它还需要具有重叠的设定次数。对于下面的示例图像,我需要3个日期连续重叠。有效的重叠日期将是8月20日至8月23日,因为8月24日只有2个重叠。

我尝试了很多方法,包括循环所有日期,并将每个日期与下一个日期进行比较。该代码看起来像这样。

这是一个更好的可视化的网络小提琴:https://dotnetfiddle.net/x3LfHR#

    private bool Compare(CompareDate a, CompareDate b)
    {
        DateTime? tStartA = a.ActiveDate;
        DateTime? tEndA = a.ExpireDate;
        DateTime? tStartB = b.ActiveDate;
        DateTime? tEndB= b.ExpireDate;

        bool overlap = (tStartA <= tEndB || tEndB == null) && (tStartB <= tEndA || tEndA == null);

        DateTime? overlapStart = null;
        DateTime? overlapEnd = null;

        if (overlap)
        {
            //Find maximum start date. 
            overlapStart = (tStartA >= tStartB) ? tStartA : tStartB;
            //Find Min End date between the two
            overlapEnd = (tEndA <= tEndB) ? tEndA : tEndB;

            if (overlapStart > this.overlapStart || this.overlapStart == null)
            {
                this.overlapStart = overlapStart;
            }
            if (overlapEnd < this.overlapEnd || this.overlapEnd == null)
            {
                this.overlapEnd = overlapEnd;
            }

然而,这种方法使得确定连续重叠日期变得棘手。我曾尝试在https://www.codeproject.com/Articles/168662/Time-Period-Library-for-NET使用.Net时间段库,但在我的情况下它并不相关。任何帮助表示赞赏。

enter image description here

2 个答案:

答案 0 :(得分:1)

好的 - LINQ救援!

注意:为了使比较起作用,您必须删除时间组件并严格使用唯一的日期(例如DateTime.Date)。根据您的要求,这正是您需要做的,所以它应该不是问题。

public List<DateTime> CompareDates(List<DateTime[]> compareRanges, int overlapLevel = 1)
{
    var grouped = compareRanges.SelectMany(r => r).GroupBy(d => d);
    var thresholdMatch = grouped.Where(g => g.Count() >= overlapLevel)
        .Select(g => g.Key)
        .OrderBy(d => d)
        .ToList();

    return thresholdMatch;
}

您可以使用下面的框架代码作为示例测试示例控制台应用程序中的逻辑:

static void Main()
{
    var setA = new[]
    {
        new DateTime(2017, 8, 20),
        new DateTime(2017, 8, 21),
        new DateTime(2017, 8, 22),      
        new DateTime(2017, 8, 23),      
        new DateTime(2017, 8, 24),
    };

    var setB = new[]
    {
        new DateTime(2017, 8, 20),
        new DateTime(2017, 8, 21),
        new DateTime(2017, 8, 22),
    };

    var setC = new[]
    {
        new DateTime(2017, 8, 22),
        new DateTime(2017, 8, 23),
        new DateTime(2017, 8, 24),
        new DateTime(2017, 8, 25),
        new DateTime(2017, 8, 26),
    };

    var setD = new[]
    {
        new DateTime(2017, 8, 20),
        new DateTime(2017, 8, 21),
        new DateTime(2017, 8, 22),
        new DateTime(2017, 8, 23),
    };

    var compareList = new List<DateTime[]>
    {
        setA, setB, setC, setD
    };

    // setting the threshold to 2 will cause 8/24 to be added to the result...
    // setting this to 1 (default) will return all intersections
    // for now, set it to 3, per the question!
    var result = CompareDates(compareList, 3); 
    foreach (var intersectDate in result)
    {
        Console.WriteLine(intersectDate);
    }
}

希望这会有所帮助,我当然很开心!

P.S。我把你的小提琴分开:https://dotnetfiddle.net/GUzhjh。 这包含原始程序的修改版本,因此您应该可以稍微使用它。

答案 1 :(得分:0)

以下是算法的开始:

  • 对所有开始和结束日期时间进行排序,为每个开始分配+1,为每个开始分配-1。
  • 从interval-start到interval-end,聚合上面的周期分配,寻找+3值。请注意此日期时间。
  • 继续前进,直到您的总值降至+3以下。
  • 瞧! (我想。)记住这个并继续处理。
  • 当第二次发生时,保存最长并丢弃另一个。
  • 继续,直到找到结束间隔;并报告结果。
相关问题