如何获取给定集合中所有重叠日期范围的数组?

问题描述 投票:0回答:1

我正在使用 fullcalendar.io JS 库来可视化我的租赁公司的预订。我将摩托车存储为类别数组(发动机尺寸),并使用一个包含属于每个类别的所有摩托车的子数组,如下例所示:

// The resources array contains information about the motorbikes in a rental store.
// The parent array contains the information about the motorbike engine, 
// while the children array contains the information about the unique motorbikes belonging to each engine category.
resources = [{
    id: "scooter50",
    title: "Scooter 50",
    children: [{
            id: "aa123ab",
            title: "AA 123 AB"
        },
        {
            id: "aa456cd",
            title: "AA 456 CD"
        },
        {
            id: "aa789ef",
            title: "AA 789 EF"
        },
        {
            id: "aa101gh",
            title: "AA 101 GH"
        }
    ]
},
{
    id: "scooter125",
    title: "Scooter 125",
    children: [{
            id: "bb123ab",
            title: "BB 123 AB"
        },
        {
            id: "bb456cd",
            title: "BB 456 CD"
        },
        {
            id: "bb789ef",
            title: "BB 789 EF"
        },
        {
            id: "bb101gh",
            title: "BB 101 GH"
        }
    ]
},
{
    id: "scooter250",
    title: "Scooter 250",
    children: [{
            id: "cc123ab",
            title: "CC 123 AB"
        },
        {
            id: "cc456cd",
            title: "CC 456 CD"
        },
        {
            id: "cc789ef",
            title: "CC 789 EF"
        },
        {
            id: "cc101gh",
            title: "CC 101 GH"
        }
    ]
}
];

然后,我有一些属于每个资源的事件(预订):

// The events array contains information about the motorbikes that are rented, including the start and end date of the rental.
events = [{
    start: new Date(2025, 0, 6, 0, 0),
    end: new Date(2025, 0, 9, 23, 59, 59),
    resourceId: "bb101gh",
    title: "Event 0"
},
{
    start: new Date(2025, 0, 11, 0, 0),
    end: new Date(2025, 0, 14, 23, 59, 59),
    resourceId: "bb101gh",
    title: "Event 1"
},
{
    start: new Date(2025, 0, 7, 0, 0),
    end: new Date(2025, 0, 11, 23, 59, 59),
    resourceId: "bb123ab",
    title: "Event 2"
},
{
    start: new Date(2025, 0, 9, 0, 0),
    end: new Date(2025, 0, 14, 23, 59, 59),
    resourceId: "bb456cd",
    title: "Event 3"
},
{
    start: new Date(2025, 0, 7, 0, 0),
    end: new Date(2025, 0, 10, 23, 59, 59),
    resourceId: "bb789ef",
    title: "Event 4"
},
{
    start: new Date(2025, 0, 11, 0, 0),
    end: new Date(2025, 0, 15, 23, 59, 59),
    resourceId: "bb789ef",
    title: "Event 5"
},
{
    start: new Date(2025, 0, 6, 0, 0),
    end: new Date(2025, 0, 15, 23, 59, 59),
    resourceId: "cc101gh",
    title: "Event 6"
},
{
    start: new Date(2025, 0, 8, 0, 0),
    end: new Date(2025, 0, 11, 23, 59, 59),
    resourceId: "cc123ab",
    title: "Event 7"
}
]

这些事件可以在 我的 fullcalendar.io 时间轴图表的屏幕截图中可视化。

每当某个类别中的所有摩托车都已预订满某个时段时,我希望在资源级别上有一些红色背景(示例此处。)这可以通过后台事件轻松实现(https://fullcalendar .io/docs/background-events)。我的问题是,我还没有找到任何方法以可靠且高效的方式存储“n”个资源中预订重叠的日期范围(其中“n”是发动机尺寸类别中的摩托车数量)。

到目前为止,我已经设法找到了一个半工作的解决方案,方法是获取所有事件的最小和最大日期,使用 30 分钟的时间范围迭代它们,并在引擎类别的所有资源都在某个时间预订时存储引擎类别的后台事件。特定时段。这是代码:

// Get the minimum and maximum date in the events array
minDate = events.map(event => event.start).reduce((a, b) => a < b ? a : b);
maxDate = events.map(event => event.end).reduce((a, b) => a > b ? a : b);

// Iterate between the dates using 30 minutes intervals.
unavailableDateRanges = [];
for (let i = minDate; i <= maxDate; i.setMinutes(i.getMinutes() + 30)) {
    // Filter the events that are happening at this time and get the resources that are being used.
    let usedResources = events.filter(event => event.start <= i && event.end >= i).map(event => event.resourceId);

    // If all resources from a certain category are used, store a 30 minutes unavailable range for that category.
    let unavailableCategories = resources.filter(resource => resource.children.every(child => usedResources.includes(child.id))).map(resource => resource.id);
    for (category of unavailableCategories) {
        let start = new Date(i);
        let end = new Date(i);
        end.setMinutes(end.getMinutes() + 30);
        unavailableDateRanges.push({
            start: start,
            end: end,
            resourceId: category,
            title: "Unavailable",
            display: "background"
        });
    }
}

这并不能可靠地达到预期的结果,因为它只检查 30 分钟的间隔,而预订可能会在不同的分钟开始。假设预订从 9:45 开始,此代码不会将 9:45 到 10:00 的时段标记为不可用。由于红色背景在不同的细节级别上都是可见的,这将是一个问题。

由于日期代表连续变量(UNIX),我猜想可以通过父引擎大小类别过滤事件,然后检查哪些日期范围在“n”辆摩托车上有重叠,假设预订某些摩托车不会重叠(我已经确定了)。我尝试编写此解决方案,但没有结果。

我知道有一些库可以处理日期范围,例如 date-fns,但它看起来没有帮助。

有经验的朋友可以帮帮我吗?

javascript arrays performance datetime fullcalendar
1个回答
0
投票

您只需从一个事件跳到另一个事件(一个事件是“预订的开始或结束”),而不需要以 3000 万跳的方式遍历整个时间范围。

因此,您将拥有所有预订开始和结束的时间线,并排序在一起,并且计数器在遇到开始日期时生成 +1,遇到结束日期时生成 -1。当计数器达到 n 时,请出示红旗!

© www.soinside.com 2019 - 2024. All rights reserved.