Reputation: 49
I am trying to make a command that counts the time between 2 commands. Example: !start
(save the current time) - !end
(saves the current time and get the difference between 2 commands). The export format of the latest time wants to be an embed that contains something like this: "Your time: 1:45:32 (hours:minutes:seconds)"
.
Here is my code:
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)
}
});
The message that this code sends is "NaN"
Upvotes: 1
Views: 734
Reputation: 14088
The bot is responding with NaN
(which stands for Not a Number) probably because startDate
is undefined
, which means:
new Date(startDate)
is an invalid datenew Date(startDate).getTime()
is NaN
new Date(startDate).getTime() - new Date(endDate).getTime()
is NaN
(NaN - anything
is always NaN
)result
, which is NaN
, gets coerced to a string and the message 'NaN'
is sent.What most likely happened is that a user sent !end
before !start
, so startDate
is uninitialised.
To fix this, check if startDate
is defined before continuing with the !end
command:
if (message.content == "!end") {
if (!startDate) return message.reply('Use !start first')
// rest of code...
}
For more information on NaN
, see NaN
on MDN.
Some other things:
new Date(startDate)
or new Date(endDate)
; startDate
and endDate
are already Date
s.!start
and then !end
. What happens if someone sends
!end
again? The bot would respond with the time since the !start
to the last !end
, which is probably unintended. You might want to set startDate
to undefined
after the !end
command to reset it.!start
in one channel and !end
in another). If you don't want this, you could try storing the dates in something like a Map
keyed by the channel IDs. (EDIT: it would probably be better to keep the timers unique per user, not per channel.)Here's how I would implement it:
/**
* 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)
}
})
Upvotes: 4