Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从两个可能重叠的日期列表中创建一个没有重叠的日期列表?_C#_List_Datetime - Fatal编程技术网

C# 如何从两个可能重叠的日期列表中创建一个没有重叠的日期列表?

C# 如何从两个可能重叠的日期列表中创建一个没有重叠的日期列表?,c#,list,datetime,C#,List,Datetime,我有两张约会时间表。第一个列表包含所有可用的可能日期范围。第二个列表包含所有不可用的日期范围。我需要创建第三个列表,它是两个列表中所有可能的日期范围及其可用或不可用状态。如果可用列表中存在任何重叠,则日期范围应划分为多个日期范围,以使可用范围不会与不可用日期发生在同一天。在房地产中,如果房子已经不可用,你就不能再租房子,因此可用日期是可用日期范围,任何重叠的不可用日期都会从可用日期中删除部分范围 假设第一个列表的可用日期为: startDate: 1/1/16 endDate: 2/15/16

我有两张约会时间表。第一个列表包含所有可用的可能日期范围。第二个列表包含所有不可用的日期范围。我需要创建第三个列表,它是两个列表中所有可能的日期范围及其可用或不可用状态。如果可用列表中存在任何重叠,则日期范围应划分为多个日期范围,以使可用范围不会与不可用日期发生在同一天。在房地产中,如果房子已经不可用,你就不能再租房子,因此可用日期是可用日期范围,任何重叠的不可用日期都会从可用日期中删除部分范围

假设第一个列表的可用日期为:

startDate: 1/1/16 endDate: 2/15/16
startDate: 2/20/16 endDate: 12/15/16
startDate: 1/1/17 endDate: 12/15/17
startDate: 4/1/19 endDate: 10/15/19
startDate: 2/16/16 endDate: 2/25/16
startDate: 12/1/16 endDate: 12/30/16
startDate: 4/1/17 endDate: 8/15/17
第二个列表的所有不可用日期如下:

startDate: 1/1/16 endDate: 2/15/16
startDate: 2/20/16 endDate: 12/15/16
startDate: 1/1/17 endDate: 12/15/17
startDate: 4/1/19 endDate: 10/15/19
startDate: 2/16/16 endDate: 2/25/16
startDate: 12/1/16 endDate: 12/30/16
startDate: 4/1/17 endDate: 8/15/17
我希望第三个列表的结果是:

startDate: 1/1/16 endDate: 2/15/16 Available
startDate: 2/16/16 endDate: 2/25/16 Unavailable
startDate: 2/26/16 endDate: 11/30/16 Available
startDate: 12/1/16 endDate: 12/30/16 Unavailable
startDate: 1/1/17 endDate: 3/31/17 Available
startDate: 4/1/17 endDate: 8/15/17 Unavailable
startDate: 8/16/17 endDate: 12/15/17 Available
startDate: 4/1/19 endDate: 10/15/19 Available
第二个列表日期根本不应该更改,而第一个列表范围需要在任何重叠的日期周围中断。请注意,2019年的日期没有任何重叠,仍在列表中。我基本上希望看到所有可能发生的日期,同时显示某些时段不可用

如何在C#using List中实现这一点

