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

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库可以省去手动写格式化逻辑的步骤,自动适配多语言:

  1. 先安装库:pip install humanize
  2. 示例用法:
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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 18:54:03