时间计数器命令在 discord.js 中给出 NaN

Time Counter Command giving NaN in discord.js

我正在尝试制作一个计算两个命令之间的时间的命令。示例:!start(保存当前时间)- !end(保存当前时间并获取 2 个命令之间的差异)。最近一次的导出格式希望是一个包含如下内容的嵌入:"Your time: 1:45:32 (hours:minutes:seconds)"。 这是我的代码:

    bot.on("message", (message) => {


        var startDate;

        if (message.content == "!start") {
            startDate = new Date();

            console.log(new Date(startDate).getTime())

            message.reply("works");
        }

        if (message.content == "!end") {
            let endDate = new Date();

            
            console.log(new Date(endDate).getTime())


            let result = new Date(startDate).getTime() - new Date(endDate).getTime();


            message.reply(result)
        }
    });

此代码发送的消息是“NaN”

机器人正在响应 NaN(代表 Not a N数)可能是因为 startDateundefined,这意味着:

  • new Date(startDate) 是无效日期
  • new Date(startDate).getTime()NaN
  • new Date(startDate).getTime() - new Date(endDate).getTime()NaNNaN - anything 总是 NaN
  • result,即 NaN,被强制转换为一个字符串并发送消息 'NaN'

最有可能发生的情况是用户在 !start 之前发送了 !end,因此 startDate 未初始化。

要解决此问题,请在继续执行 !end 命令之前检查是否定义了 startDate

if (message.content == "!end") {
    if (!startDate) return message.reply('Use !start first')

    // rest of code...
}

有关 NaN 的详细信息,请参阅 NaN on MDN


一些其他的事情:

  • 您不需要使用 new Date(startDate)new Date(endDate)startDateendDate 已经是 Date
  • 假设有人发送 !start 然后 !end。如果有人发送会发生什么 又是!end?机器人会响应从 !start 到最后一个 !end 的时间,这可能是无意的。您可能希望在 !end 命令后将 startDate 设置为 undefined 以重置它。
  • 此命令跨频道工作(有人可以在一个频道中发送 !start 而在另一个频道中发送 !end)。如果您不想这样,您可以尝试将日期存储在类似 Map 的内容中,由频道 ID 键入。 (编辑:最好让每个用户的计时器保持唯一,而不是每个频道。)

以下是我的实现方式:

/**
 * A map from user IDs to start timestamps
 * @type Map<string, number>
 */
const startTimestamps = new Map()

/**
 * Pads a number to 2 digits.
 * @param {number} value
 * @returns {string}
 */
const pad2Digits = value => String(value).padStart(2, '0')

bot.on('message', async message => {
  try {
    if (message.content === '!start') {
      // Sets the start time. This overrides any existing timers
      // Date.now() is equivalent to new Date().getTime()
      startTimestamps.set(message.author.id, Date.now())
      await message.reply('Timer started.')
    } else if (message.content === '!end') {
      if (startTimestamps.has(message.author.id)) {
        // The user has an existing timer to stop
        // Calculate the timer result
        const ms = Date.now() - startTimestamps.get(message.author.id)
        const totalSecs = Math.floor(ms / 1000)
        const totalMins = Math.floor(totalSecs / 60)
        const hrs = Math.floor(totalMins / 60)
        const mins = totalMins % 60
        const secs = totalSecs % 60
        // Reply with result
        await message.reply(`Your time: ${hrs}:${pad2Digits(mins)}:${pad2Digits(secs)}`)
        // Remove timestamp from map
        startTimestamps.delete(message.author.id)
      } else {
        // The user does not have an existing timer
        await message.reply('You need to use `!start` first!')
      }
    }
  } catch (error) {
    console.error(error)
  }
})