首页 > 解决方案 > 找到重叠的时间间隔并将它们分割成新的时间间隔

问题描述

我需要一些帮助来在 C# 中构建一个算法,该算法需要一个时间间隔列表(开始、结束),找到任何重叠的时间段并在它们的开始/结束处切割它们。然后它需要以“块”的形式合并在一起,以便最终的时间间隔只是一个周期。我会用一张图来说明它。

在此处输入图像描述

到目前为止我的代码。它适用于两个时间间隔,但引入第三个或更多时间间隔,它开始给出奇怪的结果:)

// Dummy objects
        var d1 = new TimeSlot(DateTime.Parse("2020-05-05 13:00 PM"), DateTime.Parse("2020-05-05 13:30 PM"), "1");
        var d3 = new TimeSlot(DateTime.Parse("2020-05-05 13:15 PM"), DateTime.Parse("2020-05-05 13:25 PM"), "2");
        var d2 = new TimeSlot(DateTime.Parse("2020-05-05 13:05 PM"), DateTime.Parse("2020-05-05 13:20 PM"), "3");

        List<TimeSlot> dates = new List<TimeSlot>();
        dates.Add(d1);
        dates.Add(d2);
        dates.Add(d3);

        List<TimeSlot> slicedDates = new List<TimeSlot>();

        IEnumerable<TimeSlot> dateContainer = dates;
        TimeSlot prev = dateContainer.First();
        dateContainer = dateContainer.Skip(1);

        foreach (TimeSlot date in dateContainer.OrderBy(x => x.StartDate))
        {
            var prevStartTime = prev.StartDate;
            var prevEndTime = prev.EndDate;

            if (date.StartDate < prev.EndDate)
            {
                TimeSlot leftSlice = new TimeSlot(prevStartTime, date.StartDate, prev.Name);
                slicedDates.Add(leftSlice);
            }

            if (date.EndDate < prevEndTime)
            {
                TimeSlot middleSlice = new TimeSlot(date.StartDate, date.EndDate, prev.Name + "," + date.Name);
                slicedDates.Add(middleSlice);

                TimeSlot rightSlice = new TimeSlot(date.EndDate, prevEndTime, prev.Name);
                slicedDates.Add(rightSlice);
            }

            prev = date;
        }

并输出三个错误的时间间隔:

05-05-2020 13:00:00 => 05-05-2020 13:05:00: 1
05-05-2020 13:05:00 => 05-05-2020 13:20:00: 1,3
05-05-2020 13:05:00 => 05-05-2020 13:15:00: 3
05-05-2020 13:20:00 => 05-05-2020 13:30:00: 1

标签: c#timeintervals

解决方案


我稍微调整了算法:

        var d1 = new TimeSlot(DateTime.Parse("2020-05-05 13:00 PM"), DateTime.Parse("2020-05-05 13:30 PM"), "1");
        var d3 = new TimeSlot(DateTime.Parse("2020-05-05 13:15 PM"), DateTime.Parse("2020-05-05 13:25 PM"), "2");
        var d2 = new TimeSlot(DateTime.Parse("2020-05-05 13:05 PM"), DateTime.Parse("2020-05-05 13:20 PM"), "3");

        List<TimeSlot> dates = new List<TimeSlot>();
        dates.Add(d1);
        dates.Add(d2);
        dates.Add(d3);

        List<TimeSlot> slicedDates = new List<TimeSlot>();

        IEnumerable<TimeSlot> dateContainer = dates;

        // Created an ordered list of Start & End dates.
        var times = dateContainer.Select(x => x.StartDate);
        times = times.Concat(dateContainer.Select(x => x.EndDate));
        var orderedTimes = times.Distinct().OrderBy(x => x);
        var prev = orderedTimes.First();
        times = orderedTimes.Skip(1);

        foreach (var time in times)
        {
            var names = new List<string>();
            foreach (TimeSlot date in dateContainer)
            {
                // Add the TimeSlot if it's in range
                if (prev >= date.StartDate && time <= date.EndDate)
                {
                    names.Add(date.Name);
                }
            }

            var name = string.Join(",",names);
            TimeSlot slot = new TimeSlot(prev, time, name);
            slicedDates.Add(slot);

            prev = time;
        }

推荐阅读