根据日期+持续时间(分钟)对数组(gantt时间表)进行排序-带有静态中断(日期+持续期)



我有一个基于gantt时间表的数组。数组包含具有以下属性的对象

{
id: string;
startTime: Date;
durationEstimated: number;
isBreak: boolean;
}

以及一些通用值。基于这些值,我需要循环遍历数组,并根据以前的值对startTime进行排序/更新。在这样做的时候,我还需要考虑"isBreak"(静态值–startTime/durationEstimated从未改变(

例如,假设我有这个数组:

[ 
{id: '1', startTime: "2020-04-01T08:30:00", durationEstimated: 60, isBreak: false},
{id: '2', startTime: "2020-04-01T09:00:00", durationEstimated: 15, isBreak: true},
{id: '3', startTime: "2020-04-01T09:45:00", durationEstimated: 60, isBreak: false},
{id: '4', startTime: "2020-04-01T10:45:00", durationEstimated: 60, isBreak: false},
{id: '5', startTime: "2020-04-01T11:45:00", durationEstimated: 60, isBreak: false},
{id: '6', startTime: "2020-04-01T12:00:00", durationEstimated: 60, isBreak: true},
{id: '7', startTime: "2020-04-01T13:45:00", durationEstimated: 60, isBreak: false}
] 

第一个项目(id='1'(将运行30分钟。然后中断(id='2'(15分钟,最后30分钟结束,然后开始下一个。(新项目永远不会添加到位置0(

假设我需要在此添加另一个对象(开始时间无关(

{id: '8', startTime: "2022-05-01T14:30:00", durationEstimated: 60, isBreak: false} 

我把它推到位置1的数组中,然后数组看起来像这样:

[ 
{id: '1', startTime: "2020-04-01T09:30:00", durationEstimated: 60, isBreak: false}, 
{id: '8', startTime: "2022-05-01T14:30:00", durationEstimated: 60, isBreak: false} 
{id: '2', startTime: "2020-04-01T09:00:00", durationEstimated: 15, isBreak: true}, 
{id: '3', startTime: "2020-04-01T09:45:00", durationEstimated: 60, isBreak: false}, 
{id: '4', startTime: "2020-04-01T10:45:00", durationEstimated: 60, isBreak: false},
{id: '5', startTime: "2020-04-01T11:45:00", durationEstimated: 60, isBreak: false},
{id: '6', startTime: "2020-04-01T12:00:00", durationEstimated: 60, isBreak: true},
{id: '7', startTime: "2020-04-01T13:45:00", durationEstimated: 60, isBreak: false}
] 

这就是我想要开始排序和更新第一个元素之后所有元素的startTime的地方。因此,它应该将物品转移到可容纳的休息时间。

预期结果:

[ 
{id: '1', startTime: "2020-04-01T08:30:00", durationEstimated: 60, isBreak: false}, 
{id: '2', startTime: "2020-04-01T09:00:00", durationEstimated: 15, isBreak: true}, 
{id: '8', startTime: "2020-04-01T09:45:00", durationEstimated: 60, isBreak: false},
{id: '3', startTime: "2020-04-01T10:45:00", durationEstimated: 60, isBreak: false}, 
{id: '4', startTime: "2020-04-01T11:45:00", durationEstimated: 60, isBreak: false},
{id: '6', startTime: "2020-04-01T12:00:00", durationEstimated: 60, isBreak: true},
{id: '5', startTime: "2020-04-01T13:45:00", durationEstimated: 60, isBreak: false},
{id: '7', startTime: "2020-04-01T14:45:00", durationEstimated: 60, isBreak: false}
] 

实际数组大约有60-80行长,包含多个break+diffrent durationEstimated值。

已尝试

当我不得不在数组中移动项目以计算中断时间时,我总是会遇到问题。

我的想法是循环遍历数组,检查每个项目,将其与上一个项目进行比较(startTime+duration(,并将新日期添加到当前迭代项目startTime。然后仔细检查每一个项目。问题是,当中断发生时,它们是静态的,永远不会更新。

如果你只在数组的最后一个位置添加新项,Iv'e就可以工作了(因为我不需要排序,只能检查以前的值(。但在实际应用程序中,任何位置都会添加新项目

不知道如何将其转换为JavaScript,但我认为我有一个用Python编写的解决方案,它似乎正在运行。

import datetime, json
data = [ 
{'id': '1', 'startTime': "2020-04-01T08:30:00", 'durationEstimated': 60, 'isBreak': False},
{'id': '2', 'startTime': "2020-04-01T09:00:00", 'durationEstimated': 15, 'isBreak': True},
{'id': '3', 'startTime': "2020-04-01T09:45:00", 'durationEstimated': 60, 'isBreak': False},
{'id': '4', 'startTime': "2020-04-01T10:45:00", 'durationEstimated': 60, 'isBreak': False},
{'id': '5', 'startTime': "2020-04-01T11:45:00", 'durationEstimated': 60, 'isBreak': False},
{'id': '6', 'startTime': "2020-04-01T12:00:00", 'durationEstimated': 60, 'isBreak': True},
{'id': '7', 'startTime': "2020-04-01T13:45:00", 'durationEstimated': 60, 'isBreak': False}
]
new_data = []
original_data_in_dict_form = {}
breaks = {}
sort_dict = {}
for item in data:
start_date_obj = datetime.datetime.strptime(item['startTime'], "%Y-%m-%dT%H:%M:%S")
if item['isBreak']:
breaks[item['id']] = item
breaks[item['id']]['endTime'] = start_date_obj + datetime.timedelta(minutes=item['durationEstimated'])
else:
original_data_in_dict_form[item['id']] = item
original_data_in_dict_form[item['id']]['endTime'] = start_date_obj + datetime.timedelta(minutes=item['durationEstimated'])
for break_id in breaks:
for original_id in original_data_in_dict_form:
if breaks[break_id]['startTime'] > original_data_in_dict_form[original_id]['startTime'] and breaks[break_id]['endTime'] < original_data_in_dict_form[original_id]['endTime']:
original_data_in_dict_form[original_id]['endTime'] += datetime.timedelta(minutes=breaks[break_id]['durationEstimated'])
if original_id not in sort_dict:
sort_dict[original_id] = original_data_in_dict_form[original_id]['endTime']
for original_id, end_time in sorted(sort_dict.items(), key=lambda p: p[1], reverse=False):
new_data.append(original_data_in_dict_form[original_id])
print(new_data)

endTime上排序,这显然可以转换为其他内容。这很可能是非常低效的,但可能会让你继续前进。

在Torxed答案的帮助下,我成功地使它工作起来。

首先,我循环浏览每个项目并设置endTime

items = items.map(item => {
item.startTime = new Date(item.startTime);
const endTime = new Date(item.startTime);
endTime.setMinutes(endTime.getMinutes() + item.durationEstimated);
item.endTime = endTime;
return item;
});

接下来,我过滤掉real*"和**break项目到数组中

const realItems = items.filter(x => !x.break);
const breakItems = items.filter(x => x.break);

循环通过所有realItems

从以前的值设置startTimeendTime

获取项目startTime+持续时间=endTime

realItems.forEach((realItem, index) => {
if (index !== 0) {
realItem.startTime = new Date(realItems[index - 1].endTime);
const endTime = new Date(new Date(realItem.startTime));
endTime.setMinutes(endTime.getMinutes() + realItem.durationEstimated);
realItem.endTime = endTime;
} else {
realItem.startTime = new Date(realItem.startTime);
const endTime = new Date(new Date(realItem.startTime));
endTime.setMinutes(endTime.getMinutes() + realItem.durationEstimated);
realItem.endTime = endTime;
}
});

接下来,我循环浏览breakItems,并检查项目的endTime是否为>=break的starttime。在这种情况下,我在第一个响应之后循环所有项目,并将中断的持续时间添加到项目的startTime/endTime中。

for (const breakItem of breakItems) {
const breakStart = new Date(breakItem.startTime).getTime();
for (let x = 0; x < realItems.length; x++) {
const realItem = realItems[x];
const realEnd = new Date(realItem.endTime).getTime();
if (realEnd >= breakStart + realItem.durationEstimated * 60000) {
const items = realItems.slice(x, realItems.length);
for (const item of items) {
item.startTime = new Date(item.startTime);
item.startTime.setMinutes(item.startTime.getMinutes() + breakItem.durationEstimated);
item.startTime = item.startTime;
item.endTime = new Date(item.endTime);
item.endTime.setMinutes(item.endTime.getMinutes() + breakItem.durationEstimated);
item.endTime = item.endTime;
}
break;
}
}
}

最新更新