将日期范围拆分为几个特定的​​日期范围块

Split date range into several specific date range chunks

我有具有特定值的日期范围的常规列表:

14.09.2012 - 31.12.2015 = 8.25
01.01.2016 - 13.06.2016 = 11.00
14.06.2016 - 18.09.2016 = 10.50
19.09.2016 - 26.03.2017 = 10.00
27.03.2017 - 01.05.2017 = 9.75
02.05.2017 - 18.06.2017 = 9.25
19.06.2017 - 17.09.2017 = 9.00
18.09.2017 - 29.10.2017 = 8.50
30.10.2017 - 17.12.2017 = 8.25
18.12.2017 - 11.02.2018 = 7.75
12.02.2018 - 25.03.2018 = 7.50
26.03.2018 - 16.09.2018 = 7.25
17.09.2018 - NOW = 7.50

我正在寻找一种将一个输入数据范围划分为上述数据范围并考虑系数值的方法。

例如,如果我输入日期范围 01.01.2016 - 09.02.2016,我需要得到一个输出日期范围和系数:

01.01.2016 - 13.06.2016 = 11.00

但是如果我输入了日期范围 01.01.2016 - 29.04.2017,我需要得到以下范围和系数:

14.09.2012 - 31.12.2015 = 8.25 
01.01.2016 - 13.06.2016 = 11.00 
14.06.2016 - 18.09.2016 = 10.50 
19.09.2016 - 26.03.2017 = 10.00
27.03.2017 - 01.05.2017 = 9.75

Class 输出数据:

public class OutputItem 
{

    public OutputItem()
    {

    }

    public DateTime Start { get; set; } = new DateTime();

    public DateTime End { get; set; } = new DateTime();

    public double Coeff { get; set; } = 0;
}

我尝试获取输出数据的方法

    private List<OutputItem> GetOutput(DateTime start, DateTime end, List<OutputItem> specificRanges)
    {
        List<OutputItem> periods = new List<OutputItem>();

        foreach (OutputItem sr in specificRanges)
        {
            if (start >= sr.Start && sr.End <= end)
            {
                periods.Add(new OutputItem { Start = sr.Start, End = sr.End, Coeff = sr.Coeff });
            }
        }

        return periods;
    }

所以我要在这里走出去并假设在你的第二个例子中开始日期应该在 01-01-2016 之前 - 因为如果我理解这个问题,你正在寻找 return 与您传递给方法的开始到结束时间重叠的所有范围。
如果确实如此,那么你很接近 - 但你的条件是错误的。
测试两个范围是否重叠的方法是检查一个是否在另一个结束之前开始,反之亦然,正如您在 标签的 wiki 中看到的那样:

Two or more elements overlap when they partially or totally cover one another. The way to find if the elements overlap or not is to test if one elements begins before the second one ends, while the second one begins before the first one ends.

所以你的方法应该是:

private List<OutputItem> GetOutput(DateTime start, DateTime end, List<OutputItem> specificRanges)
{
    List<OutputItem> periods = new List<OutputItem>();

    foreach (OutputItem sr in specificRanges)
    {
        if (start >= sr.End && sr.Start <= end)
        {
            periods.Add(new OutputItem { Start = sr.Start, End = sr.End, Coeff = sr.Coeff });
        }
    }

    return periods;
}