本文目录导读:

我来帮你写一个日程冲突检测脚本,这里提供Python和JavaScript两个版本的实现。
Python 版本
from datetime import datetime, timedelta
from typing import List, Tuple, Optional
class Schedule:
"""日程类"""
def __init__(self, title: str, start_time: datetime, end_time: datetime):
self.title = title
self.start_time = start_time
self.end_time = end_time
def __repr__(self):
return f"{self.title}: {self.start_time.strftime('%H:%M')}-{self.end_time.strftime('%H:%M')}"
def detect_conflicts(schedules: List[Schedule]) -> List[Tuple[Schedule, Schedule]]:
"""
检测日程冲突
返回冲突的日程对列表
"""
# 按开始时间排序
sorted_schedules = sorted(schedules, key=lambda s: s.start_time)
conflicts = []
for i in range(len(sorted_schedules)):
for j in range(i + 1, len(sorted_schedules)):
# 如果日程i的结束时间大于日程j的开始时间,则冲突
if sorted_schedules[i].end_time > sorted_schedules[j].start_time:
conflicts.append((sorted_schedules[i], sorted_schedules[j]))
else:
# 因为已排序,后面的日程开始时间更晚,不会冲突
break
return conflicts
def find_available_slots(schedules: List[Schedule],
day_start: datetime,
day_end: datetime,
min_duration: timedelta = timedelta(minutes=30)) -> List[Tuple[datetime, datetime]]:
"""
查找空闲时间段
"""
sorted_schedules = sorted(schedules, key=lambda s: s.start_time)
available_slots = []
current_time = day_start
for schedule in sorted_schedules:
# 如果当前时间早于日程开始时间,中间有空闲
if current_time < schedule.start_time:
slot_duration = schedule.start_time - current_time
if slot_duration >= min_duration:
available_slots.append((current_time, schedule.start_time))
# 更新当前时间为日程结束时间和当前时间的较晚者
current_time = max(current_time, schedule.end_time)
# 检查最后一个日程到下班时间的空闲
if current_time < day_end:
slot_duration = day_end - current_time
if slot_duration >= min_duration:
available_slots.append((current_time, day_end))
return available_slots
# 使用示例
def main():
# 创建示例日程
schedules = [
Schedule("会议A", datetime(2024, 1, 1, 9, 0), datetime(2024, 1, 1, 10, 0)),
Schedule("会议B", datetime(2024, 1, 1, 9, 30), datetime(2024, 1, 1, 10, 30)),
Schedule("访谈C", datetime(2024, 1, 1, 11, 0), datetime(2024, 1, 1, 12, 0)),
Schedule("午餐D", datetime(2024, 1, 1, 12, 0), datetime(2024, 1, 1, 13, 0)),
Schedule("培训E", datetime(2024, 1, 1, 14, 0), datetime(2024, 1, 1, 15, 30)),
Schedule("汇报F", datetime(2024, 1, 1, 15, 0), datetime(2024, 1, 1, 16, 0)),
]
# 检测冲突
conflicts = detect_conflicts(schedules)
if conflicts:
print("检测到日程冲突:")
for s1, s2 in conflicts:
print(f" - {s1} 与 {s2} 冲突")
else:
print("没有检测到日程冲突")
# 查找空闲时间段
day_start = datetime(2024, 1, 1, 8, 0) # 上班时间
day_end = datetime(2024, 1, 1, 18, 0) # 下班时间
min_duration = timedelta(minutes=30) # 最少空闲30分钟
available_slots = find_available_slots(schedules, day_start, day_end, min_duration)
print(f"\n空闲时间段(最少{min_duration.seconds//60}分钟):")
for start, end in available_slots:
print(f" {start.strftime('%H:%M')} - {end.strftime('%H:%M')}")
if __name__ == "__main__":
main()
JavaScript 版本
class Schedule {
constructor(title, startTime, endTime) {
this.title = title;
this.startTime = new Date(startTime);
this.endTime = new Date(endTime);
}
toString() {
const formatTime = (date) => {
return date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });
};
return `${this.title}: ${formatTime(this.startTime)}-${formatTime(this.endTime)}`;
}
}
function detectConflicts(schedules) {
// 按开始时间排序
const sorted = [...schedules].sort((a, b) => a.startTime - b.startTime);
const conflicts = [];
for (let i = 0; i < sorted.length; i++) {
for (let j = i + 1; j < sorted.length; j++) {
if (sorted[i].endTime > sorted[j].startTime) {
conflicts.push([sorted[i], sorted[j]]);
} else {
break; // 后面不会冲突
}
}
}
return conflicts;
}
function findAvailableSlots(schedules, dayStart, dayEnd, minDurationMinutes = 30) {
const sorted = [...schedules].sort((a, b) => a.startTime - b.startTime);
const availableSlots = [];
let currentTime = new Date(dayStart);
for (const schedule of sorted) {
if (currentTime < schedule.startTime) {
const duration = (schedule.startTime - currentTime) / (1000 * 60);
if (duration >= minDurationMinutes) {
availableSlots.push({
start: new Date(currentTime),
end: new Date(schedule.startTime)
});
}
}
currentTime = new Date(Math.max(currentTime, schedule.endTime));
}
// 最后一个日程到结束时间
if (currentTime < dayEnd) {
const duration = (dayEnd - currentTime) / (1000 * 60);
if (duration >= minDurationMinutes) {
availableSlots.push({
start: new Date(currentTime),
end: new Date(dayEnd)
});
}
}
return availableSlots;
}
// 批量检测
function batchConflictCheck(schedules) {
const conflicts = detectConflicts(schedules);
if (conflicts.length > 0) {
console.log('检测到日程冲突:');
conflicts.forEach(([s1, s2]) => {
console.log(` - ${s1.toString()} 与 ${s2.toString()} 冲突`);
});
} else {
console.log('没有检测到日程冲突');
}
return conflicts;
}
// 使用示例
function main() {
const schedules = [
new Schedule('会议A', '2024-01-01T09:00', '2024-01-01T10:00'),
new Schedule('会议B', '2024-01-01T09:30', '2024-01-01T10:30'),
new Schedule('访谈C', '2024-01-01T11:00', '2024-01-01T12:00'),
new Schedule('午餐D', '2024-01-01T12:00', '2024-01-01T13:00'),
new Schedule('培训E', '2024-01-01T14:00', '2024-01-01T15:30'),
new Schedule('汇报F', '2024-01-01T15:00', '2024-01-01T16:00')
];
// 检测冲突
batchConflictCheck(schedules);
// 查找空闲时间
const dayStart = new Date('2024-01-01T08:00');
const dayEnd = new Date('2024-01-01T18:00');
const slots = findAvailableSlots(schedules, dayStart, dayEnd, 30);
if (slots.length > 0) {
console.log('\n空闲时间段(最少30分钟):');
slots.forEach(slot => {
console.log(` ${slot.start.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })} - ${slot.end.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })}`);
});
}
}
main();
高级功能版本
如果需要更复杂的检测功能,这里提供包含更多特性的版本:
from datetime import datetime, timedelta
from typing import List, Dict, Any
import json
class AdvancedScheduleManager:
"""高级日程管理器"""
def __init__(self):
self.schedules = []
def add_schedule(self, title: str, start: str, end: str,
priority: int = 0, attendees: List[str] = None):
"""添加日程"""
schedule = {
'title': title,
'start': datetime.fromisoformat(start),
'end': datetime.fromisoformat(end),
'priority': priority,
'attendees': attendees or [],
'duration': (datetime.fromisoformat(end) -
datetime.fromisoformat(start)).total_seconds() / 60
}
self.schedules.append(schedule)
def check_all_conflicts(self) -> Dict[str, Any]:
"""全面的冲突检测"""
conflicts = []
warnings = []
for i, s1 in enumerate(self.schedules):
for j, s2 in enumerate(self.schedules[i+1:], i+1):
# 时间冲突
if s1['start'] < s2['end'] and s2['start'] < s1['end']:
conflict_info = {
'type': '时间冲突',
'schedule1': s1,
'schedule2': s2,
'overlap_minutes': self._calc_overlap(s1, s2)
}
conflicts.append(conflict_info)
# 参会者冲突
common_attendees = set(s1['attendees']) & set(s2['attendees'])
if common_attendees and not self._is_time_conflict(s1, s2):
warnings.append({
'type': '参会者冲突',
'schedule1': s1,
'schedule2': s2,
'common_attendees': list(common_attendees)
})
return {
'total_schedules': len(self.schedules),
'conflicts': conflicts,
'warnings': warnings,
'has_conflicts': len(conflicts) > 0
}
def suggest_resolution(self) -> List[Dict[str, Any]]:
"""建议冲突解决方案"""
result = self.check_all_conflicts()
suggestions = []
for conflict in result['conflicts']:
s1, s2 = conflict['schedule1'], conflict['schedule2']
# 根据优先级建议
if s1['priority'] > s2['priority']:
suggestions.append({
'keep': s1['title'],
'reschedule': s2['title'],
'reason': f"{s1['title']} 优先级更高",
'current_overlap': f"{conflict['overlap_minutes']}分钟"
})
elif s2['priority'] > s1['priority']:
suggestions.append({
'keep': s2['title'],
'reschedule': s1['title'],
'reason': f"{s2['title']} 优先级更高",
'current_overlap': f"{conflict['overlap_minutes']}分钟"
})
else:
suggestions.append({
'type': '需要协商',
'schedule1': s1['title'],
'schedule2': s2['title'],
'reason': '两个日程优先级相同',
'overlap_minutes': conflict['overlap_minutes']
})
return suggestions
def _calc_overlap(self, s1: Dict, s2: Dict) -> float:
"""计算重叠分钟数"""
overlap_start = max(s1['start'], s2['start'])
overlap_end = min(s1['end'], s2['end'])
return max(0, (overlap_end - overlap_start).total_seconds() / 60)
def _is_time_conflict(self, s1: Dict, s2: Dict) -> bool:
"""检查是否有时间冲突"""
return s1['start'] < s2['end'] and s2['start'] < s1['end']
def export_json(self, filepath: str):
"""导出为JSON"""
data = []
for s in self.schedules:
data.append({
'title': s['title'],
'start': s['start'].isoformat(),
'end': s['end'].isoformat(),
'priority': s['priority'],
'attendees': s['attendees']
})
with open(filepath, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
# 使用示例
def advanced_demo():
manager = AdvancedScheduleManager()
# 添加日程
manager.add_schedule("重要客户会议", "2024-01-01T09:00", "2024-01-01T10:30",
priority=3, attendees=["张三", "李四", "王五"])
manager.add_schedule("团队周会", "2024-01-01T10:00", "2024-01-01T11:00",
priority=2, attendees=["张三", "李四"])
manager.add_schedule("项目评审", "2024-01-01T11:00", "2024-01-01T12:00",
priority=1, attendees=["王五"])
# 检测冲突
result = manager.check_all_conflicts()
print(f"总计 {result['total_schedules']} 个日程")
print(f"发现 {len(result['conflicts'])} 个时间冲突")
print(f"发现 {len(result['warnings'])} 个警告")
# 获取建议
suggestions = manager.suggest_resolution()
if suggestions:
print("\n解决建议:")
for s in suggestions:
print(f" - {s}")
# 运行示例
if __name__ == "__main__":
main() # 运行基础版
advanced_demo() # 运行高级版
使用建议
- 基础使用:直接用
main()函数测试基本的冲突检测 - 高级功能:使用
AdvancedScheduleManager进行更复杂的日程管理 - 自定义修改:可以根据需要修改:
- 冲突判断逻辑(如允许一定时间重叠)
- 时间格式
- 批量导入/导出功能
这个脚本可以用于日历应用、会议预订系统等场景。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播