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

求助:用Swift实现员工登录日志中空闲时段查询功能

解决Swift中找出门店空闲时段的问题

别担心,这个问题其实可以拆成几个清晰的小步骤来解决,我来一步步带你实现这个功能:

第一步:定义数据模型

首先我们需要把JSON里的员工登录记录和门店营业时间转换成Swift可以处理的数据结构。假设你的JSON结构大概是这样的:

{
  "employees": [
    {"id": 1, "loginTime": "2024-05-20T09:30:00", "logoutTime": "2024-05-20T12:00:00"},
    {"id": 2, "loginTime": "2024-05-20T11:00:00", "logoutTime": "2024-05-20T14:30:00"}
  ],
  "storeHours": {"openTime": "2024-05-20T08:00:00", "closeTime": "2024-05-20T18:00:00"}
}

我们可以定义对应的Swift结构体,同时处理日期解析:

import Foundation

// 员工登录记录模型
struct EmployeeLog: Codable {
    let id: Int
    let loginTime: Date
    let logoutTime: Date
}

// 门店营业时间模型
struct StoreHours: Codable {
    let openTime: Date
    let closeTime: Date
}

// 自定义日期解码器,处理JSON中的日期格式
let dateFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
    formatter.timeZone = TimeZone.current // 根据实际需求调整时区
    return formatter
}()

let jsonDecoder: JSONDecoder = {
    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .formatted(dateFormatter)
    return decoder
}()

第二步:合并所有员工的登录时段

因为多个员工的登录时段可能重叠,我们需要先把所有有人在岗的时段合并成不重叠的连续区间,这样后续找空闲时段会更简单。

实现合并逻辑的函数:

/// 合并重叠或相邻的时间区间
/// - Parameter intervals: 原始的时间区间数组(每个元素是(开始时间, 结束时间))
/// - Returns: 合并后的不重叠时间区间数组
func mergeOverlappingIntervals(_ intervals: [(start: Date, end: Date)]) -> [(start: Date, end: Date)] {
    guard !intervals.isEmpty else { return [] }
    
    // 先按开始时间排序
    let sortedIntervals = intervals.sorted { $0.start < $1.start }
    
    var mergedIntervals = [sortedIntervals[0]]
    
    for current in sortedIntervals.dropFirst() {
        guard let last = mergedIntervals.last else { continue }
        
        if current.start <= last.end {
            // 当前区间和最后一个合并区间重叠,合并它们
            let newEnd = max(last.end, current.end)
            mergedIntervals[mergedIntervals.count - 1] = (start: last.start, end: newEnd)
        } else {
            // 没有重叠,直接添加
            mergedIntervals.append(current)
        }
    }
    
    return mergedIntervals
}

第三步:计算空闲时段

有了合并后的在岗时段,我们就可以和门店营业时间对比,找出中间的空闲区间:

/// 计算门店的空闲时段
/// - Parameters:
///   - employeeLogs: 所有员工的登录记录数组
///   - storeHours: 门店营业时间
/// - Returns: 空闲时段数组(每个元素是(开始时间, 结束时间))
func calculateIdlePeriods(employeeLogs: [EmployeeLog], storeHours: StoreHours) -> [(start: Date, end: Date)] {
    // 1. 提取所有员工的登录时段
    let workIntervals = employeeLogs.map { (start: $0.loginTime, end: $0.logoutTime) }
    
    // 2. 合并重叠的在岗时段
    let mergedWorkIntervals = mergeOverlappingIntervals(workIntervals)
    
    var idlePeriods = [(start: Date, end: Date)]()
    var currentTime = storeHours.openTime
    
    // 3. 遍历合并后的在岗时段,找出中间的空闲区间
    for interval in mergedWorkIntervals {
        if currentTime < interval.start {
            // 门店开门到第一个员工登录之间的空闲
            idlePeriods.append((start: currentTime, end: interval.start))
        }
        currentTime = max(currentTime, interval.end)
    }
    
    // 4. 最后一个员工离岗到门店关门之间的空闲
    if currentTime < storeHours.closeTime {
        idlePeriods.append((start: currentTime, end: storeHours.closeTime))
    }
    
    return idlePeriods
}

第四步:调用示例

假设你已经把JSON解析成了对应的模型,就可以这样调用:

// 示例:解析JSON数据(这里用模拟数据代替实际JSON)
let sampleJson = """
{
  "employees": [
    {"id": 1, "loginTime": "2024-05-20T09:30:00", "logoutTime": "2024-05-20T12:00:00"},
    {"id": 2, "loginTime": "2024-05-20T11:00:00", "logoutTime": "2024-05-20T14:30:00"},
    {"id": 3, "loginTime": "2024-05-20T15:00:00", "logoutTime": "2024-05-20T17:00:00"}
  ],
  "storeHours": {"openTime": "2024-05-20T08:00:00", "closeTime": "2024-05-20T18:00:00"}
}
""".data(using: .utf8)!

do {
    // 更规范的方式是定义一个包含employees和storeHours的根结构体,这里为了简化用了动态解析
    let rootObject = try JSONSerialization.jsonObject(with: sampleJson) as! [String: Any]
    let employeesData = try JSONSerialization.data(withJSONObject: rootObject["employees"]!)
    let storeHoursData = try JSONSerialization.data(withJSONObject: rootObject["storeHours"]!)
    
    let employees = try jsonDecoder.decode([EmployeeLog].self, from: employeesData)
    let storeHours = try jsonDecoder.decode(StoreHours.self, from: storeHoursData)
    
    let idlePeriods = calculateIdlePeriods(employeeLogs: employees, storeHours: storeHours)
    
    // 打印空闲时段
    for period in idlePeriods {
        print("空闲时段:\(dateFormatter.string(from: period.start)) 到 \(dateFormatter.string(from: period.end))")
    }
} catch {
    print("解析错误:\(error)")
}

额外注意点

  • 时区问题:一定要确保日期解析和处理时使用正确的时区,避免出现时间偏差。
  • 边界情况:比如没有任何员工登录,那整个营业时间都是空闲时段;或者员工覆盖了整个营业时间,那没有空闲时段。上面的函数已经处理了这些情况。
  • 日期有效性:可以额外添加验证,比如员工的登录时间不能晚于登出时间,不能超出门店营业时间等,让函数更健壮。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:43:36