You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何生成避开指定时段的可用TimeSlot列表(Kotlin)

需求与问题

需要实现一个功能:生成从起始时间到结束时间的可用TimeSlot列表,需自动避开指定的休息时段。例如:起始时间09:00、结束时间17:00,每个时段15分钟,避开12:00-12:30,最终列表应包含09:00到12:00的所有15分钟时段,以及12:30到17:00的所有15分钟时段。

我使用java.time.LocalTime编写了Kotlin代码,但运行效果不符合预期,代码如下:

现有代码

TimeSlot数据类

data class TimeSlot(
    val startTime: LocalTime,
    val endTime: LocalTime,
)

时段生成函数

private fun initializeSlots(
    slots: ArrayList<TimeSlot>,
    startTimeShift: LocalTime,
    appointmentDuration: Long,
    amountOfWorkingHours: Long,
    breakTime: LocalTime,
    breakDuration: Long
) {
    slots.add(TimeSlot(startTime = startTimeShift, endTime = startTimeShift.plusMinutes(appointmentDuration)))
    val possibleTotalAppointments = (amountOfWorkingHours * appointmentDuration) - 2 // -2 because index starts at 0 and first timeslot is already added.
    for (i in 0..(amountOfWorkingHours * appointmentDuration).toInt()) {
        if (slots[i].endTime == breakTime) {
            val endTimeOfBreak = breakTime.plusMinutes(breakDuration)
            val isTargetWithinTimeFrame = (!breakTime.isBefore(slots[i].startTime) && breakTime.isBefore(endTimeOfBreak))
            if (isTargetWithinTimeFrame) {
                slots.remove(slots[i])
                continue
            }
        } else {
            slots.add(TimeSlot(startTime = slots[i].endTime, endTime = slots[i].endTime.plusMinutes(appointmentDuration)))
        }
    }
}

现有代码的问题

  1. 循环逻辑错误:用amountOfWorkingHours * appointmentDuration作为循环上限完全不合理,无法准确计算实际应生成的时段数量,会导致生成过多或过少的时段。
  2. 休息时段处理逻辑缺陷:仅判断slots[i].endTime == breakTime过于死板,若休息时间不是刚好卡在某个时段的结束时间,就无法正确识别并跳过;且删除列表元素后继续循环会引发索引越界问题。
  3. 参数设计不合理:使用amountOfWorkingHours不如直接传入结束时间,既直观又能避免因工时计算导致的误差。

优化后的代码

调整参数为更直观的起始/结束时间,同时优化时段生成与休息跳过逻辑:

data class TimeSlot(
    val startTime: LocalTime,
    val endTime: LocalTime,
)

private fun generateAvailableSlots(
    startTime: LocalTime,
    endTime: LocalTime,
    slotDurationMinutes: Long,
    breakStartTime: LocalTime,
    breakDurationMinutes: Long
): List<TimeSlot> {
    val slots = mutableListOf<TimeSlot>()
    val breakEndTime = breakStartTime.plusMinutes(breakDurationMinutes)
    var currentTime = startTime

    // 循环生成时段,直到当前时段结束时间超过工作结束时间
    while (currentTime.plusMinutes(slotDurationMinutes) <= endTime) {
        val nextSlotEnd = currentTime.plusMinutes(slotDurationMinutes)
        
        // 检查当前时段是否与休息时段重叠
        val overlapsWithBreak = currentTime < breakEndTime && nextSlotEnd > breakStartTime
        
        if (overlapsWithBreak) {
            // 跳过休息时段,直接将当前时间设置为休息结束时间
            currentTime = breakEndTime
        } else {
            slots.add(TimeSlot(currentTime, nextSlotEnd))
            currentTime = nextSlotEnd
        }
    }
    return slots
}

代码说明

  • 通过while循环逐步推进当前时间,确保每个时段都在工作时间范围内。
  • 每次生成时段前检查是否与休息时段重叠,重叠则直接跳到休息结束时间,避免生成无效时段。
  • 参数设计更清晰,直接传入工作开始/结束时间,减少不必要的计算和错误。

内容的提问来源于stack exchange,提问作者xBullet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 18:05:18