聊天页面,按时间间隔对聊天数据分组

聊天页面中,可以通过按时间间隔(如每 5 分钟、每小时、每天等)对聊天数据分组。

  • 枚举:定义分组粒度类型

/// 聊天消息的分组粒度
enum ChatGroupInterval {
    /// 每 5 分钟一组
    case fiveMinutes
    
    /// 每 30 分钟一组
    case thirtyMinutes
    
    /// 每小时一组
    case hourly
    
    /// 每天一组
    case daily

    /// 对应的时间间隔(秒)
    var timeInterval: TimeInterval {
        switch self {
        case .fiveMinutes: return 5 * 60
        case .thirtyMinutes: return 30 * 60
        case .hourly: return 60 * 60
        case .daily: return 24 * 60 * 60
        }
    }
}

  • 分组方法:对 [ChatMessage] 按指定规则进行分组

1、分组逻辑:

每条消息的 create_time 会与当前组内最后一条消息的时间进行比较。如果两者的时间差超过指定的间隔(例如,10分钟),就开始一个新的分组。

2、每组的 groupDate:

每组的 groupDate 应该是该组内第一条消息的时间。

extension Array where Element == MessageModel {
    /// 按时间间隔进行分组
    func grouped(by interval: ChatGroupInterval) -> [(groupDate: Date, messages: [MessageModel])] {
        var result: [(Date, [MessageModel])] = []
        var currentGroup: [MessageModel] = []
        var lastMessageDate: Date?

        for message in self.sorted(by: { $0.create_time.toDate(region: .local)! < $1.create_time.toDate(region: .local)! }) {
            // 获取消息的时间
            guard let messageDateInRegion = message.create_time.toDate(region: .local) else { continue }
            let messageDate = messageDateInRegion.date
            
            // 判断当前消息与上条消息的时间差
            if let lastDate = lastMessageDate {
                let timeDifference = messageDate.timeIntervalSince(lastDate)
                if timeDifference > interval.timeInterval {
                    // 时间差超过间隔,创建新分组
                    if !currentGroup.isEmpty {
                        result.append((currentGroup.first!.create_time.toDate(region: .local)!.date, currentGroup))
                    }
                    currentGroup = [message]
                } else {
                    // 时间差未超过间隔,继续添加到当前分组
                    currentGroup.append(message)
                }
            } else {
                // 这是第一条消息,直接加入
                currentGroup.append(message)
            }
            
            // 更新 lastMessageDate 为当前消息时间
            lastMessageDate = messageDate
        }

        // 将最后一个分组添加到结果
        if !currentGroup.isEmpty {
            result.append((currentGroup.first!.create_time.toDate(region: .local)!.date, currentGroup))
        }

        return result
    }
}

extension Array where Element == (groupDate: Date, messages: [MessageModel]) {
    /// 将新消息添加到现有分组中,并返回是否新建分组
    /// - Parameters:
    ///   - message: 消息
    ///   - interval: 聊天消息的分组粒度
    /// - Returns: 返回是否新建分组
    mutating func addMessage(_ message: MessageModel, interval: ChatGroupInterval) -> Bool? {
        guard let messageDateInRegion = message.create_time.toDate(region: .local) else { return nil }
        let messageDate = messageDateInRegion.date // 将 DateInRegion 转换为 Date
        PrintLog(message: messageDate)
        // 如果当前有分组
        if let lastGroupIndex = self.lastIndex(where: { messageDate.timeIntervalSince($0.groupDate) <= interval.timeInterval }) {
            // 获取分组最后一条消息的时间
            let lastMessageDate = self[lastGroupIndex].groupDate
            PrintLog(message: lastMessageDate)
            // 判断当前消息与上条消息的时间差
            let timeDifference = messageDate.timeIntervalSince(lastMessageDate)
            PrintLog(message: timeDifference)
            if timeDifference > interval.timeInterval {
                //时间差超过间隔,创建新的分组,groupDate 为该消息时间
                self.append((messageDate, [message]))
                return true
            } else {
                // 时间差未超过间隔,继续添加到最后分组
                self[lastGroupIndex].messages.append(message)
                return false
            }
            
        } else {
            // 创建新的分组,groupDate 为该消息时间
            self.append((messageDate, [message]))
            return true
        }
    }
}

示例模型和调用方式

/// 聊天消息模型
struct ChatMessage {
    let id: UUID
    let text: String
    let timestamp: Date
    let senderId: String
}

// 示例使用:按 30 分钟分组
let messages: [ChatMessage] = [...] // 假设你已经有消息数组
let groups = messages.grouped(by: .thirtyMinutes)

// 打印分组结果
for group in groups {
    print("时间段:\(group.groupDate)")
    for msg in group.messages {
        print("  - \(msg.text)")
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容