编辑:有人要求我展示到目前为止我一直在尝试的东西。正如我在评论中提到的,这是我实际问题的简化版本,我不想整天“清理”我的代码供公众使用。因此,我将编写伪代码而不是实际的c#。假设我从两个列表开始,一个是可用日期,一个是占用日期

    var currentDate = first date from available list
    var groupedavailableList = new list

    for i = 1 to count of available list
        If loopavailableDate[i].start_date <= currentDate.EndDate
            If loopavailableDate[i].end_date >= currentDate.EndDate
                currentDate.EndDate = loopavailableDate[i].end_date
       else
            groupedavailableList.Add(currentDate)

            currentDate = loopavailableDate

    //The loop ended, add the last current date
    groupedavailableList.Add(currentDate)

    //Now I have all the available dates grouped together in a bigger block of time (not tested yet). Now we do the part that is the question.

    var finalStatus = new list

    foreach date in groupedavailableList
        var overlapDates = occupiedList.Where(w => (w.StartDate >= date.StartDate && w.StartDate <= date.EndDate) && (w.StartDate <= date.StartDate && w.EndDate >= date.EndDate) &&
                            (w.StartDate <= date.StartDate && w.EndDate <= date.EndDate).ToList()

       If overlapDates.Any()
           //Don't know what to do at this point as there can be multiple over lap dates that break up the available dates.
           Foreach overlap OverlapDates
               If overlap.start_date > date.start_date
                   date.end_date = overl.start_date.AddDays(-1)
                   finalStatus.Add(date with available status)
                   finalStatus.Add(overlap with unavailable status)
                   //Now what? I now have broken the date of the outer loop by changing its end date. If I have two overlaps, I don't know the original period of time to determine if there is an overlap after.The first overlap works but the second in the same period of time doesn't.


        Else
            finalStatus.Add(date with Status available)
var currentDate=可用列表中的第一个日期
var groupedavailableList=新列表
对于i=1,以计数可用列表
如果loopavailableDate[i]。开始日期=currentDate.EndDate
currentDate.EndDate=loopavailableDate[i]。结束日期
其他的
groupedavailableList.Add(当前日期)
currentDate=loopavailableDate
//循环结束后,添加上一个当前日期
groupedavailableList.Add(当前日期)
//现在,我将所有可用的日期组合在一个更大的时间块中(尚未测试)。现在我们做问题的部分。
var finalStatus=新列表
groupedavailableList中的每个日期

var overlappates=occupiedList.Where(w=>(w.StartDate>=date.StartDate&&w.StartDate我的方法是创建一个包含可用和不可用时间范围的单一时间线,然后创建一个小型状态机来使用此时间线并吐出所有可用时间范围

我遇到的陷阱是假设第一个日期是一个可用的日期

public enum EventType
{
    AvailableBegin,
    AvailableEnd,
    UnavailableBegin,
    UnavailableEnd
}

public class Event
{
    public DateTime Date;
    public EventType Type;
}

public class TimeRange
{
    public DateTime Start;
    public DateTime End;
}

[TestMethod]
public void q41029109single()
{
    var availabilties = new List<TimeRange> {
        new TimeRange { Start = new DateTime(2016, 1, 1), End = new DateTime(2016, 2, 15) },
        new TimeRange { Start = new DateTime(2016, 2, 20), End = new DateTime(2016, 12, 15) }
    };
    var unavailabilities = new List<TimeRange> {
        new TimeRange { Start = new DateTime(2016, 2, 16), End = new DateTime(2016, 2, 25) }
    };

    var timeline = new List<Event>();
    foreach (var availability in availabilties)
    {
        timeline.Add(new Event { Date = availability.Start, Type = EventType.AvailableBegin });
        timeline.Add(new Event { Date = availability.End, Type = EventType.AvailableEnd });
    }
    foreach (var unavailability in unavailabilities)
    {
        timeline.Add(new Event { Date = unavailability.Start, Type = EventType.UnavailableBegin });
        timeline.Add(new Event { Date = unavailability.End, Type = EventType.UnavailableEnd });
    }

    var result = new List<TimeRange>();
    TimeRange currentAvailability = null;
    var insideUnavailable = false;
    var insideAvailable = false;
    foreach (var oneEvent in timeline.OrderBy(x => x.Date))
    {
        switch (oneEvent.Type)
        {
            case EventType.AvailableBegin:
                insideAvailable = true;
                if (insideUnavailable == false)
                {
                    currentAvailability = new TimeRange { Start = oneEvent.Date };
                }
                break;
            case EventType.AvailableEnd:
                insideAvailable = false;
                if (insideUnavailable == false && currentAvailability != null)
                {
                    currentAvailability.End = oneEvent.Date;
                    result.Add(currentAvailability);
                }
                break;
            case EventType.UnavailableBegin:
                insideUnavailable = true;
                if (insideAvailable && currentAvailability != null)
                {
                    currentAvailability.End = oneEvent.Date;
                    result.Add(currentAvailability);
                }
                break;
            case EventType.UnavailableEnd:
                insideUnavailable = false;
                if (insideAvailable)
                {
                    currentAvailability = new TimeRange { Start = oneEvent.Date.AddDays(1) };
                }
                break;
            default:
                break;
        }
    }

    //result should be good here.
}
公共枚举事件类型
{
有效的,
有效的,
不可用开始,
无效端
}
公开课活动
{
公共日期时间日期;
公共事件类型;
}
公共类时间范围
{
公共日期时间开始;
公共日期时间结束;
}
[测试方法]
公开作废Q41029Single()
{
var Availabilities=新列表{
新的时间范围{Start=new DateTime(2016,1,1),End=new DateTime(2016,2,15)},
新的时间范围{开始=新的日期时间(2016,2,20),结束=新的日期时间(2016,12,15)}
};
var不可用性=新列表{
新的时间范围{开始=新的日期时间(2016,2,16),结束=新的日期时间(2016,2,25)}
};
var timeline=新列表();
foreach(可用性中的var可用性)
{
添加(新事件{Date=availability.Start,Type=EventType.availabilebegin});
添加(新事件{Date=availability.End,Type=EventType.AvailableEnd});
}
foreach(不可用中的var不可用)
{
添加(新事件{Date=unavailability.Start,Type=EventType.UnavailableBegin});
添加(新事件{Date=unavailability.End,Type=EventType.UnavailableEnd});
}
var result=新列表();
时间范围currentAvailability=null;
var InsideuNavaailable=假;
var insideAvailable=假;
foreach(timeline.OrderBy(x=>x.Date)中的var oneEvent)
{
开关(oneEvent.Type)
{
案例EventType.AvailableBegin:
insideAvailable=true;
如果(InsideuNavaailable==false)
{
currentAvailability=新时间范围{Start=oneEvent.Date};
}
打破
案例EventType.AvailableEnd:
insideAvailable=假;
if(insideUnavailable==false&¤tAvailability!=null)
{
currentAvailability.End=oneEvent.Date;
结果。添加(当前可用性);
}
打破
案例EventType.UnavailableBegin:
InsideuNavaailable=真;
if(insideAvailable&¤tAvailability!=null)
{
currentAvailability.End=oneEvent.Date;
结果。添加(当前可用性);
}
打破
案例EventType.UnavailableEnd:
InsideuNavaailable=假;
如果(内部可用)
{
currentAvailability=新时间范围{Start=oneEvent.Date.AddDays(1)};
}
打破
违约:
打破
}
}
//结果应该是好的。
}
请注意,此代码假设可用时间范围的列表不与自身重叠。同样,如果不可用列表与自身重叠,它将破坏状态机。清理列表以确保没有内部重叠应该是一件小事。如果不重叠,请告诉我。

什么是“弯曲”关于第二个列表?您是否只想按
startDate排序