如何在Discord机器人中用“days ago”格式显示用户日期?
解决Discord机器人中日期转“距今天数”的时区问题
问题核心
你在开发Discord机器人时,想要将用户的账号创建日期、服务器加入日期从格式化日期改为“距今天数”格式,但计算时间差时因时区不匹配报错——Discord返回的user.created_at和user.joined_at是带UTC时区的datetime对象,而你用的datetime.now()是本地无时区的,两者无法直接相减,即使移除时区感知也会导致计算偏差。
解决方案
统一使用UTC时区计算时间差(Discord的所有时间戳均基于UTC),封装一个辅助函数处理时间差转换,替换原代码中的日期显示逻辑即可。
辅助函数示例
from datetime import datetime, timezone def get_time_ago(target_time): utc_now = datetime.now(timezone.utc) duration = utc_now - target_time total_seconds = int(duration.total_seconds()) days, remainder = divmod(total_seconds, 86400) hours, remainder = divmod(remainder, 3600) minutes, seconds = divmod(remainder, 60) # 根据时间差大小自动选择显示单位 if days > 0: return f"{days}天前" elif hours > 0: return f"{hours}小时前" elif minutes > 0: return f"{minutes}分钟前" else: return f"{seconds}秒前"
修改后的完整机器人代码
import discord from datetime import datetime, timezone from discord.ext import commands intents = discord.Intents.all() bot = commands.Bot(command_prefix='.', intents=intents) def get_time_ago(target_time): utc_now = datetime.now(timezone.utc) duration = utc_now - target_time total_seconds = int(duration.total_seconds()) days, remainder = divmod(total_seconds, 86400) hours, remainder = divmod(remainder, 3600) minutes, seconds = divmod(remainder, 60) if days > 0: return f"{days}天前" elif hours > 0: return f"{hours}小时前" elif minutes > 0: return f"{minutes}分钟前" else: return f"{seconds}秒前" @bot.event async def on_ready(): print("Ready!") @bot.command(name="user") async def user(ctx, user: discord.Member=None): user = user or ctx.author # 简化角色列表生成逻辑 rlist = [role.mention for role in user.roles if role.name != "@everyone"] b = ','.join(rlist) if rlist else "No roles" embed = discord.Embed(colour=user.color, timestamp=ctx.message.created_at) embed.set_author(name=f"User Info - {user}") embed.set_thumbnail(url=user.avatar.url) embed.set_footer(text=f'Requested by - {ctx.author}', icon_url=ctx.author.avatar.url) embed.add_field(name='ID:', value=user.id, inline=False) embed.add_field(name='Name:', value=user.display_name, inline=False) # 替换为时间差格式显示 embed.add_field(name='Created at:', value=get_time_ago(user.created_at), inline=False) embed.add_field(name='Joined at:', value=get_time_ago(user.joined_at), inline=False) embed.add_field(name='Bot?', value=user.bot, inline=False) embed.add_field(name=f'Roles:({len(rlist)})', value=b, inline=False) embed.add_field(name='Top Role:', value=user.top_role.mention, inline=False) await ctx.send(embed=embed)
关键说明
- 时区统一:用
datetime.now(timezone.utc)获取当前UTC时间,与Discord返回的UTC时区时间直接计算差值,彻底避免时区不匹配错误。 - 灵活显示:辅助函数会根据时间差自动选择最合理的显示单位,若只需固定显示天数,直接返回
f"{days}天前"即可。 - 代码优化:用列表推导式简化角色列表生成逻辑,提升代码可读性。
内容的提问来源于stack exchange,提问作者NuiDev
相关产品推荐
相关产品推荐

