如何将time.time()结果转换为小时和分钟并写入数据库?
解决Discord机器人语音时长计算与格式化写入数据库问题
你的代码存在一个关键问题:t1 是函数内的局部变量,用户进入语音频道后函数执行完毕,t1 的值会被销毁,等用户退出语音时 t1 又会被重新初始化为0,导致无法正确计算实际语音时长。需要把用户的语音开始时间存储在跨事件可保留的位置,比如Cog类的属性中。
同时,将秒数转换为小时+分钟格式可通过对总秒数做整除、取余运算实现。下面是修正后的完整代码:
import time from discord.ext import commands class VoiceTracker(commands.Cog): def __init__(self, bot): self.bot = bot # 用字典存储用户语音开始时间,键为 (成员ID, 服务器ID),避免不同服务器的同一用户数据冲突 self.voice_start_times = {} @commands.Cog.listener() async def on_voice_state_update(self, member, before, after): async with self.bot.db.cursor() as cursor: # 获取用户当前累计语音时长记录 await cursor.execute("SELECT voicetime FROM users WHERE member_id = ? AND guild_id = ?", (member.id, member.guild.id)) voicetime_record = await cursor.fetchone() current_total = voicetime_record[0] if voicetime_record else 0 # 用户从无频道进入有频道(加入语音) if before.channel is None and after.channel is not None: self.voice_start_times[(member.id, member.guild.id)] = time.time() # 用户从有频道退出到无频道(离开语音) elif before.channel is not None and after.channel is None: # 取出对应开始时间,不存在则跳过计算 start_time = self.voice_start_times.pop((member.id, member.guild.id), None) if not start_time: return # 计算本次语音总秒数 total_seconds = time.time() - start_time # 转换为小时+分钟格式 hours = int(total_seconds // 3600) minutes = int((total_seconds % 3600) // 60) formatted_duration = f"{hours}小时{minutes}分钟" # 写入数据库(两种存储方式二选一) # 方式1:存储格式化后的字符串(需确保voicetime字段为TEXT类型) await cursor.execute("UPDATE users SET voicetime = ? WHERE member_id = ? AND guild_id = ?", (formatted_duration, member.id, member.guild.id)) # 方式2:推荐存储总秒数(字段为INT/FLOAT),后续显示时再格式化,便于数值运算 # await cursor.execute("UPDATE users SET voicetime = voicetime + ? WHERE member_id = ? AND guild_id = ?", # (total_seconds, member.id, member.guild.id)) await self.bot.db.commit() def setup(bot): bot.add_cog(VoiceTracker(bot))
核心说明:
- 新增
self.voice_start_times字典存储用户语音起始时间,用(成员ID, 服务器ID)作为键,避免跨服务器的用户数据混乱。 - 时长转换逻辑:总秒数整除3600得到小时数,剩余秒数整除60得到分钟数。
- 数据库存储建议:优先选择存储总秒数,数值类型更便于后续的累加、排序、统计等操作,需要展示时再转换为小时分钟格式。
内容的提问来源于stack exchange,提问作者haseryu
相关产品推荐
相关产品推荐

