Discord.py中实现等待合法DateTime格式回复的问题求助
解决方案
现有代码的核心问题如下:
dateutil.parser.parse解析格式错误的字符串时会直接抛出ParserError异常,你没有做异常捕获,因此输入不合法时会直接报错而非返回校验结果wait_for的check函数仅支持返回布尔值用来判断是否匹配输入,本身无法执行发消息这类异步操作,自然没法输出错误提示
优化实现思路
- 把日期格式、时间范围的校验逻辑从
check函数中剥离,check仅用来校验输入的发送者和频道是否匹配 - 拿到用户输入后单独做解析校验,捕获解析异常、时间不合法的情况,主动发送对应错误提示
- 可选添加重试次数限制,避免用户无限输错占用流程
- 解析时优先使用指定格式匹配,避免
dateutil模糊解析出现日月颠倒的问题
完整代码示例
import asyncio from datetime import datetime from dateutil.parser import parse from dateutil.parser import ParserError @commands.command(name='Due', brief="", description="Add an item that's due") @commands.cooldown(1, 2) async def add_due(self, ctx, *, message): await ctx.send("When is it due? (DD/MM/YYYY HH:MM:SS) \n NB: Time is optional") # 最多允许重试3次,可根据需求调整 retry_count = 3 due = None def check(m): # check仅做基础身份和频道校验,不处理业务逻辑 return m.author == ctx.author and m.channel == ctx.channel while retry_count > 0: try: msg = await self.bot.wait_for("message", check=check, timeout=30) # 尝试解析日期 try: # 先按指定格式严格解析,避免日月顺序混淆 # 先尝试带时间的格式 try: input_time = datetime.strptime(msg.content, "%d/%m/%Y %H:%M:%S") except ValueError: # 再尝试不带时间的格式 input_time = datetime.strptime(msg.content, "%d/%m/%Y") except ValueError: # 如果需要兼容其他非标准格式,可保留dateutil解析作为兜底 try: input_time = parse(msg.content, dayfirst=True) # 明确指定日在前,避免解析错误 except ParserError: retry_count -= 1 await ctx.send(f"日期格式错误,请按照DD/MM/YYYY HH:MM:SS格式输入,你还有{retry_count}次重试机会") continue # 校验是否为未来时间 if input_time <= datetime.now(): retry_count -= 1 await ctx.send(f"输入的时间必须是未来时间,你还有{retry_count}次重试机会") continue # 所有校验通过 due = input_time break except asyncio.TimeoutError: await ctx.send("等待输入超时,命令已终止") return if not due: await ctx.send("重试次数耗尽,命令已终止") return # 后续业务逻辑,这里的due就是校验通过的时间对象 await ctx.send(f"已成功设置截止时间为:{due.strftime('%d/%m/%Y %H:%M:%S')}")
额外说明
- 优先用
strptime严格匹配你要求的输入格式,比无限制的模糊解析可靠性更高,可根据你的实际需求调整允许的输入格式 - 不需要dateutil兼容的话可以直接去掉相关的兜底解析逻辑,减少不必要的依赖
内容的提问来源于stack exchange,提问作者nablue
相关产品推荐
相关产品推荐

