discord.py中如何在事件结束时输出「已结束X秒/几小时前」类相对时间提示
实现方案
你可以通过计算活动结束时间与当前时间的差值,结合定时更新Embed的逻辑实现相对时间提示,以下是两种可行实现方式:
方案1:原生Python实现(无需第三方依赖)
无需安装额外库,直接通过Python内置的datetime模块计算时间差并格式化输出。
步骤1:编写相对时间格式化函数
from datetime import datetime, timedelta def format_relative_time(end_time: datetime) -> str: now = datetime.utcnow() delta = end_time - now total_seconds = int(delta.total_seconds()) # 活动未结束场景 if total_seconds > 0: if total_seconds < 60: return f"Ends in {total_seconds} 秒" elif total_seconds < 3600: minutes = total_seconds // 60 return f"Ends in {minutes} 分钟" elif total_seconds < 86400: hours = total_seconds // 3600 return f"Ends in {hours} 小时" else: days = total_seconds // 86400 return f"Ends in {days} 天" # 活动已结束场景 else: total_seconds = abs(total_seconds) if total_seconds < 60: return f"Ended {total_seconds} 秒前" elif total_seconds < 3600: minutes = total_seconds // 60 return f"Ended {minutes} 分钟前" elif total_seconds < 86400: hours = total_seconds // 3600 return f"Ended {hours} 小时前" else: days = total_seconds // 86400 return f"Ended {days} 天前"
步骤2:添加定时更新Embed的任务
使用discord.py内置的tasks模块实现定时更新,让相对时间自动刷新:
from discord.ext import tasks # 定义定时更新任务,每30秒刷新一次 @tasks.loop(seconds=30) async def update_event_embed(msg_id: int, end_time: datetime, title: str, winners: int): try: msg = await ctx.fetch_message(msg_id) except: # 消息已被删除则停止任务 update_event_embed.stop() return relative_time = format_relative_time(end_time) # 构建新的Embed emb = discord.Embed(title=f"**{title}**", description=f"<:854745395314163784:910908229897297940> {relative_time}") emb.set_thumbnail(url='你的缩略图地址') emb.set_footer(text = f"{winners} Winner") await msg.edit(embed=emb) # 活动结束超过1天自动停止更新,节省资源 if (datetime.utcnow() - end_time).total_seconds() > 86400: update_event_embed.stop()
步骤3:修改原有发消息逻辑
在发送完初始Embed后启动更新任务:
emb = discord.Embed(title=f"**{title}**", description=f"<:854745395314163784:910908229897297940> 即将开始") emb.set_thumbnail(url='你的缩略图地址') emb.set_footer(text = f"{winners} Winner") msg_2 = await ctx.send(embed=emb) await msg_2.add_reaction(emoji) created = msg_2.created_at # 计算活动结束时间,假设lenght为活动持续秒数 end_time = created + timedelta(seconds=lenght) # 启动更新任务 update_event_embed.start(msg_2.id, end_time, title, winners)
方案2:使用humanize库简化开发
如果可以安装第三方依赖,使用humanize库可以省去手动写格式化逻辑的步骤,自动适配多语言:
- 先安装库:
pip install humanize - 示例用法:
import humanize import locale # 配置为中文输出 locale.setlocale(locale.LC_ALL, 'zh_CN.UTF-8') # 直接替换format_relative_time函数的逻辑即可 delta = end_time - datetime.utcnow() if delta.total_seconds() > 0: relative_time = f"Ends in {humanize.naturaldelta(delta)}" else: relative_time = f"Ended {humanize.naturaldelta(abs(delta))} 前"
注意事项
- 所有时间计算统一使用UTC时区,避免时区差异导致的时间计算错误
- 定时更新的间隔可根据需求调整,短时长活动可以设为10秒更新一次,长时长活动设为1-5分钟更新一次即可
- 消息被删除或活动结束后及时停止更新任务,避免不必要的资源消耗
内容的提问来源于stack exchange,提问作者Hiresh Verma
相关产品推荐
相关产品推荐

